Skip to content

Overview

The pipeline from a compiled module to a target program, with the public entry points. Every public name of the transpile package is importable from quivers.transpile; the names its leaf modules define are documented on their own pages (plan, IR, kernel IR, family metadata, family spelling, renderer registry), and the renderers on the renderers page. The constants and type aliases those modules define are listed here under their package path.

transpile

Transpile a compiled QVR module to other probabilistic-programming languages.

The pipeline is a didactic.api.Mapping composition of three arrows:

Module --Lower--> IRProgram --Renderer[T]--> panproto.Schema --emit_pretty--> bytes

Lower is target-independent; it elaborates the parsed module to its checked kernel module and derives the program's plan from its computation: an IRProgram carrying the module and the plan's nodes (sample, observe, marginalize, ...), each with the support / plate / argument shape read off the module's types, FAMILY_META, and torch.distributions.Distribution.arg_constraints.

Each target T has its own Renderer[T] subclass in quivers.transpile.renderers.<target>; the renderer consumes the IR and emits a target-specific panproto.Schema. The renderer's idiom (Stan's block structure, NumPyro's plate contexts, BUGS's row-loop relations) is the only place target-specific vocabulary lives.

Family-level facts (per-target distribution name, argument aliases) live in FAMILY_META; no renderer hardcodes family-name dispatch.

STAN_LIKE module-attribute

STAN_LIKE: frozenset[str] = frozenset({'object_decl', 'morphism_decl', 'define_decl', 'program_decl', 'export_decl'})

Statement kinds every PPL backend accepts.

The probabilistic-program surface: declarations and program bodies of sample, observe, let, score, return, and marginalize steps. It excludes categorical-algebra and neural-network declarations.

PYTHON_DEEP module-attribute

PYTHON_DEEP: frozenset[str] = STAN_LIKE | frozenset({'encoder_decl', 'decoder_decl'})

STAN_LIKE plus encoder and decoder declarations.

The tier of backends with a deep-learning idiom: Pyro and NumPyro modules.

CHURCH_LIKE module-attribute

CHURCH_LIKE: frozenset[str] = STAN_LIKE

The probabilistic subset Church and WebPPL accept.

The same kinds as STAN_LIKE; these targets realise marginalize as a continuation-style Infer or enumerate-query.

CATEGORICAL_METADATA_IGNORABLE module-attribute

CATEGORICAL_METADATA_IGNORABLE: frozenset[str] = frozenset({'category_decl', 'schema_decl', 'composition_decl', 'bundle_decl', 'rule_decl', 'contraction_decl', 'signature_decl', 'deduction_decl'})

Categorical declaration kinds the walker ignores beside a program_decl.

A module carrying only these declarations still raises UnsupportedConstruct naming them, so standalone categorical declarations remain rejected.

QIEC_SURFACE module-attribute

QIEC_SURFACE: frozenset[str] = frozenset({'index_decl', 'indexed_family_decl', 'effect_decl', 'effect_instance_decl', 'handler_decl', 'computation_decl'})

QIEC declaration kinds admitted once the shared boundary has checked the module.

These forms are first-class inputs to the structural IR and need no accompanying program_decl; each renderer applies its capability policy after lowering, where a diagnostic can name the computation and feature.

FAMILY_META module-attribute

