logicaffeine_kernel/interface/
repl.rs1use super::command::Command;
6use super::command_parser::parse_command;
7use super::error::InterfaceError;
8use crate::prelude::StandardLibrary;
9use crate::{infer_type, normalize, Context, Term};
10
11pub struct Repl {
15 ctx: Context,
16}
17
18impl Repl {
19 pub fn new() -> Self {
21 let mut ctx = Context::new();
22 StandardLibrary::register(&mut ctx);
23 Self { ctx }
24 }
25
26 pub fn execute(&mut self, input: &str) -> Result<String, InterfaceError> {
30 let cmd = parse_command(input)?;
31
32 match cmd {
33 Command::Definition { name, ty, body, is_hint } => {
34 let inferred_ty = infer_type(&self.ctx, &body)?;
36
37 let ty = ty.unwrap_or(inferred_ty);
39
40 self.ctx.add_definition(name.clone(), ty, body);
42
43 if is_hint {
45 self.ctx.add_hint(&name);
46 }
47
48 Ok(String::new()) }
50
51 Command::Check(term) => {
52 let ty = infer_type(&self.ctx, &term)?;
54 Ok(format!("{} : {}", term, ty))
55 }
56
57 Command::Eval(term) => {
58 let _ = infer_type(&self.ctx, &term)?;
60
61 let result = normalize(&self.ctx, &term);
63 Ok(format!("{}", result))
64 }
65
66 Command::Inductive {
67 name,
68 params,
69 sort,
70 constructors,
71 } => {
72 let poly_sort = build_polymorphic_sort(¶ms, sort);
74
75 self.ctx.add_inductive(&name, poly_sort);
77
78 for (ctor_name, ctor_ty) in constructors {
80 let poly_ctor_ty = build_polymorphic_constructor(¶ms, ctor_ty);
85 self.ctx.add_constructor(&ctor_name, &name, poly_ctor_ty);
86 }
87
88 Ok(String::new()) }
90 }
91 }
92
93 pub fn context(&self) -> &Context {
95 &self.ctx
96 }
97
98 pub fn context_mut(&mut self) -> &mut Context {
100 &mut self.ctx
101 }
102}
103
104impl Default for Repl {
105 fn default() -> Self {
106 Self::new()
107 }
108}
109
110fn build_polymorphic_sort(params: &[(String, Term)], base_sort: Term) -> Term {
115 params.iter().rev().fold(base_sort, |body, (name, ty)| {
117 Term::Pi {
118 param: name.clone(),
119 param_type: Box::new(ty.clone()),
120 body_type: Box::new(body),
121 }
122 })
123}
124
125fn build_polymorphic_constructor(params: &[(String, Term)], ctor_ty: Term) -> Term {
133 if params.is_empty() {
134 return ctor_ty;
135 }
136
137 let param_names: Vec<&str> = params.iter().map(|(n, _)| n.as_str()).collect();
139 let body = substitute_globals_with_vars(&ctor_ty, ¶m_names);
140
141 params.iter().rev().fold(body, |body, (name, ty)| {
143 Term::Pi {
144 param: name.clone(),
145 param_type: Box::new(ty.clone()),
146 body_type: Box::new(body),
147 }
148 })
149}
150
151fn substitute_globals_with_vars(term: &Term, param_names: &[&str]) -> Term {
154 match term {
155 Term::Global(n) if param_names.contains(&n.as_str()) => Term::Var(n.clone()),
156 Term::Global(n) => Term::Global(n.clone()),
157 Term::Var(n) => Term::Var(n.clone()),
158 Term::Sort(u) => Term::Sort(u.clone()),
159 Term::Lit(l) => Term::Lit(l.clone()),
160 Term::App(f, a) => Term::App(
161 Box::new(substitute_globals_with_vars(f, param_names)),
162 Box::new(substitute_globals_with_vars(a, param_names)),
163 ),
164 Term::Lambda { param, param_type, body } => Term::Lambda {
165 param: param.clone(),
166 param_type: Box::new(substitute_globals_with_vars(param_type, param_names)),
167 body: Box::new(substitute_globals_with_vars(body, param_names)),
168 },
169 Term::Pi { param, param_type, body_type } => Term::Pi {
170 param: param.clone(),
171 param_type: Box::new(substitute_globals_with_vars(param_type, param_names)),
172 body_type: Box::new(substitute_globals_with_vars(body_type, param_names)),
173 },
174 Term::Fix { name, body } => Term::Fix {
175 name: name.clone(),
176 body: Box::new(substitute_globals_with_vars(body, param_names)),
177 },
178 Term::Match { discriminant, motive, cases } => Term::Match {
179 discriminant: Box::new(substitute_globals_with_vars(discriminant, param_names)),
180 motive: Box::new(substitute_globals_with_vars(motive, param_names)),
181 cases: cases
182 .iter()
183 .map(|c| substitute_globals_with_vars(c, param_names))
184 .collect(),
185 },
186 Term::Hole => Term::Hole, }
188}