use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
use super::types::{
FinitePartialOrder, FiniteValuation, InnocentStrategy, KleenePCA, LambdaTerm, LogicalRelation,
MaybeInterp, MonotoneMap, PCFTerm, PCFType, PCFValue, ScottOpen, Trace,
};
pub fn app(f: Expr, a: Expr) -> Expr {
Expr::App(Box::new(f), Box::new(a))
}
pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
app(app(f, a), b)
}
pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
app(app2(f, a, b), c)
}
pub fn cst(s: &str) -> Expr {
Expr::Const(Name::str(s), vec![])
}
pub fn prop() -> Expr {
Expr::Sort(Level::zero())
}
pub fn type0() -> Expr {
Expr::Sort(Level::succ(Level::zero()))
}
pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
}
pub fn arrow(a: Expr, b: Expr) -> Expr {
pi(BinderInfo::Default, "_", a, b)
}
pub fn bvar(n: u32) -> Expr {
Expr::BVar(n)
}
pub fn nat_ty() -> Expr {
cst("Nat")
}
pub fn bool_ty() -> Expr {
cst("Bool")
}
pub fn list_ty(elem: Expr) -> Expr {
app(cst("List"), elem)
}
pub fn string_ty() -> Expr {
cst("String")
}
pub fn option_ty(a: Expr) -> Expr {
app(cst("Option"), a)
}
pub fn cpo_ty() -> Expr {
arrow(type0(), prop())
}
pub fn pointed_cpo_ty() -> Expr {
arrow(type0(), prop())
}
pub fn scott_domain_ty() -> Expr {
arrow(type0(), prop())
}
pub fn bounded_lattice_ty() -> Expr {
arrow(type0(), prop())
}
pub fn complete_lattice_ty() -> Expr {
arrow(type0(), prop())
}
pub fn is_directed_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
arrow(arrow(bvar(0), prop()), prop()),
)
}
pub fn directed_sup_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
arrow(arrow(bvar(0), prop()), bvar(0)),
)
}
pub fn least_element_ty() -> Expr {
pi(BinderInfo::Default, "D", type0(), bvar(0))
}
pub fn is_compact_ty() -> Expr {
pi(BinderInfo::Default, "D", type0(), arrow(bvar(0), prop()))
}
pub fn way_below_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
arrow(bvar(0), arrow(bvar(1), prop())),
)
}
pub fn scott_continuous_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
pi(
BinderInfo::Default,
"E",
type0(),
arrow(arrow(bvar(1), bvar(1)), prop()),
),
)
}
pub fn continuous_function_space_ty() -> Expr {
arrow(type0(), arrow(type0(), type0()))
}
pub fn continuous_id_ty() -> Expr {
pi(BinderInfo::Default, "D", type0(), prop())
}
pub fn continuous_compose_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
pi(
BinderInfo::Default,
"E",
type0(),
pi(BinderInfo::Default, "F", type0(), prop()),
),
)
}
pub fn is_monotone_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
pi(
BinderInfo::Default,
"E",
type0(),
arrow(arrow(bvar(1), bvar(1)), prop()),
),
)
}
pub fn continuous_implies_monotone_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
pi(BinderInfo::Default, "E", type0(), prop()),
)
}
pub fn knaster_tarski_ty() -> Expr {
pi(
BinderInfo::Default,
"L",
type0(),
arrow(prop(), arrow(prop(), prop())),
)
}
pub fn least_fixed_point_ty() -> Expr {
pi(
BinderInfo::Default,
"L",
type0(),
arrow(arrow(bvar(0), bvar(0)), bvar(0)),
)
}
pub fn greatest_fixed_point_ty() -> Expr {
pi(
BinderInfo::Default,
"L",
type0(),
arrow(arrow(bvar(0), bvar(0)), bvar(0)),
)
}
pub fn kleene_fixed_point_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
arrow(prop(), arrow(prop(), prop())),
)
}
pub fn kleene_chain_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
arrow(arrow(bvar(0), bvar(0)), arrow(nat_ty(), bvar(1))),
)
}
pub fn fixed_point_induction_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
arrow(prop(), arrow(prop(), arrow(prop(), prop()))),
)
}
pub fn is_admissible_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
arrow(arrow(bvar(0), prop()), prop()),
)
}
pub fn pcf_type_ty() -> Expr {
type0()
}
pub fn pcf_term_ty() -> Expr {
type0()
}
pub fn sem_type_ty() -> Expr {
arrow(type0(), type0())
}
pub fn sem_term_ty() -> Expr {
pi(
BinderInfo::Default,
"Gamma",
type0(),
pi(
BinderInfo::Default,
"tau",
type0(),
arrow(prop(), arrow(type0(), type0())),
),
)
}
pub fn pcf_ctx_ty() -> Expr {
type0()
}
pub fn sem_ctx_ty() -> Expr {
arrow(type0(), type0())
}
pub fn pcf_fix_ty() -> Expr {
pi(BinderInfo::Default, "tau", type0(), type0())
}
pub fn adequacy_thm_ty() -> Expr {
prop()
}
pub fn soundness_thm_ty() -> Expr {
prop()
}
pub fn operational_equivalence_ty() -> Expr {
arrow(type0(), arrow(type0(), prop()))
}
pub fn denotational_equivalence_ty() -> Expr {
arrow(type0(), arrow(type0(), prop()))
}
pub fn full_abstraction_ty() -> Expr {
prop()
}
pub fn compositionality_ty() -> Expr {
prop()
}
pub fn fully_abstract_model_ty() -> Expr {
type0()
}
pub fn arena_ty() -> Expr {
type0()
}
pub fn move_ty() -> Expr {
type0()
}
pub fn strategy_ty() -> Expr {
arrow(type0(), type0())
}
pub fn innocent_strategy_ty() -> Expr {
pi(BinderInfo::Default, "A", type0(), arrow(type0(), prop()))
}
pub fn well_bracketed_ty() -> Expr {
pi(BinderInfo::Default, "A", type0(), arrow(type0(), prop()))
}
pub fn strategy_compose_ty() -> Expr {
arrow(type0(), arrow(type0(), type0()))
}
pub fn play_ty() -> Expr {
arrow(type0(), type0())
}
pub fn p_view_ty() -> Expr {
pi(BinderInfo::Default, "A", type0(), arrow(type0(), type0()))
}
pub fn o_view_ty() -> Expr {
pi(BinderInfo::Default, "A", type0(), arrow(type0(), type0()))
}
pub fn game_model_ty() -> Expr {
type0()
}
pub fn game_full_abstraction_ty() -> Expr {
prop()
}
pub fn trace_ty() -> Expr {
arrow(type0(), type0())
}
pub fn trace_semantics_ty() -> Expr {
pi(BinderInfo::Default, "A", type0(), arrow(type0(), type0()))
}
pub fn trace_equivalence_ty() -> Expr {
pi(
BinderInfo::Default,
"A",
type0(),
arrow(type0(), arrow(type0(), prop())),
)
}
pub fn trace_inclusion_ty() -> Expr {
pi(
BinderInfo::Default,
"A",
type0(),
arrow(type0(), arrow(type0(), prop())),
)
}
pub fn infinite_trace_ty() -> Expr {
pi(BinderInfo::Default, "A", type0(), type0())
}
pub fn trace_prefix_ty() -> Expr {
pi(
BinderInfo::Default,
"A",
type0(),
arrow(list_ty(bvar(0)), arrow(list_ty(bvar(1)), prop())),
)
}
pub fn trace_concat_ty() -> Expr {
pi(
BinderInfo::Default,
"A",
type0(),
arrow(list_ty(bvar(0)), arrow(list_ty(bvar(1)), list_ty(bvar(2)))),
)
}
pub fn plotkin_power_domain_ty() -> Expr {
arrow(type0(), type0())
}
pub fn smyth_power_domain_ty() -> Expr {
arrow(type0(), type0())
}
pub fn hoare_power_domain_ty() -> Expr {
arrow(type0(), type0())
}
pub fn power_domain_unit_ty() -> Expr {
pi(BinderInfo::Default, "D", type0(), arrow(bvar(0), type0()))
}
pub fn power_domain_bind_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
pi(
BinderInfo::Default,
"E",
type0(),
arrow(type0(), arrow(arrow(bvar(1), type0()), type0())),
),
)
}
pub fn hoare_order_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
arrow(type0(), arrow(type0(), prop())),
)
}
pub fn smyth_order_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
arrow(type0(), arrow(type0(), prop())),
)
}
pub fn valuation_ty() -> Expr {
arrow(type0(), type0())
}
pub fn probabilistic_power_domain_ty() -> Expr {
arrow(type0(), type0())
}
pub fn dirac_valuation_ty() -> Expr {
pi(BinderInfo::Default, "D", type0(), arrow(bvar(0), type0()))
}
pub fn valuation_bind_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
pi(
BinderInfo::Default,
"E",
type0(),
arrow(type0(), arrow(arrow(bvar(1), type0()), type0())),
),
)
}
pub fn valuation_leq_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
arrow(type0(), arrow(type0(), prop())),
)
}
pub fn expected_value_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
arrow(type0(), arrow(arrow(bvar(0), nat_ty()), nat_ty())),
)
}
pub fn sub_probability_valuation_ty() -> Expr {
pi(BinderInfo::Default, "D", type0(), arrow(type0(), prop()))
}
pub fn domain_functor_ty() -> Expr {
arrow(type0(), type0())
}
pub fn domain_equation_ty() -> Expr {
arrow(arrow(type0(), type0()), prop())
}
pub fn bilimit_solution_ty() -> Expr {
pi(
BinderInfo::Default,
"F",
arrow(type0(), type0()),
arrow(prop(), type0()),
)
}
pub fn solution_unique_ty() -> Expr {
pi(
BinderInfo::Default,
"F",
arrow(type0(), type0()),
arrow(prop(), prop()),
)
}
pub fn embedding_projection_pair_ty() -> Expr {
arrow(type0(), arrow(type0(), prop()))
}
pub fn bilimit_ty() -> Expr {
type0()
}
pub fn universal_domain_ty() -> Expr {
prop()
}
pub fn scott_top_universal_ty() -> Expr {
prop()
}
pub fn aj_arena_ty() -> Expr {
type0()
}
pub fn aj_game_ty() -> Expr {
type0()
}
pub fn innocent_composition_ty() -> Expr {
pi(
BinderInfo::Default,
"A",
type0(),
pi(
BinderInfo::Default,
"B",
type0(),
pi(
BinderInfo::Default,
"C",
type0(),
arrow(type0(), arrow(type0(), type0())),
),
),
)
}
pub fn copying_lemma_ty() -> Expr {
pi(BinderInfo::Default, "A", type0(), arrow(type0(), prop()))
}
pub fn well_bracketed_compose_ty() -> Expr {
pi(
BinderInfo::Default,
"A",
type0(),
pi(
BinderInfo::Default,
"B",
type0(),
pi(
BinderInfo::Default,
"C",
type0(),
arrow(prop(), arrow(prop(), prop())),
),
),
)
}
pub fn logical_relation_ty() -> Expr {
arrow(arrow(type0(), arrow(type0(), prop())), prop())
}
pub fn fundamental_theorem_lr_ty() -> Expr {
prop()
}
pub fn reynolds_abstraction_ty() -> Expr {
prop()
}
pub fn parametricity_relation_ty() -> Expr {
pi(
BinderInfo::Default,
"tau",
type0(),
arrow(bvar(0), arrow(bvar(1), prop())),
)
}
pub fn log_rel_preservation_ty() -> Expr {
prop()
}
pub fn ideal_completion_ty() -> Expr {
arrow(type0(), type0())
}
pub fn rounded_ideal_ty() -> Expr {
pi(
BinderInfo::Default,
"B",
type0(),
arrow(arrow(bvar(0), prop()), prop()),
)
}
pub fn scott_open_set_ty() -> Expr {
pi(
BinderInfo::Default,
"D",
type0(),
arrow(arrow(bvar(0), prop()), prop()),
)
}
pub fn scott_topology_ty() -> Expr {
pi(BinderInfo::Default, "D", type0(), prop())
}
pub fn basis_scott_topology_ty() -> Expr {
pi(BinderInfo::Default, "D", type0(), prop())
}
pub fn ccc_model_ty() -> Expr {
type0()
}
pub fn ccc_interpretation_ty() -> Expr {
type0()
}
pub fn lccc_model_ty() -> Expr {
type0()
}
pub fn pcf_full_abstraction_ty() -> Expr {
prop()
}
pub fn soundness_ccc_ty() -> Expr {
prop()
}
pub fn completeness_ccc_ty() -> Expr {
prop()
}
pub fn computational_monad_ty() -> Expr {
arrow(arrow(type0(), type0()), prop())
}
pub fn monad_unit_ty() -> Expr {
pi(
BinderInfo::Default,
"T",
arrow(type0(), type0()),
pi(BinderInfo::Default, "A", type0(), arrow(bvar(0), type0())),
)
}
pub fn monad_bind_ty() -> Expr {
pi(
BinderInfo::Default,
"T",
arrow(type0(), type0()),
pi(
BinderInfo::Default,
"A",
type0(),
pi(
BinderInfo::Default,
"B",
type0(),
arrow(type0(), arrow(arrow(bvar(1), type0()), type0())),
),
),
)
}
pub fn monad_laws_ty() -> Expr {
pi(
BinderInfo::Default,
"T",
arrow(type0(), type0()),
arrow(prop(), prop()),
)
}
pub fn moggi_interpretation_ty() -> Expr {
type0()
}
pub fn iso_recursive_type_ty() -> Expr {
arrow(arrow(type0(), type0()), type0())
}
pub fn fold_iso_ty() -> Expr {
pi(BinderInfo::Default, "F", arrow(type0(), type0()), prop())
}
pub fn unfold_iso_ty() -> Expr {
pi(BinderInfo::Default, "F", arrow(type0(), type0()), prop())
}
pub fn equi_recursive_type_ty() -> Expr {
arrow(arrow(type0(), type0()), type0())
}
pub fn mixed_variance_functor_ty() -> Expr {
arrow(arrow(type0(), arrow(type0(), type0())), prop())
}
pub fn cont_type_ty() -> Expr {
arrow(type0(), arrow(type0(), type0()))
}
pub fn cps_transform_ty() -> Expr {
pi(
BinderInfo::Default,
"tau",
type0(),
pi(
BinderInfo::Default,
"R",
type0(),
arrow(bvar(1), arrow(arrow(bvar(2), bvar(2)), bvar(2))),
),
)
}
pub fn double_negation_translation_ty() -> Expr {
arrow(type0(), type0())
}
pub fn callcc_operator_ty() -> Expr {
pi(
BinderInfo::Default,
"tau",
type0(),
pi(
BinderInfo::Default,
"R",
type0(),
arrow(arrow(arrow(bvar(1), bvar(1)), bvar(1)), bvar(1)),
),
)
}
pub fn cps_adequacy_ty() -> Expr {
prop()
}
pub fn computational_adequacy_ty() -> Expr {
prop()
}
pub fn operational_soundness_ty() -> Expr {
prop()
}
pub fn bi_orthogonality_ty() -> Expr {
pi(
BinderInfo::Default,
"tau",
type0(),
arrow(bvar(0), arrow(bvar(1), prop())),
)
}
pub fn reflexive_graph_model_ty() -> Expr {
type0()
}
pub fn pca_ty() -> Expr {
arrow(type0(), prop())
}
pub fn pca_combinator_k_ty() -> Expr {
pi(BinderInfo::Default, "A", type0(), arrow(prop(), bvar(1)))
}
pub fn pca_combinator_s_ty() -> Expr {
pi(BinderInfo::Default, "A", type0(), arrow(prop(), bvar(1)))
}
pub fn realizability_interp_ty() -> Expr {
pi(
BinderInfo::Default,
"A",
type0(),
arrow(prop(), arrow(type0(), arrow(bvar(2), prop()))),
)
}
pub fn kleene_realizability_ty() -> Expr {
prop()
}
pub fn modified_realizability_ty() -> Expr {
prop()
}
pub fn cp_map_ty() -> Expr {
arrow(type0(), arrow(type0(), type0()))
}
pub fn cptp_map_ty() -> Expr {
arrow(type0(), arrow(type0(), type0()))
}
pub fn quantum_channel_ty() -> Expr {
arrow(type0(), arrow(type0(), type0()))
}
pub fn density_matrix_ty() -> Expr {
type0()
}
pub fn quantum_denotation_ty() -> Expr {
type0()
}
pub fn build_denotational_semantics_env() -> Environment {
let mut env = Environment::new();
let axioms: &[(&str, Expr)] = &[
("CPO", cpo_ty()),
("PointedCPO", pointed_cpo_ty()),
("ScottDomain", scott_domain_ty()),
("BoundedLattice", bounded_lattice_ty()),
("CompleteLattice", complete_lattice_ty()),
("IsDirected", is_directed_ty()),
("DirectedSup", directed_sup_ty()),
("LeastElement", least_element_ty()),
("IsCompact", is_compact_ty()),
("WayBelow", way_below_ty()),
("ScottContinuous", scott_continuous_ty()),
("ContinuousFunctionSpace", continuous_function_space_ty()),
("ContinuousId", continuous_id_ty()),
("ContinuousCompose", continuous_compose_ty()),
("IsMonotone", is_monotone_ty()),
(
"ContinuousImpliesMonotone",
continuous_implies_monotone_ty(),
),
("KnasterTarski", knaster_tarski_ty()),
("LeastFixedPoint", least_fixed_point_ty()),
("GreatestFixedPoint", greatest_fixed_point_ty()),
("KleeneFixedPoint", kleene_fixed_point_ty()),
("KleeneChain", kleene_chain_ty()),
("FixedPointInduction", fixed_point_induction_ty()),
("IsAdmissible", is_admissible_ty()),
("PCFType", pcf_type_ty()),
("PCFTerm", pcf_term_ty()),
("SemType", sem_type_ty()),
("SemTerm", sem_term_ty()),
("PCFCtx", pcf_ctx_ty()),
("SemCtx", sem_ctx_ty()),
("PCFFix", pcf_fix_ty()),
("AdequacyThm", adequacy_thm_ty()),
("SoundnessThm", soundness_thm_ty()),
("OperationalEquivalence", operational_equivalence_ty()),
("DenotationalEquivalence", denotational_equivalence_ty()),
("FullAbstraction", full_abstraction_ty()),
("Compositionality", compositionality_ty()),
("FullyAbstractModel", fully_abstract_model_ty()),
("Arena", arena_ty()),
("Move", move_ty()),
("Strategy", strategy_ty()),
("InnocentStrategy", innocent_strategy_ty()),
("WellBracketed", well_bracketed_ty()),
("StrategyCompose", strategy_compose_ty()),
("Play", play_ty()),
("PView", p_view_ty()),
("OView", o_view_ty()),
("GameModel", game_model_ty()),
("GameFullAbstraction", game_full_abstraction_ty()),
("Trace", trace_ty()),
("TraceSemantics", trace_semantics_ty()),
("TraceEquivalence", trace_equivalence_ty()),
("TraceInclusion", trace_inclusion_ty()),
("InfiniteTrace", infinite_trace_ty()),
("TracePrefix", trace_prefix_ty()),
("TraceConcat", trace_concat_ty()),
("PlotkinPowerDomain", plotkin_power_domain_ty()),
("SmythPowerDomain", smyth_power_domain_ty()),
("HoarePowerDomain", hoare_power_domain_ty()),
("PowerDomainUnit", power_domain_unit_ty()),
("PowerDomainBind", power_domain_bind_ty()),
("HoareOrder", hoare_order_ty()),
("SmythOrder", smyth_order_ty()),
("Valuation", valuation_ty()),
("ProbabilisticPowerDomain", probabilistic_power_domain_ty()),
("DiracValuation", dirac_valuation_ty()),
("ValuationBind", valuation_bind_ty()),
("ValuationLeq", valuation_leq_ty()),
("ExpectedValue", expected_value_ty()),
("SubProbabilityValuation", sub_probability_valuation_ty()),
("DomainFunctor", domain_functor_ty()),
("DomainEquation", domain_equation_ty()),
("BilimitSolution", bilimit_solution_ty()),
("SolutionUnique", solution_unique_ty()),
("EmbeddingProjectionPair", embedding_projection_pair_ty()),
("Bilimit", bilimit_ty()),
("UniversalDomain", universal_domain_ty()),
("ScottTopUniversal", scott_top_universal_ty()),
("AJArena", aj_arena_ty()),
("AJGame", aj_game_ty()),
("InnocentComposition", innocent_composition_ty()),
("CopyingLemma", copying_lemma_ty()),
("WellBracketedCompose", well_bracketed_compose_ty()),
("LogicalRelation", logical_relation_ty()),
("FundamentalTheoremLR", fundamental_theorem_lr_ty()),
("ReynoldsAbstraction", reynolds_abstraction_ty()),
("ParametricityRelation", parametricity_relation_ty()),
("LogRelPreservation", log_rel_preservation_ty()),
("IdealCompletion", ideal_completion_ty()),
("RoundedIdeal", rounded_ideal_ty()),
("ScottOpenSet", scott_open_set_ty()),
("ScottTopology", scott_topology_ty()),
("BasisScottTopology", basis_scott_topology_ty()),
("CCCModel", ccc_model_ty()),
("CCCInterpretation", ccc_interpretation_ty()),
("LCCCModel", lccc_model_ty()),
("PCFFullAbstraction", pcf_full_abstraction_ty()),
("SoundnessCCC", soundness_ccc_ty()),
("CompletenessCCC", completeness_ccc_ty()),
("ComputationalMonad", computational_monad_ty()),
("MonadUnit", monad_unit_ty()),
("MonadBind", monad_bind_ty()),
("MonadLaws", monad_laws_ty()),
("MoggiInterpretation", moggi_interpretation_ty()),
("IsoRecursiveType", iso_recursive_type_ty()),
("FoldIso", fold_iso_ty()),
("UnfoldIso", unfold_iso_ty()),
("EquiRecursiveType", equi_recursive_type_ty()),
("MixedVarianceFunctor", mixed_variance_functor_ty()),
("ContType", cont_type_ty()),
("CPSTransform", cps_transform_ty()),
(
"DoubleNegationTranslation",
double_negation_translation_ty(),
),
("CallccOperator", callcc_operator_ty()),
("CPSAdequacy", cps_adequacy_ty()),
("ComputationalAdequacy", computational_adequacy_ty()),
("OperationalSoundness", operational_soundness_ty()),
("BiOrthogonality", bi_orthogonality_ty()),
("ReflexiveGraphModel", reflexive_graph_model_ty()),
("PCA", pca_ty()),
("PCACombinatorK", pca_combinator_k_ty()),
("PCACombinatorS", pca_combinator_s_ty()),
("RealizabilityInterp", realizability_interp_ty()),
("KleeneRealizability", kleene_realizability_ty()),
("ModifiedRealizability", modified_realizability_ty()),
("CPMap", cp_map_ty()),
("CPTPMap", cptp_map_ty()),
("QuantumChannel", quantum_channel_ty()),
("DensityMatrix", density_matrix_ty()),
("QuantumDenotation", quantum_denotation_ty()),
];
for (name, ty) in axioms {
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty: ty.clone(),
})
.ok();
}
env
}
pub fn kleene_lfp(f: &MonotoneMap, n: usize) -> usize {
let mut x = 0usize;
for _ in 0..=n {
let fx = f.apply(x);
if fx == x {
return x;
}
x = fx;
}
x
}
pub fn kleene_chain(f: &MonotoneMap, max_steps: usize) -> Vec<usize> {
let mut chain = vec![0usize];
let mut x = 0usize;
for _ in 0..max_steps {
let fx = f.apply(x);
chain.push(fx);
if fx == x {
break;
}
x = fx;
}
chain
}
pub fn pcf_eval(term: &PCFTerm, fuel: u64) -> PCFValue {
if fuel == 0 {
return PCFValue::Bottom;
}
match term {
PCFTerm::Zero => PCFValue::Num(0),
PCFTerm::True => PCFValue::Bool(true),
PCFTerm::False => PCFValue::Bool(false),
PCFTerm::Succ(t) => match pcf_eval(t, fuel - 1) {
PCFValue::Num(n) => PCFValue::Num(n + 1),
_ => PCFValue::Bottom,
},
PCFTerm::Pred(t) => match pcf_eval(t, fuel - 1) {
PCFValue::Num(0) => PCFValue::Num(0),
PCFValue::Num(n) => PCFValue::Num(n - 1),
_ => PCFValue::Bottom,
},
PCFTerm::IsZero(t) => match pcf_eval(t, fuel - 1) {
PCFValue::Num(0) => PCFValue::Bool(true),
PCFValue::Num(_) => PCFValue::Bool(false),
_ => PCFValue::Bottom,
},
PCFTerm::If(cond, tb, fb) => match pcf_eval(cond, fuel - 1) {
PCFValue::Bool(true) => pcf_eval(tb, fuel - 1),
PCFValue::Bool(false) => pcf_eval(fb, fuel - 1),
_ => PCFValue::Bottom,
},
PCFTerm::Lam(body) => PCFValue::Closure(body.clone(), 0),
_ => PCFValue::Bottom,
}
}
pub fn cps_transform_to_string(term: &LambdaTerm, depth: usize) -> String {
let k = format!("k{depth}");
match term {
LambdaTerm::Var(n) => format!("({k} x{n})"),
LambdaTerm::Const(s) => format!("({k} {s})"),
LambdaTerm::Lam(body) => {
let inner = cps_transform_to_string(body, depth + 2);
format!("({k} (lam x{}. lam k{}. {inner}))", depth + 1, depth + 2)
}
LambdaTerm::App(f, x) => {
let x_cps = cps_transform_to_string(x, depth + 2);
let f_cont = format!(
"(lam f{}. (lam v{}. (f{} v{} {k})))",
depth + 1,
depth + 2,
depth + 1,
depth + 2
);
format!(
"{} /* arg={x_cps} */",
cps_transform_with_cont(f, depth + 1, &f_cont)
)
}
}
}
pub fn cps_transform_with_cont(term: &LambdaTerm, depth: usize, cont: &str) -> String {
match term {
LambdaTerm::Var(n) => format!("({cont} x{n})"),
LambdaTerm::Const(s) => format!("({cont} {s})"),
LambdaTerm::Lam(body) => {
let inner = cps_transform_to_string(body, depth + 2);
format!("({cont} (lam x{}. lam k{}. {inner}))", depth + 1, depth + 2)
}
LambdaTerm::App(f, x) => {
let x_cps = cps_transform_to_string(x, depth + 2);
let f_cont = format!(
"(lam f{}. (lam v{}. (f{} v{} {cont})))",
depth + 1,
depth + 2,
depth + 1,
depth + 2
);
format!(
"{} /* arg={x_cps} */",
cps_transform_with_cont(f, depth + 1, &f_cont)
)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_build_denotational_semantics_env() {
let env = build_denotational_semantics_env();
assert!(env.get(&Name::str("CPO")).is_some());
assert!(env.get(&Name::str("KnasterTarski")).is_some());
assert!(env.get(&Name::str("KleeneFixedPoint")).is_some());
assert!(env.get(&Name::str("FullAbstraction")).is_some());
assert!(env.get(&Name::str("Arena")).is_some());
assert!(env.get(&Name::str("Valuation")).is_some());
assert!(env.get(&Name::str("DomainEquation")).is_some());
assert!(env.get(&Name::str("BilimitSolution")).is_some());
}
#[test]
fn test_partial_order_validity() {
let po = FinitePartialOrder::discrete(4);
assert!(po.is_valid());
let flat = FinitePartialOrder::flat(3);
assert!(flat.is_valid());
}
#[test]
fn test_partial_order_lub() {
let flat = FinitePartialOrder::flat(3);
assert_eq!(flat.lub(0, 1), Some(1));
assert_eq!(flat.lub(1, 1), Some(1));
}
#[test]
fn test_kleene_chain_and_lfp() {
let f = MonotoneMap::new(vec![1, 1]);
let chain = kleene_chain(&f, 10);
assert_eq!(chain[0], 0);
assert_eq!(chain[1], 1);
assert_eq!(chain[2], 1);
let lfp = kleene_lfp(&f, 10);
assert_eq!(lfp, 1);
}
#[test]
fn test_pcf_type_names() {
assert_eq!(PCFType::Nat.name(), "Nat");
assert_eq!(PCFType::Bool.name(), "Bool");
let arr = PCFType::arrow(PCFType::Nat, PCFType::Bool);
assert_eq!(arr.name(), "(Nat → Bool)");
}
#[test]
fn test_pcf_eval_basic() {
let t = PCFTerm::Succ(Box::new(PCFTerm::Succ(Box::new(PCFTerm::Zero))));
assert_eq!(pcf_eval(&t, 100), PCFValue::Num(2));
let pred_zero = PCFTerm::Pred(Box::new(PCFTerm::Zero));
assert_eq!(pcf_eval(&pred_zero, 100), PCFValue::Num(0));
let iszero = PCFTerm::IsZero(Box::new(PCFTerm::Zero));
assert_eq!(pcf_eval(&iszero, 100), PCFValue::Bool(true));
}
#[test]
fn test_trace_operations() {
let t1: Trace<&str> = Trace::new(vec!["a", "b"]);
let t2: Trace<&str> = Trace::new(vec!["c"]);
let t3 = t1.concat(&t2);
assert_eq!(t3.actions, vec!["a", "b", "c"]);
assert!(t1.is_prefix_of(&t3));
assert!(!t2.is_prefix_of(&t3));
let empty: Trace<&str> = Trace::empty();
assert!(empty.is_prefix_of(&t1));
}
#[test]
fn test_valuation_sub_probability() {
let v = FiniteValuation::dirac("x");
assert!(v.is_sub_probability());
assert!((v.total_mass() - 1.0).abs() < 1e-9);
let w = FiniteValuation::dirac("y");
let mixed = v.mix(&w, 0.5);
assert!(mixed.is_sub_probability());
assert!((mixed.total_mass() - 1.0).abs() < 1e-9);
}
#[test]
fn test_innocent_strategy() {
let mut strat = InnocentStrategy::new();
strat.add_response(vec![0], 1);
strat.add_response(vec![0, 2], 3);
assert_eq!(strat.respond(&[0]), Some(1));
assert_eq!(strat.respond(&[0, 2]), Some(3));
assert_eq!(strat.respond(&[99]), None);
assert_eq!(strat.size(), 2);
}
#[test]
fn test_new_axioms_registered() {
let env = build_denotational_semantics_env();
assert!(env.get(&Name::str("AJArena")).is_some());
assert!(env.get(&Name::str("AJGame")).is_some());
assert!(env.get(&Name::str("InnocentComposition")).is_some());
assert!(env.get(&Name::str("CopyingLemma")).is_some());
assert!(env.get(&Name::str("WellBracketedCompose")).is_some());
assert!(env.get(&Name::str("LogicalRelation")).is_some());
assert!(env.get(&Name::str("FundamentalTheoremLR")).is_some());
assert!(env.get(&Name::str("ReynoldsAbstraction")).is_some());
assert!(env.get(&Name::str("ParametricityRelation")).is_some());
assert!(env.get(&Name::str("LogRelPreservation")).is_some());
assert!(env.get(&Name::str("IdealCompletion")).is_some());
assert!(env.get(&Name::str("RoundedIdeal")).is_some());
assert!(env.get(&Name::str("ScottOpenSet")).is_some());
assert!(env.get(&Name::str("ScottTopology")).is_some());
assert!(env.get(&Name::str("BasisScottTopology")).is_some());
assert!(env.get(&Name::str("CCCModel")).is_some());
assert!(env.get(&Name::str("CCCInterpretation")).is_some());
assert!(env.get(&Name::str("LCCCModel")).is_some());
assert!(env.get(&Name::str("PCFFullAbstraction")).is_some());
assert!(env.get(&Name::str("SoundnessCCC")).is_some());
assert!(env.get(&Name::str("CompletenessCCC")).is_some());
assert!(env.get(&Name::str("ComputationalMonad")).is_some());
assert!(env.get(&Name::str("MonadUnit")).is_some());
assert!(env.get(&Name::str("MonadBind")).is_some());
assert!(env.get(&Name::str("MonadLaws")).is_some());
assert!(env.get(&Name::str("MoggiInterpretation")).is_some());
assert!(env.get(&Name::str("IsoRecursiveType")).is_some());
assert!(env.get(&Name::str("FoldIso")).is_some());
assert!(env.get(&Name::str("UnfoldIso")).is_some());
assert!(env.get(&Name::str("EquiRecursiveType")).is_some());
assert!(env.get(&Name::str("MixedVarianceFunctor")).is_some());
assert!(env.get(&Name::str("ContType")).is_some());
assert!(env.get(&Name::str("CPSTransform")).is_some());
assert!(env.get(&Name::str("DoubleNegationTranslation")).is_some());
assert!(env.get(&Name::str("CallccOperator")).is_some());
assert!(env.get(&Name::str("CPSAdequacy")).is_some());
assert!(env.get(&Name::str("ComputationalAdequacy")).is_some());
assert!(env.get(&Name::str("OperationalSoundness")).is_some());
assert!(env.get(&Name::str("BiOrthogonality")).is_some());
assert!(env.get(&Name::str("ReflexiveGraphModel")).is_some());
assert!(env.get(&Name::str("PCA")).is_some());
assert!(env.get(&Name::str("PCACombinatorK")).is_some());
assert!(env.get(&Name::str("PCACombinatorS")).is_some());
assert!(env.get(&Name::str("RealizabilityInterp")).is_some());
assert!(env.get(&Name::str("KleeneRealizability")).is_some());
assert!(env.get(&Name::str("ModifiedRealizability")).is_some());
assert!(env.get(&Name::str("CPMap")).is_some());
assert!(env.get(&Name::str("CPTPMap")).is_some());
assert!(env.get(&Name::str("QuantumChannel")).is_some());
assert!(env.get(&Name::str("DensityMatrix")).is_some());
assert!(env.get(&Name::str("QuantumDenotation")).is_some());
}
#[test]
fn test_logical_relation_basic() {
let mut lr = LogicalRelation::new();
lr.add("Nat", 0, 0);
lr.add("Nat", 1, 1);
lr.add("Nat", 2, 2);
assert!(lr.relates("Nat", 0, 0));
assert!(!lr.relates("Nat", 0, 1));
assert_eq!(lr.size("Nat"), 3);
assert!(lr.is_reflexive_on("Nat", 3));
assert!(lr.is_symmetric_on("Nat"));
}
#[test]
fn test_logical_relation_asymmetric() {
let mut lr = LogicalRelation::new();
lr.add("Bool", 0, 1);
assert!(!lr.is_symmetric_on("Bool"));
}
#[test]
fn test_lambda_term_size_and_free_vars() {
let id = LambdaTerm::lam(LambdaTerm::var(0));
assert_eq!(id.size(), 2);
let ap = LambdaTerm::app(LambdaTerm::cst("f"), LambdaTerm::var(0));
assert_eq!(ap.size(), 3);
assert!(LambdaTerm::var(0).has_free_var(0, 0));
assert!(!id.has_free_var(0, 0));
}
#[test]
fn test_cps_transform_produces_output() {
let v = LambdaTerm::var(0);
let s = cps_transform_to_string(&v, 0);
assert!(!s.is_empty());
assert!(s.contains("k0") && s.contains("x0"));
let c = LambdaTerm::cst("zero");
let sc = cps_transform_to_string(&c, 1);
assert!(sc.contains("k1") && sc.contains("zero"));
assert!(!cps_transform_to_string(&LambdaTerm::lam(LambdaTerm::var(0)), 0).is_empty());
}
#[test]
fn test_kleene_pca_laws() {
let pca = KleenePCA::with_ks();
assert!(pca.check_k_law(), "K law must hold");
assert!(pca.check_i_law(), "I law must hold");
assert!(pca.lookup("K").is_some());
assert!(pca.lookup("S").is_some());
assert!(pca.lookup("I").is_some());
}
#[test]
fn test_kleene_pca_add_element() {
let mut pca = KleenePCA::with_ks();
let idx = pca.add_element("custom");
assert!(idx >= 3);
assert_eq!(pca.lookup("custom"), Some(idx));
pca.define_app(idx, 0, 1);
assert_eq!(pca.apply(idx, 0), Some(1));
assert_eq!(pca.apply(idx, 1), None);
}
#[test]
fn test_scott_open_set_operations() {
let open = ScottOpen::new(5, [1, 2, 3]);
assert!(open.is_scott_open());
assert!(open.contains(1) && open.contains(2));
assert!(!open.contains(0) && !open.contains(4));
let top = ScottOpen::top(5);
assert!(top.is_scott_open() && top.elements.len() == 4);
let empty = ScottOpen::empty(5);
assert!(empty.is_scott_open() && empty.elements.is_empty());
assert_eq!(open.union(&empty).elements, vec![1, 2, 3]);
assert_eq!(open.intersection(&top).elements, vec![1, 2, 3]);
assert!(open.characteristic(2) && !open.characteristic(4));
}
#[test]
fn test_maybe_interp_monad_laws() {
let interp = MaybeInterp::new(100);
assert_eq!(interp.eval(&PCFTerm::Zero), Some(PCFValue::Num(0)));
assert_eq!(MaybeInterp::new(0).eval(&PCFTerm::Zero), None);
let v = MaybeInterp::ret(PCFValue::Num(7));
assert_eq!(v, Some(PCFValue::Num(7)));
let bound = MaybeInterp::bind(v, |x| match x {
PCFValue::Num(n) => Some(PCFValue::Num(n * 2)),
_ => None,
});
assert_eq!(bound, Some(PCFValue::Num(14)));
assert_eq!(MaybeInterp::bind(None, |_| Some(PCFValue::Num(99))), None);
assert_eq!(MaybeInterp::guard(true), Some(()));
assert_eq!(MaybeInterp::guard(false), None);
let mapped = MaybeInterp::map(Some(PCFValue::Num(3)), |v| match v {
PCFValue::Num(n) => PCFValue::Num(n + 1),
other => other,
});
assert_eq!(mapped, Some(PCFValue::Num(4)));
let succ_zero = PCFTerm::Succ(Box::new(PCFTerm::Zero));
assert_eq!(
interp.seq(&PCFTerm::Zero, &succ_zero),
Some(PCFValue::Num(1))
);
}
}