FAMILY_META: dict[str, FamilyMeta] = {'Normal': FamilyMeta(qvr_name='Normal', distribution_class=td.Normal, quivers_class=ConditionalNormal, target_names={'stan': 'normal', 'numpyro': 'Normal', 'pyro': 'Normal', 'pymc': 'Normal', 'edward2': 'Normal', 'turing': 'Normal', 'gen': 'normal', 'church': 'gaussian', 'webppl': 'Gaussian', 'bugs': 'dnorm', 'jags': 'dnorm'}, arg_aliases={'bugs': {'scale': 'tau'}, 'jags': {'scale': 'tau'}, 'pymc': {'loc': 'mu', 'scale': 'sigma'}, 'webppl': {'loc': 'mu', 'scale': 'sigma'}}), 'LogitNormal': FamilyMeta(qvr_name='LogitNormal', distribution_class=_LogitNormal, quivers_class=ConditionalLogitNormal, target_names={'stan': 'logit_normal', 'numpyro': 'LogitNormal', 'pyro': 'LogitNormal', 'pymc': 'LogitNormal', 'edward2': 'LogitNormal'}, arg_aliases={'pymc': {'loc': 'mu', 'scale': 'sigma'}}), 'Beta': FamilyMeta(qvr_name='Beta', distribution_class=td.Beta, quivers_class=ConditionalBeta, target_names={'stan': 'beta', 'numpyro': 'Beta', 'pyro': 'Beta', 'pymc': 'Beta', 'edward2': 'Beta', 'turing': 'Beta', 'gen': 'beta', 'church': 'beta', 'webppl': 'Beta', 'bugs': 'dbeta', 'jags': 'dbeta'}, arg_aliases={'pymc': {'concentration1': 'alpha', 'concentration0': 'beta'}, 'webppl': {'concentration1': 'a', 'concentration0': 'b'}}), 'TruncatedNormal': FamilyMeta(qvr_name='TruncatedNormal', distribution_class=_TruncatedNormal, quivers_class=ConditionalTruncatedNormal, target_names={'numpyro': 'TruncatedNormal', 'pyro': 'TruncatedNormal', 'pymc': 'TruncatedNormal', 'edward2': 'TruncatedNormal', 'turing': 'truncated', 'gen': 'truncated_normal', 'stan': 'normal', 'bugs': 'dnorm', 'jags': 'dnorm'}, arg_aliases={'pymc': {'loc': 'mu', 'scale': 'sigma', 'low': 'lower', 'high': 'upper'}, 'bugs': {'scale': 'tau'}, 'jags': {'scale': 'tau'}}), 'Dirichlet': FamilyMeta(qvr_name='Dirichlet', event_rank=1, distribution_class=td.Dirichlet, quivers_class=ConditionalDirichlet, target_names={'stan': 'dirichlet', 'numpyro': 'Dirichlet', 'pyro': 'Dirichlet', 'pymc': 'Dirichlet', 'edward2': 'Dirichlet', 'turing': 'Dirichlet', 'gen': 'dirichlet', 'church': 'dirichlet', 'webppl': 'Dirichlet', 'bugs': 'ddirch', 'jags': 'ddirich'}, arg_aliases={'pymc': {'concentration': 'a'}, 'webppl': {'concentration': 'alpha'}}), 'Cauchy': FamilyMeta(qvr_name='Cauchy', distribution_class=td.Cauchy, quivers_class=ConditionalCauchy, target_names={'stan': 'cauchy', 'numpyro': 'Cauchy', 'pyro': 'Cauchy', 'pymc': 'Cauchy', 'edward2': 'Cauchy', 'turing': 'Cauchy', 'gen': 'cauchy', 'church': 'cauchy', 'webppl': 'Cauchy', 'bugs': 'dt', 'jags': 'dt'}, arg_aliases={'bugs': {'scale': 'tau'}, 'jags': {'scale': 'tau'}, 'pymc': {'loc': 'alpha', 'scale': 'beta'}, 'webppl': {'loc': 'location'}}), 'Laplace': FamilyMeta(qvr_name='Laplace', distribution_class=td.Laplace, quivers_class=ConditionalLaplace, target_names={'stan': 'double_exponential', 'numpyro': 'Laplace', 'pyro': 'Laplace', 'pymc': 'Laplace', 'edward2': 'Laplace', 'turing': 'Laplace', 'gen': 'laplace', 'webppl': 'Laplace', 'bugs': 'ddexp', 'jags': 'ddexp'}, arg_aliases={'bugs': {'scale': 'tau'}, 'jags': {'scale': 'tau'}, 'pymc': {'loc': 'mu', 'scale': 'b'}, 'webppl': {'loc': 'location', 'scale': 'scale'}}), 'Gumbel': FamilyMeta(qvr_name='Gumbel', distribution_class=td.Gumbel, quivers_class=ConditionalGumbel, target_names={'stan': 'gumbel', 'numpyro': 'Gumbel', 'pyro': 'Gumbel', 'pymc': 'Gumbel', 'edward2': 'Gumbel', 'turing': 'Gumbel'}, arg_aliases={'pymc': {'loc': 'mu', 'scale': 'beta'}}), 'LogNormal': FamilyMeta(qvr_name='LogNormal', distribution_class=td.LogNormal, quivers_class=ConditionalLogNormal, target_names={'stan': 'lognormal', 'numpyro': 'LogNormal', 'pyro': 'LogNormal', 'pymc': 'LogNormal', 'edward2': 'LogNormal', 'turing': 'LogNormal', 'gen': 'lognormal', 'church': 'lognormal', 'webppl': 'LogNormal', 'bugs': 'dlnorm', 'jags': 'dlnorm'}, arg_aliases={'pymc': {'loc': 'mu', 'scale': 'sigma'}}), 'StudentT': FamilyMeta(qvr_name='StudentT', distribution_class=td.StudentT, quivers_class=ConditionalStudentT, target_names={'stan': 'student_t', 'numpyro': 'StudentT', 'pyro': 'StudentT', 'pymc': 'StudentT', 'edward2': 'StudentT', 'turing': 'TDist', 'church': 'student-t', 'webppl': 'StudentT', 'bugs': 'dt', 'jags': 'dt'}, arg_aliases={'pymc': {'df': 'nu', 'loc': 'mu', 'scale': 'sigma'}}), 'Exponential': FamilyMeta(qvr_name='Exponential', distribution_class=td.Exponential, quivers_class=ConditionalExponential, target_names={'stan': 'exponential', 'numpyro': 'Exponential', 'pyro': 'Exponential', 'pymc': 'Exponential', 'edward2': 'Exponential', 'turing': 'Exponential', 'gen': 'exponential', 'church': 'exponential', 'webppl': 'Exponential', 'bugs': 'dexp', 'jags': 'dexp'}, arg_aliases={'pymc': {'rate': 'lam'}, 'webppl': {'rate': 'a'}}), 'Gamma': FamilyMeta(qvr_name='Gamma', distribution_class=td.Gamma, quivers_class=ConditionalGamma, target_names={'stan': 'gamma', 'numpyro': 'Gamma', 'pyro': 'Gamma', 'pymc': 'Gamma', 'edward2': 'Gamma', 'turing': 'Gamma', 'gen': 'gamma', 'church': 'gamma', 'webppl': 'Gamma', 'bugs': 'dgamma', 'jags': 'dgamma'}, arg_aliases={'pymc': {'concentration': 'alpha', 'rate': 'beta'}, 'webppl': {'concentration': 'shape', 'rate': 'scale'}}), 'Chi2': FamilyMeta(qvr_name='Chi2', distribution_class=td.Chi2, quivers_class=ConditionalChi2, target_names={'stan': 'chi_square', 'numpyro': 'Chi2', 'pyro': 'Chi2', 'pymc': 'ChiSquared', 'edward2': 'Chi2', 'turing': 'Chisq', 'bugs': 'dchisqr', 'jags': 'dchisqr'}, arg_aliases={'pymc': {'df': 'nu'}}), 'HalfCauchy': FamilyMeta(qvr_name='HalfCauchy', distribution_class=td.HalfCauchy, quivers_class=ConditionalHalfCauchy, target_names={'stan': 'cauchy', 'numpyro': 'HalfCauchy', 'pyro': 'HalfCauchy', 'pymc': 'HalfCauchy', 'edward2': 'HalfCauchy', 'turing': 'truncated', 'gen': 'cauchy', 'church': 'cauchy', 'webppl': 'Cauchy', 'bugs': 'dt', 'jags': 'dt'}, arg_aliases={'pymc': {'scale': 'beta'}, 'webppl': {'scale': 'scale', 'loc': 'location'}, 'bugs': {'scale': 'tau'}, 'jags': {'scale': 'tau'}}), 'HalfNormal': FamilyMeta(qvr_name='HalfNormal', distribution_class=td.HalfNormal, quivers_class=ConditionalHalfNormal, target_names={'stan': 'normal', 'numpyro': 'HalfNormal', 'pyro': 'HalfNormal', 'pymc': 'HalfNormal', 'edward2': 'HalfNormal', 'turing': 'truncated', 'gen': 'normal', 'church': 'gaussian', 'webppl': 'Gaussian', 'bugs': 'dnorm', 'jags': 'dnorm'}, arg_aliases={'pymc': {'scale': 'sigma'}, 'webppl': {'scale': 'sigma', 'loc': 'mu'}, 'bugs': {'scale': 'tau'}, 'jags': {'scale': 'tau'}}), 'InverseGamma': FamilyMeta(qvr_name='InverseGamma', distribution_class=td.InverseGamma, quivers_class=ConditionalInverseGamma, target_names={'stan': 'inv_gamma', 'numpyro': 'InverseGamma', 'pyro': 'InverseGamma', 'pymc': 'InverseGamma', 'edward2': 'InverseGamma', 'turing': 'InverseGamma'}, arg_aliases={'pymc': {'concentration': 'alpha', 'rate': 'beta'}}), 'Weibull': FamilyMeta(qvr_name='Weibull', distribution_class=td.Weibull, quivers_class=ConditionalWeibull, target_names={'stan': 'weibull', 'numpyro': 'Weibull', 'pyro': 'Weibull', 'pymc': 'Weibull', 'edward2': 'Weibull', 'turing': 'Weibull', 'gen': 'weibull', 'church': 'weibull', 'webppl': 'Weibull', 'bugs': 'dweib', 'jags': 'dweib'}, arg_aliases={'pymc': {'concentration': 'alpha', 'scale': 'beta'}}), 'Pareto': FamilyMeta(qvr_name='Pareto', distribution_class=td.Pareto, quivers_class=ConditionalPareto, target_names={'stan': 'pareto', 'numpyro': 'Pareto', 'pyro': 'Pareto', 'pymc': 'Pareto', 'edward2': 'Pareto', 'turing': 'Pareto', 'church': 'pareto', 'bugs': 'dpar', 'jags': 'dpar'}, arg_aliases={'pymc': {'alpha': 'alpha', 'scale': 'm'}}), 'Kumaraswamy': FamilyMeta(qvr_name='Kumaraswamy', distribution_class=td.Kumaraswamy, quivers_class=ConditionalKumaraswamy, target_names={'stan': 'kumaraswamy', 'numpyro': 'Kumaraswamy', 'pyro': 'Kumaraswamy', 'pymc': 'Kumaraswamy', 'edward2': 'Kumaraswamy', 'gen': 'kumaraswamy', 'turing': 'Kumaraswamy', 'webppl': 'Kumaraswamy'}, arg_aliases={'pymc': {'concentration1': 'a', 'concentration0': 'b'}}), 'ContinuousBernoulli': FamilyMeta(qvr_name='ContinuousBernoulli', distribution_class=td.ContinuousBernoulli, quivers_class=ConditionalContinuousBernoulli, target_names={'stan': 'continuous_bernoulli', 'numpyro': 'ContinuousBernoulli', 'pyro': 'ContinuousBernoulli', 'edward2': 'ContinuousBernoulli', 'pymc': 'ContinuousBernoulli', 'turing': 'ContinuousBernoulli', 'gen': 'continuous_bernoulli', 'webppl': 'ContinuousBernoulli'}), 'FisherSnedecor': FamilyMeta(qvr_name='FisherSnedecor', distribution_class=td.FisherSnedecor, quivers_class=ConditionalFisherSnedecor, target_names={'numpyro': 'FisherSnedecor', 'pyro': 'FisherSnedecor', 'turing': 'FDist', 'jags': 'df'}, arg_aliases={'jags': {'df1': 'n', 'df2': 'm'}}), 'Uniform': FamilyMeta(qvr_name='Uniform', distribution_class=td.Uniform, quivers_class=ConditionalUniform, target_names={'stan': 'uniform', 'numpyro': 'Uniform', 'pyro': 'Uniform', 'pymc': 'Uniform', 'edward2': 'Uniform', 'turing': 'Uniform', 'gen': 'uniform', 'church': 'uniform', 'webppl': 'Uniform', 'bugs': 'dunif', 'jags': 'dunif'}, arg_aliases={'pymc': {'low': 'lower', 'high': 'upper'}, 'webppl': {'low': 'a', 'high': 'b'}}), 'MultivariateNormal': FamilyMeta(qvr_name='MultivariateNormal', event_rank=1, distribution_class=td.MultivariateNormal, quivers_class=ConditionalMultivariateNormal, target_names={'stan': 'multi_normal', 'numpyro': 'MultivariateNormal', 'pyro': 'MultivariateNormal', 'pymc': 'MvNormal', 'edward2': 'MultivariateNormalFullCovariance', 'turing': 'MvNormal', 'gen': 'mvnormal', 'church': 'multivariate-gaussian', 'webppl': 'MultivariateGaussian', 'bugs': 'dmnorm', 'jags': 'dmnorm'}, arg_aliases={'pymc': {'loc': 'mu', 'covariance_matrix': 'cov'}, 'webppl': {'loc': 'mu', 'covariance_matrix': 'cov'}}, structured_lowering=StructuredSampleLowering(args=(StructuredDataArg(arg_name='loc', axis_indices=(0,), constraint_kind='real_vector'), StructuredDataArg(arg_name='covariance_matrix', axis_indices=(0, 0), constraint_kind='positive_definite')), event_axis_source=OverOrCodomainAxes(axis_count=1), sample_constraint_kind='real_vector')), 'LowRankMVN': FamilyMeta(qvr_name='LowRankMVN', event_rank=1, distribution_class=td.LowRankMultivariateNormal, quivers_class=ConditionalLowRankMVN, target_names={'numpyro': 'LowRankMultivariateNormal', 'pyro': 'LowRankMultivariateNormal'}, arg_aliases={'pymc': {'loc': 'mu', 'cov_factor': 'W', 'cov_diag': 'diag'}}), 'RelaxedBernoulli': FamilyMeta(qvr_name='RelaxedBernoulli', distribution_class=td.RelaxedBernoulli, quivers_class=ConditionalRelaxedBernoulli, target_names={'numpyro': 'RelaxedBernoulli', 'pyro': 'RelaxedBernoulli', 'edward2': 'RelaxedBernoulli'}), 'RelaxedOneHotCategorical': FamilyMeta(qvr_name='RelaxedOneHotCategorical', event_rank=1, distribution_class=td.RelaxedOneHotCategorical, quivers_class=ConditionalRelaxedOneHotCategorical, target_names={'numpyro': 'RelaxedOneHotCategorical', 'pyro': 'RelaxedOneHotCategorical', 'edward2': 'RelaxedOneHotCategorical'}), 'Wishart': FamilyMeta(qvr_name='Wishart', event_rank=2, distribution_class=td.Wishart, quivers_class=ConditionalWishart, target_names={'stan': 'wishart', 'numpyro': 'Wishart', 'pyro': 'Wishart', 'pymc': 'Wishart', 'edward2': 'Wishart', 'turing': 'Wishart', 'bugs': 'dwish', 'jags': 'dwish'}, arg_aliases={'pymc': {'df': 'nu', 'covariance_matrix': 'V'}}), 'InverseWishart': FamilyMeta(qvr_name='InverseWishart', event_rank=2, distribution_class=_InverseWishart, quivers_class=ConditionalInverseWishart, target_names={'stan': 'inv_wishart', 'numpyro': 'InverseWishart', 'pyro': 'InverseWishart', 'turing': 'InverseWishart'}), 'MatrixNormal': FamilyMeta(qvr_name='MatrixNormal', event_rank=2, distribution_class=_MatrixNormal, quivers_class=ConditionalMatrixNormal, target_names={'stan': 'matrix_normal', 'numpyro': 'MatrixNormal', 'pyro': 'MatrixNormal', 'pymc': 'MatrixNormal', 'edward2': 'MatrixNormalLinearOperator', 'turing': 'MatrixNormal', 'gen': 'matrix_normal', 'webppl': 'MatrixNormal', 'church': 'matrix-normal'}, arg_aliases={'pymc': {'loc': 'mu', 'row_covariance': 'rowcov', 'col_covariance': 'colcov'}}, structured_lowering=StructuredSampleLowering(args=(StructuredDataArg(arg_name='loc', axis_indices=(0, 1), constraint_kind='real_matrix'), StructuredDataArg(arg_name='row_covariance', axis_indices=(0, 0), constraint_kind='positive_definite'), StructuredDataArg(arg_name='col_covariance', axis_indices=(1, 1), constraint_kind='positive_definite')), event_axis_source=OverOrCodomainAxes(axis_count=2), sample_constraint_kind='real_matrix')), 'GP': FamilyMeta(qvr_name='GP', event_rank=1, distribution_class=_GaussianProcess, quivers_class=ConditionalGaussianProcess, target_names={'edward2': 'MultivariateNormalFullCovariance', 'stan': 'multi_normal', 'numpyro': 'MultivariateNormal', 'pyro': 'MultivariateNormal', 'pymc': 'MvNormal', 'turing': 'MvNormal', 'gen': 'mvnormal', 'webppl': 'MultivariateGaussian', 'church': 'multivariate-gaussian', 'bugs': 'dmnorm', 'jags': 'dmnorm'}, structured_lowering=StructuredSampleLowering(args=(StructuredZeroVectorArg(arg_name='mean'), StructuredKernelArg(arg_name='covariance_matrix', x_input_name='x')), event_axis_source=DomainGridAxis(), sample_constraint_kind='real_vector', always_apply=True)), 'Horseshoe': FamilyMeta(qvr_name='Horseshoe', distribution_class=_Horseshoe, quivers_class=ConditionalHorseshoe, target_names={}), 'Bernoulli': FamilyMeta(qvr_name='Bernoulli', distribution_class=td.Bernoulli, quivers_class=ConditionalBernoulli, target_names={'stan': 'bernoulli', 'numpyro': 'Bernoulli', 'pyro': 'Bernoulli', 'pymc': 'Bernoulli', 'edward2': 'Bernoulli', 'turing': 'Bernoulli', 'gen': 'bernoulli', 'church': 'flip', 'webppl': 'Bernoulli', 'bugs': 'dbern', 'jags': 'dbern'}, arg_aliases={'pymc': {'probs': 'p'}, 'webppl': {'probs': 'p'}}), 'Categorical': FamilyMeta(qvr_name='Categorical', distribution_class=td.Categorical, quivers_class=ConditionalCategorical, target_names={'stan': 'categorical', 'numpyro': 'Categorical', 'pyro': 'Categorical', 'pymc': 'Categorical', 'edward2': 'Categorical', 'turing': 'Categorical', 'gen': 'categorical', 'church': 'categorical', 'webppl': 'Categorical', 'bugs': 'dcat', 'jags': 'dcat'}, arg_aliases={'pymc': {'probs': 'p', 'logits': 'logit_p'}, 'webppl': {'probs': 'ps'}}), 'Poisson': FamilyMeta(qvr_name='Poisson', distribution_class=td.Poisson, quivers_class=ConditionalPoisson, target_names={'stan': 'poisson', 'numpyro': 'Poisson', 'pyro': 'Poisson', 'pymc': 'Poisson', 'edward2': 'Poisson', 'turing': 'Poisson', 'gen': 'poisson', 'church': 'poisson', 'webppl': 'Poisson', 'bugs': 'dpois', 'jags': 'dpois'}, arg_aliases={'pymc': {'rate': 'mu'}, 'webppl': {'rate': 'mu'}}), 'NegativeBinomial': FamilyMeta(qvr_name='NegativeBinomial', distribution_class=td.NegativeBinomial, quivers_class=ConditionalNegativeBinomial, target_names={'stan': 'neg_binomial_2', 'numpyro': 'NegativeBinomial2', 'pyro': 'NegativeBinomial', 'pymc': 'NegativeBinomial', 'edward2': 'NegativeBinomial', 'turing': 'NegativeBinomial', 'gen': 'neg_binom', 'church': 'negative-binomial', 'webppl': 'NegativeBinomial', 'bugs': 'dnegbin', 'jags': 'dnegbin'}, arg_aliases={'pymc': {'probs': 'p', 'total_count': 'n'}}), 'Geometric': FamilyMeta(qvr_name='Geometric', distribution_class=td.Geometric, quivers_class=ConditionalGeometric, target_names={'numpyro': 'Geometric', 'pyro': 'Geometric', 'pymc': 'Geometric', 'edward2': 'Geometric', 'turing': 'Geometric', 'gen': 'geometric', 'church': 'geometric'}, arg_aliases={'pymc': {'probs': 'p'}}), 'Binomial': FamilyMeta(qvr_name='Binomial', distribution_class=td.Binomial, quivers_class=ConditionalBinomial, target_names={'stan': 'binomial', 'numpyro': 'Binomial', 'pyro': 'Binomial', 'pymc': 'Binomial', 'edward2': 'Binomial', 'turing': 'Binomial', 'webppl': 'Binomial', 'bugs': 'dbin', 'jags': 'dbin'}, arg_aliases={'pymc': {'probs': 'p', 'total_count': 'n'}, 'webppl': {'probs': 'p', 'total_count': 'n'}}), 'VonMises': FamilyMeta(qvr_name='VonMises', distribution_class=td.VonMises, quivers_class=ConditionalVonMises, target_names={'stan': 'von_mises', 'numpyro': 'VonMises', 'pyro': 'VonMises', 'pymc': 'VonMises', 'edward2': 'VonMises', 'turing': 'VonMises'}, arg_aliases={'pymc': {'loc': 'mu', 'concentration': 'kappa'}}), 'LogisticNormal': FamilyMeta(qvr_name='LogisticNormal', event_rank=1, distribution_class=td.LogisticNormal, quivers_class=ConditionalLogisticNormal, target_names={'numpyro': 'LogisticNormal', 'pyro': 'LogisticNormal', 'webppl': 'LogisticNormal'}, arg_aliases={'webppl': {'loc': 'mu', 'scale': 'sigma'}}), 'OneHotCategorical': FamilyMeta(qvr_name='OneHotCategorical', event_rank=1, distribution_class=td.OneHotCategorical, quivers_class=ConditionalOneHotCategorical, target_names={'numpyro': 'OneHotCategorical', 'pyro': 'OneHotCategorical', 'edward2': 'OneHotCategorical'}, arg_aliases={'pymc': {'probs': 'p'}}), 'LKJCholesky': FamilyMeta(qvr_name='LKJCholesky', event_rank=2, distribution_class=td.LKJCholesky, quivers_class=ConditionalLKJCholesky, target_names={'stan': 'lkj_corr_cholesky', 'numpyro': 'LKJCholesky', 'pyro': 'LKJCorrCholesky', 'pymc': 'LKJCholesky', 'edward2': 'LKJ', 'turing': 'LKJCholesky', 'gen': 'lkj_cholesky', 'webppl': 'LKJCholesky'}, arg_aliases={'pymc': {'concentration': 'eta'}}), 'Mixture': FamilyMeta(qvr_name='Mixture', distribution_class=td.MixtureSameFamily, quivers_class=ConditionalMixture, target_names={'numpyro': 'MixtureSameFamily', 'pyro': 'MixtureSameFamily', 'pymc': 'Mixture', 'edward2': 'MixtureSameFamily', 'turing': 'MixtureModel', 'webppl': 'Mixture', 'jags': 'dpois'}, arg_aliases={'pymc': {'mixture_distribution': 'w', 'component_distribution': 'comp_dists'}}), 'MixtureNormal': FamilyMeta(qvr_name='MixtureNormal', distribution_class=MixtureNormal, quivers_class=ConditionalMixtureNormal, target_names={'numpyro': 'MixtureSameFamily', 'pyro': 'MixtureSameFamily', 'edward2': 'MixtureSameFamily', 'pymc': 'NormalMixture', 'turing': 'MixtureModel', 'stan': 'log_mix', 'gen': 'HomogeneousMixture', 'webppl': 'Mixture'}, arg_aliases={'pymc': {'weights': 'w', 'loc': 'mu', 'scale': 'sigma'}}), 'Independent': FamilyMeta(qvr_name='Independent', distribution_class=td.Independent, quivers_class=ConditionalIndependent, target_names={'numpyro': 'Independent', 'pyro': 'Independent', 'edward2': 'Independent'}), 'Transformed': FamilyMeta(qvr_name='Transformed', distribution_class=td.TransformedDistribution, quivers_class=ConditionalTransformed, target_names={'numpyro': 'TransformedDistribution', 'pyro': 'TransformedDistribution', 'edward2': 'TransformedDistribution'}), 'Truncated': FamilyMeta(qvr_name='Truncated', distribution_class=_Truncated, quivers_class=Truncated, target_names={'pymc': 'Truncated', 'numpyro': 'TruncatedDistribution', 'pyro': 'TruncatedDistribution', 'turing': 'truncated'}, arg_aliases={'pymc': {'base_distribution': 'dist'}}), 'ZeroInflatedPoisson': FamilyMeta(qvr_name='ZeroInflatedPoisson', distribution_class=ZeroInflatedPoisson, target_names={}), 'HurdlePoisson': FamilyMeta(qvr_name='HurdlePoisson', distribution_class=HurdlePoisson, target_names={}), 'ZeroOneInflatedBeta': FamilyMeta(qvr_name='ZeroOneInflatedBeta', distribution_class=ZeroOneInflatedBeta, target_names={}), 'Restrict': FamilyMeta(qvr_name='Restrict', distribution_class=Restrict, target_names={}), 'Normalize': FamilyMeta(qvr_name='Normalize', distribution_class=Normalize, target_names={}), 'PointMass': FamilyMeta(qvr_name='PointMass', distribution_class=PointMass, target_names={}), 'LKJCorrelationFactor': FamilyMeta(qvr_name='LKJCorrelationFactor', event_rank=2, distribution_class=_LKJCorrelationFactor, quivers_class=LKJCorrelationFactor, target_names={'pymc': 'LKJCorr', 'stan': 'lkj_corr', 'numpyro': 'LKJ', 'pyro': 'LKJ'}), 'BetaBinomial': FamilyMeta(qvr_name='BetaBinomial', distribution_class=BetaBinomial, quivers_class=ConditionalBetaBinomial, target_names={'stan': 'beta_binomial', 'numpyro': 'BetaBinomial', 'pyro': 'BetaBinomial', 'pymc': 'BetaBinomial', 'edward2': 'BetaBinomial', 'turing': 'BetaBinomial', 'bugs': 'dbetabin', 'jags': 'dbetabin', 'gen': 'beta_binomial', 'webppl': 'BetaBinomial'}, arg_aliases={'pymc': {'concentration1': 'alpha', 'concentration0': 'beta', 'total_count': 'n'}}), 'OrderedLogistic': FamilyMeta(qvr_name='OrderedLogistic', distribution_class=OrderedLogistic, quivers_class=ConditionalOrderedLogistic, target_names={'stan': 'ordered_logistic', 'numpyro': 'OrderedLogistic', 'pyro': 'OrderedLogistic', 'pymc': 'OrderedLogistic'}), 'OrderedProbit': FamilyMeta(qvr_name='OrderedProbit', distribution_class=OrderedProbit, quivers_class=ConditionalOrderedProbit, target_names={'stan': 'ordered_probit', 'numpyro': 'OrderedProbit', 'pyro': 'OrderedProbit', 'pymc': 'OrderedProbit'}), 'Logistic': FamilyMeta(qvr_name='Logistic', distribution_class=Logistic, quivers_class=ConditionalLogistic, target_names={'stan': 'logistic', 'numpyro': 'Logistic', 'pyro': 'Logistic', 'pymc': 'Logistic', 'edward2': 'Logistic', 'turing': 'Logistic', 'bugs': 'dlogis', 'jags': 'dlogis', 'gen': 'logistic', 'webppl': 'Logistic'}, arg_aliases={'pymc': {'loc': 'mu', 'scale': 's'}}), 'HalfStudentT': FamilyMeta(qvr_name='HalfStudentT', distribution_class=HalfStudentT, quivers_class=ConditionalHalfStudentT, target_names={'stan': 'student_t', 'numpyro': 'HalfStudentT', 'pyro': 'HalfStudentT', 'pymc': 'HalfStudentT', 'edward2': 'HalfStudentT', 'bugs': 'dt', 'jags': 'dt', 'gen': 'half_student_t', 'turing': 'HalfStudentT', 'webppl': 'HalfStudentT'}, arg_aliases={'pymc': {'df': 'nu', 'scale': 'sigma'}, 'bugs': {'scale': 'tau'}, 'jags': {'scale': 'tau'}})}

