Skip to content

Commit 53af277

Browse files
Add unified type-system decoration framework and Sigma types
2 parents cbd5ad1 + 26b96ad commit 53af277

30 files changed

Lines changed: 744 additions & 2 deletions

src/rust/agent/explanations.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,18 @@ impl ExplanationGenerator {
301301
self.format_term(body)
302302
)
303303
},
304+
Term::Sigma {
305+
param,
306+
param_type,
307+
body,
308+
} => {
309+
format!(
310+
"∃{}:{}. {}",
311+
param,
312+
self.format_term(param_type),
313+
self.format_term(body)
314+
)
315+
},
304316
Term::App { func, args } => {
305317
let args_str: Vec<_> = args.iter().map(|a| self.format_term(a)).collect();
306318
format!("({} {})", self.format_term(func), args_str.join(" "))

src/rust/aspect.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,9 @@ pub struct TheoremFeatures {
417417
/// Pi type (dependent function) count
418418
pub pi_count: usize,
419419

420+
/// Sigma type (dependent pair) count
421+
pub sigma_count: usize,
422+
420423
/// Universe levels used
421424
pub universe_levels: HashSet<usize>,
422425

@@ -650,6 +653,9 @@ impl RuleBasedTagger {
650653
},
651654
Term::Pi {
652655
param_type, body, ..
656+
}
657+
| Term::Sigma {
658+
param_type, body, ..
653659
} => {
654660
self.extract_symbols_recursive(param_type, symbols);
655661
self.extract_symbols_recursive(body, symbols);
@@ -746,6 +752,11 @@ impl AspectTagger for RuleBasedTagger {
746752
total_matches += features.pi_count;
747753
}
748754

755+
if features.sigma_count > 0 {
756+
*aspect_counts.entry(Aspect::DependentTypes).or_insert(0) += features.sigma_count;
757+
total_matches += features.sigma_count;
758+
}
759+
749760
if !features.universe_levels.is_empty() {
750761
*aspect_counts.entry(Aspect::Universes).or_insert(0) += 1;
751762
total_matches += 1;
@@ -807,6 +818,13 @@ impl RuleBasedTagger {
807818
self.analyze_term(param_type, features, depth + 1);
808819
self.analyze_term(body, features, depth + 1);
809820
},
821+
Term::Sigma {
822+
param_type, body, ..
823+
} => {
824+
features.sigma_count += 1;
825+
self.analyze_term(param_type, features, depth + 1);
826+
self.analyze_term(body, features, depth + 1);
827+
},
810828
Term::Universe(level) | Term::Type(level) | Term::Sort(level) => {
811829
features.universe_levels.insert(*level);
812830
},

src/rust/core.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
//! Core types and abstractions for ECHIDNA theorem proving
55
6+
use crate::types::TypeInfo;
67
use serde::{Deserialize, Serialize};
78
use std::collections::HashMap;
89
use std::fmt;
@@ -33,6 +34,17 @@ pub enum Term {
3334
body: Box<Term>,
3435
},
3536

37+
/// Dependent pair / sum (Sigma type) Σ(x: A). B
38+
///
39+
/// Represents dependent pairs where the type of the second component may
40+
/// depend on the value of the first. Non-dependent pairs are expressible
41+
/// as `Sigma { body }` where `body` does not mention `param`.
42+
Sigma {
43+
param: String,
44+
param_type: Box<Term>,
45+
body: Box<Term>,
46+
},
47+
3648
/// Type universe at level
3749
Type(usize),
3850

@@ -121,6 +133,13 @@ impl fmt::Display for Term {
121133
} => {
122134
write!(f, "(Π {}: {}. {})", param, param_type, body)
123135
},
136+
Term::Sigma {
137+
param,
138+
param_type,
139+
body,
140+
} => {
141+
write!(f, "(Σ {}: {}. {})", param, param_type, body)
142+
},
124143
Term::Type(level) => write!(f, "Type{}", level),
125144
Term::Sort(level) => write!(f, "Sort{}", level),
126145
Term::Universe(level) => write!(f, "Type{}", level),
@@ -190,6 +209,26 @@ pub struct Hypothesis {
190209

191210
/// Optional body (for definitions)
192211
pub body: Option<Term>,
212+
213+
/// Optional native type-system decoration (multiplicity, effects, modality,
214+
/// refinement, semiring, …). `None` is semantically equivalent to a plain
215+
/// unannotated hypothesis — backends that don't understand the decoration
216+
/// safely ignore it.
217+
#[serde(default, skip_serializing_if = "Option::is_none")]
218+
pub type_info: Option<TypeInfo>,
219+
}
220+
221+
impl Hypothesis {
222+
/// Construct a plain hypothesis with no type decoration.
223+
pub fn new(name: impl Into<String>, ty: Term) -> Self {
224+
Self { name: name.into(), ty, body: None, type_info: None }
225+
}
226+
227+
/// Attach a [`TypeInfo`] decoration.
228+
pub fn with_type_info(mut self, info: TypeInfo) -> Self {
229+
self.type_info = Some(info);
230+
self
231+
}
193232
}
194233

195234
/// Proof context with available premises
@@ -223,13 +262,47 @@ pub struct Definition {
223262
pub name: String,
224263
pub ty: Term,
225264
pub body: Term,
265+
266+
/// Optional native type-system decoration (see [`TypeInfo`]).
267+
#[serde(default, skip_serializing_if = "Option::is_none")]
268+
pub type_info: Option<TypeInfo>,
269+
}
270+
271+
impl Definition {
272+
/// Construct a plain definition with no type decoration.
273+
pub fn new(name: impl Into<String>, ty: Term, body: Term) -> Self {
274+
Self { name: name.into(), ty, body, type_info: None }
275+
}
276+
277+
/// Attach a [`TypeInfo`] decoration.
278+
pub fn with_type_info(mut self, info: TypeInfo) -> Self {
279+
self.type_info = Some(info);
280+
self
281+
}
226282
}
227283

228284
/// A variable declaration
229285
#[derive(Debug, Clone, Serialize, Deserialize)]
230286
pub struct Variable {
231287
pub name: String,
232288
pub ty: Term,
289+
290+
/// Optional native type-system decoration (see [`TypeInfo`]).
291+
#[serde(default, skip_serializing_if = "Option::is_none")]
292+
pub type_info: Option<TypeInfo>,
293+
}
294+
295+
impl Variable {
296+
/// Construct a plain variable with no type decoration.
297+
pub fn new(name: impl Into<String>, ty: Term) -> Self {
298+
Self { name: name.into(), ty, type_info: None }
299+
}
300+
301+
/// Attach a [`TypeInfo`] decoration.
302+
pub fn with_type_info(mut self, info: TypeInfo) -> Self {
303+
self.type_info = Some(info);
304+
self
305+
}
233306
}
234307

235308
/// A proof tactic/command

src/rust/gnn/embeddings.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ fn term_kind_index(term: &Term) -> usize {
350350
Term::Hole(_) => 10,
351351
Term::Meta(_) => 11,
352352
Term::ProverSpecific { .. } => 12,
353+
Term::Sigma { .. } => 13,
353354
}
354355
}
355356

@@ -367,7 +368,8 @@ fn term_depth(term: &Term) -> usize {
367368
let pt = param_type.as_ref().map(|t| term_depth(t)).unwrap_or(0);
368369
1 + pt.max(term_depth(body))
369370
}
370-
Term::Pi { param_type, body, .. } => {
371+
Term::Pi { param_type, body, .. }
372+
| Term::Sigma { param_type, body, .. } => {
371373
1 + term_depth(param_type).max(term_depth(body))
372374
}
373375
Term::Let { ty, value, body, .. } => {
@@ -394,7 +396,7 @@ fn term_arity(term: &Term) -> usize {
394396
| Term::Universe(_) | Term::Hole(_) | Term::Meta(_) | Term::ProverSpecific { .. } => 0,
395397
Term::App { args, .. } => 1 + args.len(), // func + args
396398
Term::Lambda { param_type, .. } => if param_type.is_some() { 2 } else { 1 },
397-
Term::Pi { .. } => 2, // param_type + body
399+
Term::Pi { .. } | Term::Sigma { .. } => 2, // param_type + body
398400
Term::Let { ty, .. } => if ty.is_some() { 3 } else { 2 },
399401
Term::Match { branches, .. } => 1 + branches.len(),
400402
Term::Fix { ty, .. } => if ty.is_some() { 2 } else { 1 },

src/rust/gnn/graph.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,23 @@ impl ProofGraphBuilder {
372372
}
373373
Some(nid)
374374
}
375+
Term::Sigma {
376+
param,
377+
param_type,
378+
body,
379+
} => {
380+
let label = format!("sigma_{}", param);
381+
let nid = self.add_node(NodeKind::Binder, &label, depth);
382+
self.add_edge(parent_id, nid, EdgeKind::Contains, 1.0);
383+
384+
if let Some(tid) = self.expand_term(param_type, nid, depth + 1) {
385+
self.add_edge(nid, tid, EdgeKind::HasType, 1.0);
386+
}
387+
if let Some(bid) = self.expand_term(body, nid, depth + 1) {
388+
self.add_edge(nid, bid, EdgeKind::BindsOver, 1.0);
389+
}
390+
Some(nid)
391+
}
375392
Term::Type(level) | Term::Sort(level) | Term::Universe(level) => {
376393
let label = format!("Type{}", level);
377394
let nid = self.add_or_get_node(NodeKind::TypeExpr, &label, depth);
@@ -642,6 +659,7 @@ mod tests {
642659
name: "h_nat".to_string(),
643660
ty: Term::Const("Nat".to_string()),
644661
body: None,
662+
type_info: None,
645663
};
646664

647665
let theorem = Theorem {
@@ -687,6 +705,7 @@ mod tests {
687705
variables: vec![Variable {
688706
name: "n".to_string(),
689707
ty: Term::Const("Nat".to_string()),
708+
type_info: None,
690709
}],
691710
},
692711
proof_script: Vec::new(),

src/rust/gnn/guided_search.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ mod tests {
381381
name: "h".to_string(),
382382
ty: Term::Const("Nat".to_string()),
383383
body: None,
384+
type_info: None,
384385
}],
385386
}],
386387
context: Context {
@@ -390,6 +391,7 @@ mod tests {
390391
variables: vec![Variable {
391392
name: "n".to_string(),
392393
ty: Term::Const("Nat".to_string()),
394+
type_info: None,
393395
}],
394396
},
395397
proof_script: Vec::new(),

src/rust/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub mod parsers;
2626
pub mod proof_encoding; // CBOR encoding + proof identity hashing
2727
pub mod proof_search; // Chapel parallel proof search (optional feature)
2828
pub mod provers;
29+
pub mod types; // Native type-system decorations (multiplicity, effects, modality, temporal, semiring, …)
2930
pub mod verification;
3031
#[cfg(feature = "verisim")]
3132
pub mod verisim_bridge; // VeriSimDB 8-modality octad integration

src/rust/provers/abc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ impl AbcBackend {
269269
name: input_name.to_string(),
270270
ty: Term::Const("BLIF_INPUT".to_string()),
271271
body: Term::Const(input_name.to_string()),
272+
type_info: None,
272273
});
273274
}
274275
}

src/rust/provers/acl2.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,18 @@ impl ACL2Backend {
980980
])
981981
}
982982
},
983+
Term::Sigma {
984+
param: _,
985+
param_type,
986+
body,
987+
} => {
988+
// ACL2 has no dependent pairs; approximate with (and A B).
989+
SExp::List(vec![
990+
SExp::Atom("and".to_string()),
991+
self.term_to_sexp(param_type),
992+
self.term_to_sexp(body),
993+
])
994+
},
983995
Term::Let {
984996
name, value, body, ..
985997
} => SExp::List(vec![
@@ -1250,6 +1262,7 @@ impl ProverBackend for ACL2Backend {
12501262
name,
12511263
ty: Term::Universe(0), // ACL2 doesn't have explicit types
12521264
body: body_term,
1265+
type_info: None,
12531266
});
12541267
},
12551268
ACL2Event::Defthm {
@@ -1291,6 +1304,7 @@ impl ProverBackend for ACL2Backend {
12911304
name,
12921305
ty: Term::Universe(0),
12931306
body: value_term,
1307+
type_info: None,
12941308
});
12951309
},
12961310
_ => {},

