1use crate::{
3 dbl::{
4 category::VDblCategory,
5 theory::{DblTheory, DiscreteDblTheory},
6 },
7 zero::name,
8};
9use fnotation::*;
10use nonempty::nonempty;
11use scopeguard::{ScopeGuard, guard};
12use std::fmt::Write;
13
14use tattle::declare_error;
15
16use crate::{
17 tt::{context::*, eval::*, modelgen::*, prelude::*, stx::*, toplevel::*, val::*},
18 zero::QualifiedName,
19};
20
21pub enum TopElabResult {
23 Declaration(TopVarName, TopDecl),
25 Output(String),
27}
28
29pub struct TopElaborator {
33 current_theory: Option<Theory>,
34 reporter: Reporter,
35}
36
37impl TopElaborator {
38 pub fn new(reporter: Reporter) -> Self {
40 Self {
41 current_theory: None,
42 reporter,
43 }
44 }
45
46 fn bare_def<'c>(&self, n: &FNtn<'c>) -> Option<(TopVarName, &'c FNtn<'c>)> {
47 match n.ast0() {
48 App2(L(_, Keyword(":=")), L(_, Var(name)), tn) => {
49 Some((NameSegment::Text(ustr(name)), tn))
50 }
51 _ => None,
52 }
53 }
54
55 fn annotated_def<'c>(
56 &self,
57 n: &FNtn<'c>,
58 ) -> Option<(TopVarName, Option<&'c [&'c FNtn<'c>]>, &'c FNtn<'c>, &'c FNtn<'c>)> {
59 match n.ast0() {
60 App2(L(_, Keyword(":=")), L(_, App2(L(_, Keyword(":")), head_n, annotn)), valn) => {
61 match head_n.ast0() {
62 App1(L(_, Var(name)), L(_, Tuple(args))) => {
63 Some((name_seg(*name), Some(args.as_slice()), annotn, valn))
64 }
65 Var(name) => Some((name_seg(*name), None, annotn, valn)),
66 _ => None,
67 }
68 }
69 _ => None,
70 }
71 }
72
73 fn expr_with_context<'c>(&self, n: &'c FNtn<'c>) -> (&'c [&'c FNtn<'c>], &'c FNtn<'c>) {
74 match n.ast0() {
75 App1(L(_, Tuple(ctx_elems)), n) => (ctx_elems.as_slice(), n),
76 _ => (&[], n),
77 }
78 }
79
80 fn get_theory(&self, loc: Loc) -> Option<Theory> {
81 let Some(theory) = &self.current_theory else {
82 return self.error(
83 loc,
84 "have not yet set a theory, set a theory via `set_theory <THEORY_NAME>`",
85 );
86 };
87 Some(theory.clone())
88 }
89
90 fn elaborator<'a>(&self, theory: &Theory, toplevel: &'a Toplevel) -> Elaborator<'a> {
91 Elaborator::new(theory.clone(), self.reporter.clone(), toplevel)
92 }
93
94 fn error<T>(&self, loc: Loc, msg: impl Into<String>) -> Option<T> {
95 self.reporter.error(loc, ELAB_ERROR, msg.into());
96 None
97 }
98
99 pub fn elab(&mut self, toplevel: &Toplevel, tn: &FNtnTop) -> Option<TopElabResult> {
101 match tn.name {
102 "set_theory" => match tn.body.ast0() {
103 Var(theory_name) => match toplevel.theory_library.get(&name(*theory_name)) {
104 Some(theory) => {
105 self.current_theory = Some(theory.clone());
106 Some(TopElabResult::Output(format!("set theory to {}", theory_name)))
107 }
108 None => self.error(tn.loc, format!("{theory_name} not found")),
109 },
110 _ => self.error(tn.loc, "expected a theory name"),
111 },
112 "type" => {
113 let theory = self.get_theory(tn.loc)?;
114 let (name, ty_n) = self.bare_def(tn.body).or_else(|| {
115 self.error(
116 tn.loc,
117 "unknown syntax for type declaration, expected <name> := <type>",
118 )
119 })?;
120 let (ty_s, ty_v) = self.elaborator(&theory, toplevel).ty(ty_n)?;
121 Some(TopElabResult::Declaration(
122 name,
123 TopDecl::Type(Type::new(theory.clone(), ty_s, ty_v)),
124 ))
125 }
126 "def" => {
127 let theory = self.get_theory(tn.loc)?;
128 let (name, args_n, ty_n, tm_n) = self.annotated_def(tn.body).or_else(|| {
129 self.error(
130 tn.loc,
131 "unknown syntax for term declaration, expected <name> : <type> := <term>",
132 )
133 })?;
134 match args_n {
135 Some(args_n) => {
136 let mut elab = self.elaborator(&theory, toplevel);
137 let mut args_stx = IndexMap::new();
138 for arg_n in args_n {
139 let (name, label, ty_s, ty_v) = elab.binding(arg_n)?;
140 args_stx.insert(name, (label, ty_s));
141 elab.intro(name, label, Some(ty_v));
142 }
143 let (ret_ty_s, ret_ty_v) = elab.ty(ty_n)?;
144 let (body_s, _) = elab.chk(&ret_ty_v, tm_n)?;
145 Some(TopElabResult::Declaration(
146 name,
147 TopDecl::Def(Def::new(
148 theory.clone(),
149 args_stx.into(),
150 ret_ty_s,
151 body_s,
152 )),
153 ))
154 }
155 None => {
156 let mut elab = self.elaborator(&theory, toplevel);
157 let (_, ty_v) = elab.ty(ty_n)?;
158 let (tm_s, tm_v) = elab.chk(&ty_v, tm_n)?;
159 Some(TopElabResult::Declaration(
160 name,
161 TopDecl::DefConst(DefConst::new(theory.clone(), tm_s, tm_v, ty_v)),
162 ))
163 }
164 }
165 }
166 "syn" => {
167 let theory = self.get_theory(tn.loc)?;
168 let (ctx_ns, n) = self.expr_with_context(tn.body);
169 let mut elab = self.elaborator(&theory, toplevel);
170 for ctx_n in ctx_ns {
171 let (name, label, _, ty_v) = elab.binding(ctx_n)?;
172 elab.intro(name, label, Some(ty_v));
173 }
174 let (tm_s, _, ty_v) = elab.syn(n)?;
175 Some(TopElabResult::Output(format!(
176 "{tm_s} : {}",
177 elab.evaluator().quote_ty(&ty_v)
178 )))
179 }
180 "norm" => {
181 let theory = self.get_theory(tn.loc)?;
182 let (ctx_ns, n) = self.expr_with_context(tn.body);
183 let mut elab = self.elaborator(&theory, toplevel);
184 for ctx_n in ctx_ns {
185 let (name, label, _, ty_v) = elab.binding(ctx_n)?;
186 elab.intro(name, label, Some(ty_v));
187 }
188 let (_, tm_v, ty_v) = elab.syn(n)?;
189 let eval = elab.evaluator();
190 Some(TopElabResult::Output(format!("{}", eval.quote_tm(&eval.eta(&tm_v, &ty_v)),)))
191 }
192 "chk" => {
193 let theory = self.get_theory(tn.loc)?;
194 let (ctx_ns, n) = self.expr_with_context(tn.body);
195 let mut elab = self.elaborator(&theory, toplevel);
196 for ctx_n in ctx_ns {
197 let (name, label, _, ty_v) = elab.binding(ctx_n)?;
198 elab.intro(name, label, Some(ty_v));
199 }
200 let (tm_n, ty_n) = match n.ast0() {
201 App2(L(_, Keyword(":")), tm_n, ty_n) => (tm_n, ty_n),
202 _ => return elab.error("expected <expr> : <type>"),
203 };
204 let (_, ty_v) = elab.ty(ty_n)?;
205 let (tm_s, _) = elab.chk(&ty_v, tm_n)?;
206 Some(TopElabResult::Output(format!("{tm_s}")))
207 }
208 "generate" => {
209 let theory = self.get_theory(tn.loc)?;
210 let mut elab = self.elaborator(&theory, toplevel);
211 let (_, ty_v) = elab.ty(tn.body)?;
212 let (model, name_translation) = generate(toplevel, &theory, &ty_v);
213 let mut out = String::new();
214 writeln!(&mut out).unwrap();
215 model_output("#/ ", &mut out, &model, &name_translation).unwrap();
216 Some(TopElabResult::Output(out))
217 }
218 _ => self.error(tn.loc, "unknown toplevel declaration"),
219 }
220 }
221}
222
223struct Elaborator<'a> {
224 theory: Theory,
225 reporter: Reporter,
226 toplevel: &'a Toplevel,
227 loc: Option<Loc>,
228 ctx: Context,
229}
230
231struct ElaboratorCheckpoint {
232 loc: Option<Loc>,
233 ctx: ContextCheckpoint,
234}
235
236declare_error!(ELAB_ERROR, "elab", "an error during elaboration");
237
238impl<'a> Elaborator<'a> {
239 fn new(theory: Theory, reporter: Reporter, toplevel: &'a Toplevel) -> Self {
240 Self {
241 theory,
242 reporter,
243 toplevel,
244 loc: None,
245 ctx: Context::new(),
246 }
247 }
248
249 fn dbl_theory(&self) -> &DiscreteDblTheory {
250 &self.theory.definition
251 }
252
253 fn checkpoint(&self) -> ElaboratorCheckpoint {
254 ElaboratorCheckpoint {
255 loc: self.loc,
256 ctx: self.ctx.checkpoint(),
257 }
258 }
259
260 fn reset_to(&mut self, c: ElaboratorCheckpoint) {
261 self.loc = c.loc;
262 self.ctx.reset_to(c.ctx);
263 }
264
265 fn enter<'c>(&'c mut self, loc: Loc) -> ScopeGuard<&'c mut Self, impl FnOnce(&'c mut Self)> {
266 let c = self.checkpoint();
267 self.loc = Some(loc);
268 guard(self, |e| {
269 e.reset_to(c);
270 })
271 }
272
273 fn error<T>(&self, msg: impl Into<String>) -> Option<T> {
274 self.reporter.error_option_loc(self.loc, ELAB_ERROR, msg.into());
275 None
276 }
277
278 fn evaluator(&self) -> Evaluator<'a> {
279 Evaluator::new(self.toplevel, self.ctx.env.clone(), self.ctx.scope.len())
280 }
281
282 fn intro(&mut self, name: VarName, label: LabelSegment, ty: Option<TyV>) -> TmV {
283 let v = TmV::Neu(
284 TmN::var(self.ctx.scope.len().into(), name, label),
285 ty.clone().unwrap_or(TyV::unit()),
286 );
287 let v = if let Some(ty) = &ty {
288 self.evaluator().eta(&v, ty)
289 } else {
290 v
291 };
292 self.ctx.env = self.ctx.env.snoc(v.clone());
293 self.ctx.push_scope(name, label, ty);
294 v
295 }
296
297 fn binding(&mut self, n: &FNtn) -> Option<(VarName, LabelSegment, TyS, TyV)> {
298 let mut elab = self.enter(n.loc());
299 match n.ast0() {
300 App2(L(_, Keyword(":")), L(_, Var(name)), ty_n) => {
301 let (ty_s, ty_v) = elab.ty(ty_n)?;
302 Some((name_seg(*name), label_seg(*name), ty_s, ty_v))
303 }
304 _ => elab.error("unexpected notation for binding"),
305 }
306 }
307
308 fn lookup_ty(&self, name: VarName) -> Option<(TyS, TyV)> {
309 let qname = QualifiedName::single(name);
310 if self.dbl_theory().has_ob(&qname) {
311 Some((TyS::object(qname.clone()), TyV::object(qname)))
312 } else if let Some(d) = self.toplevel.declarations.get(&name) {
313 match d {
314 TopDecl::Type(t) => {
315 if t.theory == self.theory {
316 Some((TyS::topvar(name), t.val.clone()))
317 } else {
318 self.error(format!(
319 "{name} refers to a type in theory {}, expected a type in theory {}",
320 t.theory, self.theory
321 ))
322 }
323 }
324 TopDecl::Def(_) | TopDecl::DefConst(_) => {
325 self.error(format!("{name} refers to a term not a type"))
326 }
327 }
328 } else {
329 self.error(format!("no such type {name} defined"))
330 }
331 }
332
333 fn morphism_ty(&mut self, n: &FNtn) -> Option<(MorphismType, ObjectType, ObjectType)> {
334 let elab = self.enter(n.loc());
335 match n.ast0() {
336 App1(L(_, Keyword("Id")), L(_, Var(name))) => {
337 let qname = QualifiedName::single(name_seg(*name));
338 if elab.dbl_theory().has_ob(&qname) {
339 Some((MorphismType(Path::Id(qname.clone())), qname.clone(), qname))
340 } else {
341 elab.error(format!("no such object type {name}"))
342 }
343 }
344 Var(name) => {
345 let qname = QualifiedName::single(name_seg(*name));
346 let mt = Path::single(qname);
347 let theory = elab.dbl_theory();
348 if theory.has_proarrow(&mt) {
349 let dom = theory.src(&mt);
350 let cod = theory.tgt(&mt);
351 Some((MorphismType(mt), dom, cod))
352 } else {
353 elab.error(format!("no such morphism type {name}"))
354 }
355 }
356 _ => elab.error("unexpected notation for morphism type"),
357 }
358 }
359
360 fn path(&mut self, n: &FNtn) -> Option<Vec<(NameSegment, LabelSegment)>> {
361 let mut elab = self.enter(n.loc());
362 match n.ast0() {
363 Field(f) => Some(vec![(name_seg(*f), label_seg(*f))]),
364 App1(p_n, L(_, Field(f))) => {
365 let mut p = elab.path(p_n)?;
366 p.push((name_seg(*f), label_seg(*f)));
367 Some(p)
368 }
369 _ => elab.error("unexpected notation for path"),
370 }
371 }
372
373 #[allow(clippy::type_complexity)]
374 fn specialization(&mut self, n: &FNtn) -> Option<(Vec<(NameSegment, LabelSegment)>, TyS, TyV)> {
375 let mut elab = self.enter(n.loc());
376 match n.ast0() {
377 App2(L(_, Keyword(":")), p_n, ty_n) => {
378 let p = elab.path(p_n)?;
379 let (ty_s, ty_v) = elab.ty(ty_n)?;
380 Some((p, ty_s, ty_v))
381 }
382 App2(L(_, Keyword(":=")), p_n, tm_n) => {
383 let p = elab.path(p_n)?;
384 let (tm_s, tm_v, ty_v) = elab.syn(tm_n)?;
385 Some((p, TyS::sing(elab.evaluator().quote_ty(&ty_v), tm_s), TyV::sing(ty_v, tm_v)))
386 }
387 _ => elab.error("unexpected notation for specialization"),
388 }
389 }
390
391 fn ty(&mut self, n: &FNtn) -> Option<(TyS, TyV)> {
392 let mut elab = self.enter(n.loc());
393 match n.ast0() {
394 Var(name) => elab.lookup_ty(name_seg(*name)),
395 Keyword("Unit") => Some((TyS::unit(), TyV::unit())),
396 App1(L(_, Prim("sing")), tm_n) => {
397 let (tm_s, tm_v, ty_v) = elab.syn(tm_n)?;
398 Some((TyS::sing(elab.evaluator().quote_ty(&ty_v), tm_s), TyV::sing(ty_v, tm_v)))
399 }
400 App1(mt_n, L(_, Tuple(domcod_n))) => {
401 if domcod_n.len() != 2 {
402 return elab.error("expected two arguments for morphism type");
403 }
404 let (mt, dom_ty, cod_ty) = elab.morphism_ty(mt_n)?;
405 let (dom_s, dom_v) = elab.chk(&TyV::object(dom_ty.clone()), domcod_n[0])?;
406 let (cod_s, cod_v) = elab.chk(&TyV::object(cod_ty.clone()), domcod_n[1])?;
407 Some((
408 TyS::morphism(mt.clone(), dom_s, cod_s),
409 TyV::morphism(mt.clone(), dom_v, cod_v),
410 ))
411 }
412 Tuple(field_ns) => {
413 let mut field_ty0s = Vec::<(FieldName, (LabelSegment, Ty0))>::new();
414 let mut field_ty_vs = Vec::<(FieldName, (LabelSegment, TyV))>::new();
415 let mut failed = false;
416 let self_var = elab.intro(name_seg("self"), label_seg("self"), None).as_neu();
417 let c = elab.checkpoint();
418 for field_n in field_ns.iter() {
419 elab.loc = Some(field_n.loc());
420 let Some((name, label, ty_n)) = (match field_n.ast0() {
421 App2(L(_, Keyword(":")), L(_, Var(name)), ty_n) => {
422 Some((name_seg(*name), label_seg(*name), ty_n))
423 }
424 _ => elab.error("expected fields in the form <name> : <type>"),
425 }) else {
426 println!("failed");
427 failed = true;
428 continue;
429 };
430 let Some((_, ty_v)) = elab.ty(ty_n) else {
431 failed = true;
432 continue;
433 };
434 field_ty0s.push((name, (label, ty_v.ty0())));
435 field_ty_vs.push((name, (label, ty_v.clone())));
436 elab.ctx.push_scope(name, label, Some(ty_v.clone()));
437 elab.ctx.env =
438 elab.ctx.env.snoc(TmV::Neu(TmN::proj(self_var.clone(), name, label), ty_v));
439 }
440 if failed {
441 return None;
442 }
443 elab.reset_to(c);
444 let field_tys: Row<_> = field_ty_vs
445 .iter()
446 .map(|(name, (label, ty_v))| (*name, (*label, elab.evaluator().quote_ty(ty_v))))
447 .collect();
448 let field_ty0s: Row<_> = field_ty0s.into_iter().collect();
449 let r_s = RecordS::new(field_ty0s.clone(), field_tys.clone());
450 let r_v = RecordV::new(field_ty0s, elab.ctx.env.clone(), field_tys, Dtry::empty());
451 Some((TyS::record(r_s), TyV::record(r_v)))
452 }
453 App2(L(_, Keyword("&")), ty_n, L(_, Tuple(specialization_ns))) => {
454 let (ty_s, mut ty_v) = elab.ty(ty_n)?;
455 let mut specializations = Vec::new();
456 for specialization_n in specialization_ns.iter() {
463 elab.loc = Some(specialization_n.loc());
464 let (path, sty_s, sty_v) = elab.specialization(specialization_n)?;
465 match elab.evaluator().try_specialize(&ty_v, &path, sty_v) {
466 Ok(specialized) => {
467 ty_v = specialized;
468 specializations.push((path, sty_s));
469 }
470 Err(s) => {
471 return elab.error(format!("Failed to specialize:\n... because {s}"));
472 }
473 }
474 }
475 Some((TyS::specialize(ty_s, specializations), ty_v))
476 }
477 _ => elab.error("unexpected notation for type"),
478 }
479 }
480
481 fn lookup_tm(&mut self, name: Ustr) -> Option<(TmS, TmV, TyV)> {
482 let label = label_seg(name);
483 let name = name_seg(name);
484 if let Some((i, _, ty)) = self.ctx.lookup(name) {
485 Some((
486 TmS::var(i, name, label),
487 self.ctx.env.get(*i).unwrap().clone(),
488 ty.clone().unwrap(),
489 ))
490 } else if let Some(d) = self.toplevel.lookup(name) {
491 match d {
492 TopDecl::Type(_) => self.error(format!("{name} refers type, not term")),
493 TopDecl::DefConst(d) => Some((TmS::topvar(name), d.val.clone(), d.ty.clone())),
494 TopDecl::Def(_) => self.error(format!("{name} must be applied to arguments")),
495 }
496 } else {
497 self.error(format!("no such variable {name}"))
498 }
499 }
500
501 fn syn(&mut self, n: &FNtn) -> Option<(TmS, TmV, TyV)> {
502 let mut elab = self.enter(n.loc());
503 match n.ast0() {
504 Var(name) => elab.lookup_tm(ustr(name)),
505 App1(tm_n, L(_, Field(f))) => {
506 let (tm_s, tm_v, ty_v) = elab.syn(tm_n)?;
507 let TyV_::Record(r) = &*ty_v else {
508 return elab.error("can only project from record type");
509 };
510 let label = label_seg(*f);
511 let f = name_seg(*f);
512 if !r.fields1.has(f) {
513 return elab.error(format!("no such field {f}"));
514 }
515 Some((
516 TmS::proj(tm_s, f, label),
517 elab.evaluator().proj(&tm_v, f, label),
518 elab.evaluator().field_ty(&ty_v, &tm_v, f),
519 ))
520 }
521 App1(L(_, Prim("id")), ob_n) => {
522 let (ob_s, ob_v, ob_t) = elab.syn(ob_n)?;
523 let TyV_::Object(ot) = &*ob_t else {
524 return elab.error("can only apply @id to objects");
525 };
526 Some((
527 TmS::id(ob_s),
528 TmV::Tt,
529 TyV::morphism(MorphismType(Path::Id(ot.clone())), ob_v.clone(), ob_v),
530 ))
531 }
532 App2(L(_, Keyword("*")), f_n, g_n) => {
533 let (f_s, _, f_ty) = elab.syn(f_n)?;
534 let (g_s, _, g_ty) = elab.syn(g_n)?;
535 let TyV_::Morphism(f_mt, f_dom, f_cod) = &*f_ty else {
536 elab.loc = Some(f_n.loc());
537 return elab.error("expected a morphism");
538 };
539 let TyV_::Morphism(g_mt, g_dom, g_cod) = &*g_ty else {
540 elab.loc = Some(g_n.loc());
541 return elab.error("expected a morphism");
542 };
543 if elab.dbl_theory().tgt(&f_mt.0) != elab.dbl_theory().src(&g_mt.0) {
544 return elab.error("incompatible morphism types");
545 }
546 if let Err(s) = elab.evaluator().equal_tm(f_cod, g_dom) {
547 return elab.error(format!(
548 "codomain {} and domain {} not equal:\n...because {}",
549 elab.evaluator().quote_tm(f_cod),
550 elab.evaluator().quote_tm(g_dom),
551 s.pretty()
552 ));
553 }
554 Some((
555 TmS::compose(f_s, g_s),
556 TmV::Tt,
557 TyV::morphism(
558 MorphismType(
559 elab.dbl_theory()
560 .compose_types(Path::Seq(nonempty![f_mt.0.clone(), g_mt.0.clone()]))
561 .unwrap(),
562 ),
563 f_dom.clone(),
564 g_cod.clone(),
565 ),
566 ))
567 }
568 App1(L(_, Var(tv)), L(_, Tuple(args_n))) => {
569 let tv = name_seg(*tv);
570 let Some(TopDecl::Def(d)) = elab.toplevel.lookup(tv) else {
571 return elab.error(format!("no such toplevel def {tv}"));
572 };
573 let mut arg_stxs = Vec::new();
574 let mut env = Env::nil();
575 if args_n.len() != d.args.len() {
576 return elab.error(format!(
577 "wrong number of args for {tv}, expected {}, got {}",
578 d.args.len(),
579 args_n.len()
580 ));
581 }
582 for (arg_n, (_, (_, arg_ty_s))) in args_n.iter().zip(d.args.iter()) {
583 let arg_ty_v = elab.evaluator().with_env(env.clone()).eval_ty(arg_ty_s);
584 let (arg_s, arg_v) = elab.chk(&arg_ty_v, arg_n)?;
585 arg_stxs.push(arg_s);
586 env = env.snoc(arg_v);
587 }
588 let eval = elab.evaluator().with_env(env.clone());
589 Some((TmS::topapp(tv, arg_stxs), eval.eval_tm(&d.body), eval.eval_ty(&d.ret_ty)))
590 }
591 Tag("tt") => Some((TmS::tt(), TmV::Tt, TyV::unit())),
592 Tuple(_) => elab.error("must check agains a type in order to construct a record"),
593 _ => elab.error("unexpected notation for term"),
594 }
595 }
596
597 fn chk(&mut self, ty: &TyV, n: &FNtn) -> Option<(TmS, TmV)> {
598 let mut elab = self.enter(n.loc());
599 match n.ast0() {
600 Tuple(field_ns) => {
601 let TyV_::Record(r) = &**ty else {
602 return elab.error("must check record former against record type");
603 };
604 if r.fields1.len() != field_ns.len() {
605 return elab.error(format!(
606 "wrong number of fields provided, expected {}, got {}",
607 r.fields1.len(),
608 r.fields0.len(),
609 ));
610 }
611 let mut field_stxs = IndexMap::new();
612 let mut field_vals = IndexMap::new();
613 for (field_n, (name, (label, field_ty_s))) in field_ns.iter().zip(r.fields1.iter())
614 {
615 elab.loc = Some(field_n.loc());
616 let tm_n = match field_n.ast0() {
617 App2(L(_, Keyword(":=")), L(_, Var(given_name)), field_val_n) => {
618 if name_seg(*given_name) == *name {
619 field_val_n
620 } else {
621 return elab.error(format!("unexpected field {given_name}"));
622 }
623 }
624 _ => {
625 return elab.error("unexpected notation for field");
626 }
627 };
628 let v = TmV::Cons(field_vals.clone().into());
629 let field_ty_v =
630 elab.evaluator().with_env(r.env.snoc(v.clone())).eval_ty(field_ty_s);
631 let (tm_s, tm_v) = elab.chk(&field_ty_v, tm_n)?;
632 field_stxs.insert(*name, (*label, tm_s));
633 field_vals.insert(*name, (*label, tm_v));
634 }
635 Some((TmS::cons(field_stxs.into()), TmV::Cons(field_vals.into())))
636 }
637 _ => {
638 let (tm_s, tm_v, synthed) = elab.syn(n)?;
639 let eval = elab.evaluator();
640 if let Err(e) = eval.convertable_ty(&synthed, ty) {
641 return elab.error(format!(
642 "synthesized type {} does not match expected type {}:\n{}",
643 eval.quote_ty(&synthed),
644 eval.quote_ty(ty),
645 e.pretty()
646 ));
647 }
648 if let Err(e) = eval.element_of(&tm_v, ty) {
649 return elab.error(format!(
650 "evaluated term {} is not an element of specialized type {}:\n{}",
651 eval.quote_tm(&tm_v),
652 eval.quote_ty(ty),
653 e.pretty()
654 ));
655 }
656 Some((tm_s, tm_v))
657 }
658 }
659 }
660}