The transpile-time family registry, keyed by QVR family name.

DYNAMIC_TARGET_LANGUAGES module-attribute

DYNAMIC_TARGET_LANGUAGES: dict[str, str] = {'pyro': 'python', 'numpyro': 'python', 'pymc': 'python', 'edward2': 'python', 'turing': 'julia', 'gen': 'julia', 'webppl': 'javascript', 'church': 'scheme'}

The dynamic targets, each mapped to the host language it renders to.

TARGET_NAME_SEPARATOR module-attribute

TARGET_NAME_SEPARATOR = '__'

How a target spells the $ of a name a program draw renamed.

theta$z is the site of the local z of a program drawn under theta, and no target language admits $ in an identifier.

EmitFn module-attribute

EmitFn = Callable[..., Any]

An emit function: called with the renderer, its context, and one IR node or argument, returning the backend's fragment for it.

MarginalizeAtomSet

MarginalizeAtomSet = Literal['binary', 'class_index']

How a marginalized latent's atoms are enumerated.

"binary" integrates over the two atoms 0 and 1; "class_index" integrates over every index of the family's support.

QiecFeature

QiecFeature = Literal['declarations', 'return', 'bind', 'perform', 'handle', 'case', 'if', 'call', 'recursion', 'resume', 'local-instance', 'authored-handler', 'arithmetic', 'comparison', 'boolean', 'string', 'conversion', 'math', 'tuple', 'tensor', 'distribution', 'plate', 'log-density', 'site', 'gather', 'segment-sum', 'kernel-matrix', 'affine-map', 'table-map', 'neural-attachment', 'search', 'reduction', 'rowwise', 'comprehension', 'special', 'activation', 'weight', 'evidence', 'transport', 'attachment', 'structured-value', 'effectful-row', 'open-effect-row', 'type-polymorphism', 'index-polymorphism', 'effect-polymorphism', 'named-parameter', 'non-scalar-result', 'non-scalar-parameter', 'zero-resumption', 'affine-resumption', 'linear-resumption', 'unrestricted-resumption']