src/rust/provers/agda.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,16 @@ impl AgdaBackend {
134134
let body_str = self.term_to_agda(body);
135135
format!("({} : {}) → {}", param, param_ty_str, body_str)
136136
},
137+
Term::Sigma {
138+
param,
139+
param_type,
140+
body,
141+
} => {
142+
// Agda: Σ A λ x → B (standard-library)
143+
let param_ty_str = self.term_to_agda(param_type);
144+
let body_str = self.term_to_agda(body);
145+
format!("Σ {} λ {} → {}", param_ty_str, param, body_str)
146+
},
137147
Term::Universe(level) | Term::Type(level) => {
138148
if *level == 0 {
139149
"Set".to_string()
@@ -263,6 +273,7 @@ impl ProverBackend for AgdaBackend {
263273
name: name.clone(),
264274
ty: type_term.clone(),
265275
body: type_term,
276+
type_info: None,
266277
});
267278
},
268279
AgdaDecl::TypeSig { name, ty } => {
@@ -318,6 +329,7 @@ impl ProverBackend for AgdaBackend {
318329
name: param_name,
319330
ty: Term::Universe(0),
320331
body: None,
332+
type_info: None,
321333
});
322334
}
323335
Ok(TacticResult::Success(new_state))

0 commit comments

Comments
 (0)