One QIEC construct a target may or may not preserve.

analyze_qiec_capabilities names the features a module needs, and a QiecTargetCapabilities names the ones a target has.

UnsupportedConstruct

UnsupportedConstruct(target: str, kinds: list[str], *, declarations: tuple[RefusedDeclaration, ...] = (), module_has_program: bool = False)

Bases: Exception

Raised when a backend cannot transpile one or more QVR constructs.

The exception message describes the unsupported constructs and possible replacements. The structured identifiers remain available in kinds.

PARAMETER DESCRIPTION
target

Backend name, such as "qvr-stan".

TYPE: str

kinds

Construct identifiers suitable for programmatic matching; they are sorted and deduplicated on construction.

TYPE: list[str]

declarations

Affected top-level declarations, when applicable.

TYPE: tuple[RefusedDeclaration, ...] DEFAULT: ()

module_has_program

Whether the refused module declares a probabilistic program.

TYPE: bool DEFAULT: False

ATTRIBUTE DESCRIPTION
target

Backend name, such as "qvr-stan".

kinds

Sorted, deduplicated construct identifiers.

declarations

Affected top-level declarations, when applicable.

module_has_program

Whether the refused module declares a probabilistic program.

Source code in src/quivers/transpile/_api.py
def __init__(
    self,
    target: str,
    kinds: list[str],
    *,
    declarations: tuple[RefusedDeclaration, ...] = (),
    module_has_program: bool = False,
) -> None:
    self.target = target
    self.kinds = sorted(set(kinds))
    self.declarations = declarations
    self.module_has_program = module_has_program
    super().__init__(
        user_facing_message(
            target,
            tuple(self.kinds),
            declarations,
            module_has_program,
        )
    )

RefusedDeclaration didactic-model

RefusedDeclaration(*, kind: str, name: str = '', line: int = 0)

Bases: Model

One top-level declaration a target's support tier rejected.

unsupported_for reads these off the module's AST so the message can name the declaration the way the user wrote it (composition pmf_scores) and point at its line, rather than echoing the grammar rule's name (composition_decl).

PARAMETER DESCRIPTION
kind

The statement's didactic discriminator, such as "composition_decl".

TYPE: str

name

The name the declaration binds, empty when the form binds none.

TYPE: str DEFAULT: ''

line

The one-based source line, 0 when the parser recorded none.

TYPE: int DEFAULT: 0

Backend

Bases: Protocol

The protocol every backend module satisfies.

Backends register themselves via didactic.codegen.emitter under a "qvr-<name>" key. Quivers' top-level transpile dispatches by looking up the registered emitter, then delegates to its emit_instance.

ATTRIBUTE DESCRIPTION
file_extension

Canonical filename extension ("stan", "py", "jl", "js", "scm").

TYPE: str

grammar

The tree-sitter grammar name backing this backend, as accepted by panproto.AstParserRegistry.parse_with_protocol.

TYPE: str

support

The probabilistic-subset support tier accepted by this backend.

TYPE: frozenset[str]

emit_instance

emit_instance(module: Module) -> bytes

Transpile a parsed QVR module to bytes.

PARAMETER DESCRIPTION
module

The parsed module.

TYPE: Module

RETURNS DESCRIPTION
bytes

The target program's source.

RAISES DESCRIPTION
UnsupportedConstruct

If the module holds constructs the backend cannot represent.

Source code in src/quivers/transpile/_support.py
def emit_instance(self, module: Module) -> bytes:
    """Transpile a parsed QVR module to bytes.

    Parameters
    ----------
    module
        The parsed module.

    Returns
    -------
    bytes
        The target program's source.

    Raises
    ------
    UnsupportedConstruct
        If the module holds constructs the backend cannot represent.
    """
    ...

EmitPretty

EmitPretty(grammar: str)

Bases: Mapping[Schema, bytes]

The last arrow of the pipeline: a target schema to source bytes.

A Mapping[panproto.Schema, bytes] over the registry's emit_pretty, which walks the grammar's productions to print the schema a renderer built.

PARAMETER DESCRIPTION
grammar

The tree-sitter grammar the schemas are built in.

TYPE: str

Source code in src/quivers/transpile/_pipeline.py
def __init__(self, grammar: str) -> None:
    self._grammar = grammar

forward

forward(schema: Schema) -> bytes

Print one schema as source.

PARAMETER DESCRIPTION
schema

A schema in the grammar's theory, as a renderer returns it.

TYPE: Schema

RETURNS DESCRIPTION
bytes

The target program's source.

Source code in src/quivers/transpile/_pipeline.py
def forward(self, schema: panproto.Schema) -> bytes:
    """Print one schema as source.

    Parameters
    ----------
    schema
        A schema in the grammar's theory, as a renderer returns it.

    Returns
    -------
    bytes
        The target program's source.
    """
    return bytes(parser_registry().emit_pretty(self._grammar, schema))

transpile

transpile(module: Module, *, target: str) -> bytes

Transpile a QVR module to the named target backend.

PARAMETER DESCRIPTION
module

The parsed Module AST.

TYPE: Module

target

A registered backend key. See available_targets.

TYPE: str

RETURNS DESCRIPTION
bytes

The transpiled source bytes.

RAISES DESCRIPTION
UnsupportedConstruct

If target is not registered, or if the module contains constructs the chosen renderer cannot lower (e.g. a non-finite-support marginalize on Stan).

Source code in src/quivers/transpile/_entry.py
def transpile(module: Module, *, target: str) -> bytes:
    """Transpile a QVR module to the named ``target`` backend.

    Parameters
    ----------
    module
        The parsed [`Module`][quivers.dsl.ast_nodes.Module] AST.
    target
        A registered backend key. See
        [`available_targets`][quivers.transpile.available_targets].

    Returns
    -------
    bytes
        The transpiled source bytes.

    Raises
    ------
    UnsupportedConstruct
        If ``target`` is not registered, or if the module contains
        constructs the chosen renderer cannot lower (e.g. a
        non-finite-support marginalize on Stan).
    """
    if target not in _RENDERERS:
        raise UnsupportedConstruct(
            target,
            [f"target:unknown:{target}:{','.join(sorted(_RENDERERS))}"],
        )
    renderer_cls, grammar, support_tier = _RENDERERS[target]
    unsupported_for(f"qvr-{target}", module, allow=support_tier)
    expanded = expand_composite_lets(module, target=target)
    ir = Lower().forward(expanded, target=target)
    schema = renderer_cls().render(ir)
    return bytes(parser_registry().emit_pretty(grammar, schema))

available_targets

available_targets() -> list[str]

List every registered backend, sorted.

RETURNS DESCRIPTION
list[str]

The keys transpile accepts as target.

Source code in src/quivers/transpile/_entry.py
def available_targets() -> list[str]:
    """List every registered backend, sorted.

    Returns
    -------
    list[str]
        The keys [`transpile`][quivers.transpile.transpile] accepts as
        ``target``.
    """
    return sorted(_RENDERERS)

unsupported_for

unsupported_for(target: str, module: Module, *, allow: frozenset[str]) -> None

Raise UnsupportedConstruct if module contains statement kinds outside allow.

Walks the module's top-level statements; the kind field is the didactic TaggedUnion discriminator ("program_decl", "morphism_decl", etc.). Any kind not in allow is collected; if the resulting set is non-empty, raises.

CATEGORICAL_METADATA_IGNORABLE kinds (composition_decl, category_decl, schema_decl, bundle_decl, rule_decl, contraction_decl, signature_decl, deduction_decl) are accepted ALONGSIDE a program_decl. The QIEC forms in QIEC_SURFACE are always admitted because the caller has already lowered and checked the complete QIEC submodule. Renderer-level capability analysis decides which executable QIEC features the selected target can preserve.

PARAMETER DESCRIPTION
target

The backend name reported in the error, such as "qvr-stan".

TYPE: str

module

The parsed module to check.

TYPE: Module

allow

The statement kinds the backend accepts, usually one of the support tiers such as STAN_LIKE.

TYPE: frozenset[str]

RAISES DESCRIPTION
UnsupportedConstruct

If a top-level statement's kind is outside the effective allowance.

Source code in src/quivers/transpile/_support.py
def unsupported_for(target: str, module: Module, *, allow: frozenset[str]) -> None:
    """Raise [`UnsupportedConstruct`][quivers.transpile.UnsupportedConstruct]
    if ``module`` contains statement kinds outside ``allow``.

    Walks the module's top-level statements; the ``kind`` field is the
    didactic `TaggedUnion` discriminator
    (``"program_decl"``, ``"morphism_decl"``, etc.). Any kind not in
    ``allow`` is collected; if the resulting set is non-empty, raises.

    [`CATEGORICAL_METADATA_IGNORABLE`][quivers.transpile.CATEGORICAL_METADATA_IGNORABLE]
    kinds (``composition_decl``, ``category_decl``, ``schema_decl``,
    ``bundle_decl``, ``rule_decl``, ``contraction_decl``,
    ``signature_decl``, ``deduction_decl``) are accepted ALONGSIDE a
    ``program_decl``. The QIEC forms in
    [`QIEC_SURFACE`][quivers.transpile.QIEC_SURFACE]
    are always admitted because the caller has already lowered and checked the
    complete QIEC submodule. Renderer-level capability analysis decides which
    executable QIEC features the selected target can preserve.

    Parameters
    ----------
    target
        The backend name reported in the error, such as ``"qvr-stan"``.
    module
        The parsed module to check.
    allow
        The statement kinds the backend accepts, usually one of the
        support tiers such as [`STAN_LIKE`][quivers.transpile.STAN_LIKE].

    Raises
    ------
    UnsupportedConstruct
        If a top-level statement's kind is outside the effective
        allowance.
    """
    kinds = {cast_kind(s) for s in module.statements}
    has_program = "program_decl" in kinds
    has_schema_parser = any(
        cast_kind(statement) == "define_decl"
        and str(getattr(getattr(statement, "expr", None), "kind", "")) == "expr_parser"
        for statement in module.statements
    )
    has_structural = "signature_decl" in kinds and bool(
        kinds & {"encoder_decl", "decoder_decl"}
    )
    effective_allow = allow | QIEC_SURFACE
    if has_program or has_schema_parser:
        effective_allow |= CATEGORICAL_METADATA_IGNORABLE
    if has_structural:
        effective_allow |= STRUCTURAL_QIEC
    bad: set[str] = set()
    for statement in module.statements:
        kind = cast_kind(statement)
        if kind not in effective_allow:
            bad.add(kind)
    if bad:
        raise UnsupportedConstruct(target, sorted(bad))

parser_registry

parser_registry() -> AstParserRegistry

Cached process-wide AstParserRegistry.

Construction walks every installed panproto.grammars entry-point pack; doing it once amortises that work across every transpile call.

RETURNS DESCRIPTION
AstParserRegistry

The registry every renderer parses and emits through.

Source code in src/quivers/transpile/_pipeline.py
def parser_registry() -> _NativeAstParserRegistry:
    """Cached process-wide `AstParserRegistry`.

    Construction walks every installed ``panproto.grammars`` entry-point
    pack; doing it once amortises that work across every transpile call.

    Returns
    -------
    panproto.AstParserRegistry
        The registry every renderer parses and emits through.
    """
    global _REGISTRY
    if _REGISTRY is None:
        _REGISTRY = panproto.AstParserRegistry()
    return _REGISTRY

target_protocol

target_protocol(grammar: str) -> Protocol

Synthesise a panproto.Protocol handle for a tree-sitter grammar.

Tree-sitter grammars are not registered as builtin protocols (panproto.get_builtin_protocol(grammar) raises KeyError for every grammar in AstParserRegistry().protocol_names()). The panproto API does, however, accept a string theory name in Protocol.from_theories; the resulting Protocol is suitable for fresh schema() builders that emit through the grammar's auto-derived theory.

PARAMETER DESCRIPTION
grammar

The tree-sitter grammar name, such as "stan" or "python".

TYPE: str

RETURNS DESCRIPTION
Protocol

A protocol whose schemas are built in the grammar's theory.

Source code in src/quivers/transpile/_pipeline.py
def target_protocol(grammar: str) -> panproto.Protocol:
    """Synthesise a `panproto.Protocol` handle for
    a tree-sitter grammar.

    Tree-sitter grammars are not registered as builtin protocols
    (``panproto.get_builtin_protocol(grammar)`` raises ``KeyError`` for
    every grammar in `AstParserRegistry().protocol_names()`). The
    panproto API does, however, accept a string theory name in
    `Protocol.from_theories`; the
    resulting Protocol is suitable for fresh
    `schema()` builders that emit through
    the grammar's auto-derived theory.

    Parameters
    ----------
    grammar
        The tree-sitter grammar name, such as ``"stan"`` or ``"python"``.

    Returns
    -------
    panproto.Protocol
        A protocol whose schemas are built in the grammar's theory.
    """
    # `schema_theory` is documented to accept either a `Theory` instance
    # or a string theory name; the published stub types it as `Theory`
    # only, so we cast at the boundary.
    return panproto.Protocol.from_theories(
        name=grammar,
        schema_theory=grammar,  # type: ignore[arg-type]
        obj_kinds=[],
    )