1use crate::ast;
17use crate::error::*;
18use crate::files::Files;
19use crate::lexer::Pos;
20use crate::log;
21use crate::stablemapset::{StableMap, StableSet};
22use std::collections::BTreeMap;
23use std::collections::BTreeSet;
24use std::collections::HashMap;
25use std::collections::hash_map::Entry;
26use std::fmt;
27
28declare_id!(
29 Sym
31);
32declare_id!(
33 TypeId
35);
36declare_id!(
37 VariantId
39);
40declare_id!(
41 FieldId
43);
44declare_id!(
45 TermId
47);
48declare_id!(
49 RuleId
51);
52declare_id!(
53 VarId
55);
56
57#[derive(Debug)]
61pub struct TypeEnv {
62 pub syms: Vec<String>,
66
67 pub sym_map: StableMap<String, Sym>,
69
70 pub types: Vec<Type>,
74
75 pub type_map: StableMap<Sym, TypeId>,
77
78 pub const_types: StableMap<Sym, TypeId>,
80
81 pub errors: Vec<Error>,
83}
84
85#[derive(Copy, Clone, Debug, PartialEq, Eq)]
87#[repr(u8)]
88pub enum BuiltinType {
89 Bool,
91 Int(IntType),
93}
94
95#[derive(Copy, Clone, Debug, PartialEq, Eq)]
97pub enum IntType {
98 U8,
100 U16,
102 U32,
104 U64,
106 U128,
108 USize,
110 I8,
112 I16,
114 I32,
116 I64,
118 I128,
120 ISize,
122}
123
124impl IntType {
125 pub fn name(&self) -> &'static str {
127 match self {
128 IntType::U8 => "u8",
129 IntType::U16 => "u16",
130 IntType::U32 => "u32",
131 IntType::U64 => "u64",
132 IntType::U128 => "u128",
133 IntType::USize => "usize",
134 IntType::I8 => "i8",
135 IntType::I16 => "i16",
136 IntType::I32 => "i32",
137 IntType::I64 => "i64",
138 IntType::I128 => "i128",
139 IntType::ISize => "isize",
140 }
141 }
142
143 pub fn is_signed(&self) -> bool {
145 match self {
146 IntType::U8
147 | IntType::U16
148 | IntType::U32
149 | IntType::U64
150 | IntType::U128
151 | IntType::USize => false,
152
153 IntType::I8
154 | IntType::I16
155 | IntType::I32
156 | IntType::I64
157 | IntType::I128
158 | IntType::ISize => true,
159 }
160 }
161}
162
163impl fmt::Display for IntType {
164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165 write!(f, "{}", self.name())
166 }
167}
168
169impl BuiltinType {
170 pub const ALL: &'static [Self] = &[
172 Self::Bool,
173 Self::Int(IntType::U8),
174 Self::Int(IntType::U16),
175 Self::Int(IntType::U32),
176 Self::Int(IntType::U64),
177 Self::Int(IntType::U128),
178 Self::Int(IntType::USize),
179 Self::Int(IntType::I8),
180 Self::Int(IntType::I16),
181 Self::Int(IntType::I32),
182 Self::Int(IntType::I64),
183 Self::Int(IntType::I128),
184 Self::Int(IntType::ISize),
185 ];
186
187 pub fn name(&self) -> &'static str {
189 match self {
190 BuiltinType::Bool => "bool",
191 BuiltinType::Int(it) => it.name(),
192 }
193 }
194
195 pub const fn to_usize(&self) -> usize {
197 match self {
198 Self::Bool => 0,
199 Self::Int(ty) => *ty as usize + 1,
200 }
201 }
202}
203
204impl TypeId {
205 pub const fn builtin(builtin: BuiltinType) -> Self {
207 Self(builtin.to_usize())
208 }
209
210 pub const BOOL: Self = Self::builtin(BuiltinType::Bool);
212
213 pub const U8: Self = Self::builtin(BuiltinType::Int(IntType::U8));
215 pub const U16: Self = Self::builtin(BuiltinType::Int(IntType::U16));
217 pub const U32: Self = Self::builtin(BuiltinType::Int(IntType::U32));
219 pub const U64: Self = Self::builtin(BuiltinType::Int(IntType::U64));
221 pub const U128: Self = Self::builtin(BuiltinType::Int(IntType::U128));
223 pub const USIZE: Self = Self::builtin(BuiltinType::Int(IntType::USize));
225
226 pub const I8: Self = Self::builtin(BuiltinType::Int(IntType::I8));
228 pub const I16: Self = Self::builtin(BuiltinType::Int(IntType::I16));
230 pub const I32: Self = Self::builtin(BuiltinType::Int(IntType::I32));
232 pub const I64: Self = Self::builtin(BuiltinType::Int(IntType::I64));
234 pub const I128: Self = Self::builtin(BuiltinType::Int(IntType::I128));
236 pub const ISIZE: Self = Self::builtin(BuiltinType::Int(IntType::ISize));
238}
239
240#[derive(Clone, Debug, PartialEq, Eq)]
242pub enum Type {
243 Builtin(BuiltinType),
245
246 Primitive(TypeId, Sym, Pos),
251
252 Enum {
256 name: Sym,
258 id: TypeId,
260 is_extern: bool,
265 is_nodebug: bool,
269 variants: Vec<Variant>,
271 pos: Pos,
273 },
274
275 Struct {
280 name: Sym,
282 id: TypeId,
284 is_extern: bool,
289 is_nodebug: bool,
293 fields: Fields,
295 pos: Pos,
297 },
298}
299
300impl Type {
301 pub fn id(&self) -> TypeId {
303 match self {
304 Self::Primitive(id, _, _) | Self::Enum { id, .. } | Self::Struct { id, .. } => *id,
305 Self::Builtin(b) => TypeId::builtin(*b),
306 }
307 }
308
309 pub fn name<'a>(&self, tyenv: &'a TypeEnv) -> &'a str {
311 match self {
312 Self::Builtin(ty) => ty.name(),
313 Self::Primitive(_, name, _) | Self::Enum { name, .. } | Type::Struct { name, .. } => {
314 &tyenv.syms[name.index()]
315 }
316 }
317 }
318
319 pub fn pos(&self) -> Option<Pos> {
321 match self {
322 Self::Builtin(..) => None,
323 Self::Primitive(_, _, pos) | Self::Enum { pos, .. } | Type::Struct { pos, .. } => {
324 Some(*pos)
325 }
326 }
327 }
328
329 pub fn is_prim(&self) -> bool {
331 matches!(self, Type::Primitive(..))
332 }
333
334 pub fn is_int(&self) -> bool {
336 matches!(self, Self::Builtin(BuiltinType::Int(_)))
337 }
338}
339
340#[derive(Clone, Debug, PartialEq, Eq)]
342pub struct Variant {
343 pub name: Sym,
345
346 pub fullname: Sym,
351
352 pub id: VariantId,
355
356 pub fields: Fields,
358
359 pub pos: Pos,
361}
362
363#[derive(Clone, PartialEq, Eq, Debug)]
365pub enum Fields {
366 Unit,
368 Struct(StructFields),
370 Tuple(TupleFields),
372}
373
374impl Fields {
375 pub fn types(&self) -> Vec<TypeId> {
377 match self {
378 Fields::Unit => Vec::new(),
379 Fields::Struct(fields) => fields.fields.iter().map(|f| f.ty).collect(),
380 Fields::Tuple(fields) => fields.fields.iter().map(|f| f.ty).collect(),
381 }
382 }
383}
384
385#[derive(Clone, PartialEq, Eq, Debug)]
387pub struct StructFields {
388 pub fields: Vec<StructField>,
390}
391
392#[derive(Clone, Debug, PartialEq, Eq)]
394pub struct StructField {
395 pub name: Sym,
397 pub id: FieldId,
399 pub ty: TypeId,
401}
402
403#[derive(Clone, PartialEq, Eq, Debug)]
405pub struct TupleFields {
406 pub fields: Vec<TupleField>,
408}
409
410#[derive(Clone, Debug, PartialEq, Eq)]
412pub struct TupleField {
413 pub id: FieldId,
415 pub ty: TypeId,
417}
418
419#[derive(Clone, Debug)]
425pub struct TermEnv {
426 pub terms: Vec<Term>,
430
431 pub term_map: StableMap<Sym, TermId>,
433
434 pub rules: Vec<Rule>,
438
439 pub rule_map: StableMap<Sym, RuleId>,
441
442 pub converters: StableMap<(TypeId, TypeId), TermId>,
446
447 pub expand_internal_extractors: bool,
450}
451
452#[derive(Clone, Debug, PartialEq, Eq)]
458pub struct Term {
459 pub id: TermId,
461 pub decl_pos: Pos,
463 pub name: Sym,
465 pub arg_tys: Vec<TypeId>,
467 pub ret_ty: TypeId,
469 pub kind: TermKind,
471}
472
473#[derive(Copy, Clone, Debug, PartialEq, Eq)]
475pub struct TermFlags {
476 pub pure: bool,
478 pub multi: bool,
480 pub partial: bool,
482 pub rec: bool,
484}
485
486impl TermFlags {
487 pub fn on_lhs(mut self) -> Self {
489 self.pure = true;
490 self.partial = true;
491 self
492 }
493}
494
495#[derive(Clone, Debug, PartialEq, Eq)]
497pub enum TermKind {
498 EnumVariant {
500 variant: VariantId,
503 },
504 Struct,
506 Decl {
508 flags: TermFlags,
510 constructor_kind: Option<ConstructorKind>,
512 extractor_kind: Option<ExtractorKind>,
514 },
515}
516
517#[derive(Clone, Debug, PartialEq, Eq)]
519pub enum ConstructorKind {
520 InternalConstructor,
523 ExternalConstructor {
525 name: Sym,
527 },
528}
529
530#[derive(Clone, Debug, PartialEq, Eq)]
532pub enum ExtractorKind {
533 InternalExtractor {
537 template: ast::Pattern,
539 },
540 ExternalExtractor {
542 name: Sym,
544 infallible: bool,
546 pos: Pos,
548 },
549}
550
551#[derive(Clone, Copy, Debug, Eq, PartialEq)]
553pub enum ReturnKind {
554 Plain,
556 Option,
558 Iterator,
560}
561
562#[derive(Clone, Debug)]
564pub struct ExternalSig {
565 pub func_name: String,
567 pub full_name: String,
569 pub param_tys: Vec<TypeId>,
571 pub ret_tys: Vec<TypeId>,
573 pub ret_kind: ReturnKind,
575}
576
577impl Term {
578 pub fn ty(&self) -> TypeId {
580 self.ret_ty
581 }
582
583 fn check_args_count<T>(&self, args: &[T], tyenv: &mut TypeEnv, pos: Pos, sym: &ast::Ident) {
584 if self.arg_tys.len() != args.len() {
585 tyenv.report_error(
586 pos,
587 format!(
588 "Incorrect argument count for term '{}': got {}, expect {}",
589 sym.0,
590 args.len(),
591 self.arg_tys.len()
592 ),
593 );
594 }
595 }
596
597 pub fn is_enum_variant(&self) -> bool {
599 matches!(self.kind, TermKind::EnumVariant { .. })
600 }
601
602 pub fn is_struct(&self) -> bool {
604 matches!(self.kind, TermKind::Struct { .. })
605 }
606
607 pub fn is_partial(&self) -> bool {
609 matches!(
610 self.kind,
611 TermKind::Decl {
612 flags: TermFlags { partial: true, .. },
613 ..
614 }
615 )
616 }
617
618 pub fn is_recursive(&self) -> bool {
620 matches!(
621 self.kind,
622 TermKind::Decl {
623 flags: TermFlags { rec: true, .. },
624 ..
625 }
626 )
627 }
628
629 pub fn has_constructor(&self) -> bool {
631 matches!(
632 self.kind,
633 TermKind::EnumVariant { .. }
634 | TermKind::Struct
635 | TermKind::Decl {
636 constructor_kind: Some(_),
637 ..
638 }
639 )
640 }
641
642 pub fn has_extractor(&self) -> bool {
644 matches!(
645 self.kind,
646 TermKind::EnumVariant { .. }
647 | TermKind::Struct
648 | TermKind::Decl {
649 extractor_kind: Some(_),
650 ..
651 }
652 )
653 }
654
655 pub fn has_external_extractor(&self) -> bool {
657 matches!(
658 self.kind,
659 TermKind::Decl {
660 extractor_kind: Some(ExtractorKind::ExternalExtractor { .. }),
661 ..
662 }
663 )
664 }
665
666 pub fn has_external_constructor(&self) -> bool {
668 matches!(
669 self.kind,
670 TermKind::Decl {
671 constructor_kind: Some(ConstructorKind::ExternalConstructor { .. }),
672 ..
673 }
674 )
675 }
676
677 pub fn has_internal_constructor(&self) -> bool {
679 matches!(
680 self.kind,
681 TermKind::Decl {
682 constructor_kind: Some(ConstructorKind::InternalConstructor { .. }),
683 ..
684 }
685 )
686 }
687
688 pub fn extractor_sig(&self, tyenv: &TypeEnv) -> Option<ExternalSig> {
690 match &self.kind {
691 TermKind::Decl {
692 flags,
693 extractor_kind: Some(kind),
694 ..
695 } => {
696 let (func_name, full_name, infallible) = match kind {
697 ExtractorKind::InternalExtractor { .. } => {
698 let name = format!("extractor_{}", tyenv.syms[self.name.index()]);
699 (name.clone(), name, false)
700 }
701 ExtractorKind::ExternalExtractor {
702 name, infallible, ..
703 } => (
704 tyenv.syms[name.index()].clone(),
705 format!("C::{}", tyenv.syms[name.index()]),
706 *infallible,
707 ),
708 };
709 let ret_kind = if flags.multi {
710 ReturnKind::Iterator
711 } else if infallible {
712 ReturnKind::Plain
713 } else {
714 ReturnKind::Option
715 };
716 Some(ExternalSig {
717 func_name,
718 full_name,
719 param_tys: vec![self.ret_ty],
720 ret_tys: self.arg_tys.clone(),
721 ret_kind,
722 })
723 }
724 _ => None,
725 }
726 }
727
728 pub fn constructor_sig(&self, tyenv: &TypeEnv) -> Option<ExternalSig> {
730 match &self.kind {
731 TermKind::Decl {
732 constructor_kind: Some(kind),
733 flags,
734 ..
735 } => {
736 let (func_name, full_name) = match kind {
737 ConstructorKind::InternalConstructor => {
738 let name = format!("constructor_{}", tyenv.syms[self.name.index()]);
739 (name.clone(), name)
740 }
741 ConstructorKind::ExternalConstructor { name } => (
742 tyenv.syms[name.index()].clone(),
743 format!("C::{}", tyenv.syms[name.index()]),
744 ),
745 };
746 let ret_kind = if flags.multi {
747 ReturnKind::Iterator
748 } else if flags.partial {
749 ReturnKind::Option
750 } else {
751 ReturnKind::Plain
752 };
753 Some(ExternalSig {
754 func_name,
755 full_name,
756 param_tys: self.arg_tys.clone(),
757 ret_tys: vec![self.ret_ty],
758 ret_kind,
759 })
760 }
761 _ => None,
762 }
763 }
764}
765
766#[derive(Clone, Debug)]
768pub struct Rule {
769 pub id: RuleId,
771 pub root_term: TermId,
773 pub args: Vec<Pattern>,
775 pub iflets: Vec<IfLet>,
777 pub rhs: Expr,
780 pub vars: Vec<BoundVar>,
782 pub prio: i64,
784 pub pos: Pos,
786 pub name: Option<Sym>,
788}
789
790#[derive(Clone, Debug)]
792pub struct BoundVar {
793 pub id: VarId,
795 pub name: Sym,
797 pub ty: TypeId,
799 scope: usize,
802}
803
804#[derive(Clone, Debug)]
807pub struct IfLet {
808 pub lhs: Pattern,
811 pub rhs: Expr,
814}
815
816#[derive(Clone, Debug, PartialEq, Eq)]
818pub enum Pattern {
819 BindPattern(TypeId, VarId, Box<Pattern>),
823
824 Var(TypeId, VarId),
827
828 ConstBool(TypeId, bool),
830
831 ConstInt(TypeId, i128),
834
835 ConstPrim(TypeId, Sym),
838
839 Term(TypeId, TermId, Vec<Pattern>),
842
843 Wildcard(TypeId),
845
846 And(TypeId, Vec<Pattern>),
848}
849
850#[derive(Clone, Debug, PartialEq, Eq)]
852pub enum Expr {
853 Term(TypeId, TermId, Vec<Expr>),
855 Var(TypeId, VarId),
857 ConstBool(TypeId, bool),
859 ConstInt(TypeId, i128),
861 ConstPrim(TypeId, Sym),
863 Let {
866 ty: TypeId,
868 bindings: Vec<(VarId, TypeId, Box<Expr>)>,
870 body: Box<Expr>,
872 },
873}
874
875pub trait PatternVisitor {
878 type PatternId: Copy;
880
881 fn add_match_equal(&mut self, a: Self::PatternId, b: Self::PatternId, ty: TypeId);
883 fn add_match_bool(&mut self, input: Self::PatternId, ty: TypeId, bool_val: bool);
885 fn add_match_int(&mut self, input: Self::PatternId, ty: TypeId, int_val: i128);
887 fn add_match_prim(&mut self, input: Self::PatternId, ty: TypeId, val: Sym);
889
890 fn add_match_variant(
893 &mut self,
894 input: Self::PatternId,
895 input_ty: TypeId,
896 arg_tys: &[TypeId],
897 variant: VariantId,
898 ) -> Vec<Self::PatternId>;
899
900 fn add_extract_struct(
903 &mut self,
904 input: Self::PatternId,
905 input_ty: TypeId,
906 arg_tys: &[TypeId],
907 ) -> Vec<Self::PatternId>;
908
909 fn add_extract(
913 &mut self,
914 input: Self::PatternId,
915 input_ty: TypeId,
916 output_tys: Vec<TypeId>,
917 term: TermId,
918 infallible: bool,
919 multi: bool,
920 ) -> Vec<Self::PatternId>;
921}
922
923impl Pattern {
924 pub fn ty(&self) -> TypeId {
926 match *self {
927 Self::BindPattern(t, ..) => t,
928 Self::Var(t, ..) => t,
929 Self::ConstBool(t, ..) => t,
930 Self::ConstInt(t, ..) => t,
931 Self::ConstPrim(t, ..) => t,
932 Self::Term(t, ..) => t,
933 Self::Wildcard(t, ..) => t,
934 Self::And(t, ..) => t,
935 }
936 }
937
938 pub fn visit<V: PatternVisitor>(
940 &self,
941 visitor: &mut V,
942 input: V::PatternId,
943 termenv: &TermEnv,
944 vars: &mut HashMap<VarId, V::PatternId>,
945 ) {
946 match *self {
947 Pattern::BindPattern(_ty, var, ref subpat) => {
948 assert!(!vars.contains_key(&var));
950 vars.insert(var, input);
951 subpat.visit(visitor, input, termenv, vars);
952 }
953 Pattern::Var(ty, var) => {
954 let var_val = vars
956 .get(&var)
957 .copied()
958 .expect("Variable should already be bound");
959 visitor.add_match_equal(input, var_val, ty);
960 }
961 Pattern::ConstBool(ty, value) => visitor.add_match_bool(input, ty, value),
962 Pattern::ConstInt(ty, value) => visitor.add_match_int(input, ty, value),
963 Pattern::ConstPrim(ty, value) => visitor.add_match_prim(input, ty, value),
964 Pattern::Term(ty, term, ref args) => {
965 let termdata = &termenv.terms[term.index()];
967 let arg_values = match &termdata.kind {
968 TermKind::EnumVariant { variant } => {
969 visitor.add_match_variant(input, ty, &termdata.arg_tys, *variant)
970 }
971 TermKind::Struct => visitor.add_extract_struct(input, ty, &termdata.arg_tys),
972 TermKind::Decl {
973 extractor_kind: None,
974 ..
975 } => {
976 panic!("Pattern invocation of undefined term body")
977 }
978 TermKind::Decl {
979 flags,
980 extractor_kind,
981 ..
982 } => {
983 let output_tys = args.iter().map(|arg| arg.ty()).collect();
985
986 let infallible = match extractor_kind {
987 Some(ExtractorKind::ExternalExtractor { infallible, .. }) => {
988 *infallible
989 }
990 _ => false,
991 };
992
993 visitor.add_extract(
995 input,
996 termdata.ret_ty,
997 output_tys,
998 term,
999 infallible && !flags.multi,
1000 flags.multi,
1001 )
1002 }
1003 };
1004 for (pat, val) in args.iter().zip(arg_values) {
1005 pat.visit(visitor, val, termenv, vars);
1006 }
1007 }
1008 Pattern::And(_ty, ref children) => {
1009 for child in children {
1010 child.visit(visitor, input, termenv, vars);
1011 }
1012 }
1013 Pattern::Wildcard(_ty) => {
1014 }
1016 }
1017 }
1018}
1019
1020pub trait ExprVisitor {
1023 type ExprId: Copy;
1025
1026 fn add_const_bool(&mut self, ty: TypeId, val: bool) -> Self::ExprId;
1028 fn add_const_int(&mut self, ty: TypeId, val: i128) -> Self::ExprId;
1030 fn add_const_prim(&mut self, ty: TypeId, val: Sym) -> Self::ExprId;
1032
1033 fn add_create_variant(
1035 &mut self,
1036 inputs: Vec<(Self::ExprId, TypeId)>,
1037 ty: TypeId,
1038 variant: VariantId,
1039 ) -> Self::ExprId;
1040
1041 fn add_create_struct(
1043 &mut self,
1044 inputs: Vec<(Self::ExprId, TypeId)>,
1045 ty: TypeId,
1046 ) -> Self::ExprId;
1047
1048 fn add_construct(
1050 &mut self,
1051 inputs: Vec<(Self::ExprId, TypeId)>,
1052 ty: TypeId,
1053 term: TermId,
1054 pure: bool,
1055 infallible: bool,
1056 multi: bool,
1057 rec: bool,
1058 ) -> Self::ExprId;
1059}
1060
1061impl Expr {
1062 pub fn ty(&self) -> TypeId {
1064 match *self {
1065 Self::Term(t, ..) => t,
1066 Self::Var(t, ..) => t,
1067 Self::ConstBool(t, ..) => t,
1068 Self::ConstInt(t, ..) => t,
1069 Self::ConstPrim(t, ..) => t,
1070 Self::Let { ty: t, .. } => t,
1071 }
1072 }
1073
1074 pub fn visit<V: ExprVisitor>(
1076 &self,
1077 visitor: &mut V,
1078 termenv: &TermEnv,
1079 vars: &HashMap<VarId, V::ExprId>,
1080 ) -> V::ExprId {
1081 log!("Expr::visit: expr {:?}", self);
1082 match *self {
1083 Expr::ConstBool(ty, val) => visitor.add_const_bool(ty, val),
1084 Expr::ConstInt(ty, val) => visitor.add_const_int(ty, val),
1085 Expr::ConstPrim(ty, val) => visitor.add_const_prim(ty, val),
1086 Expr::Let {
1087 ty: _ty,
1088 ref bindings,
1089 ref body,
1090 } => {
1091 let mut vars = vars.clone();
1092 for &(var, _var_ty, ref var_expr) in bindings {
1093 let var_value = var_expr.visit(visitor, termenv, &vars);
1094 vars.insert(var, var_value);
1095 }
1096 body.visit(visitor, termenv, &vars)
1097 }
1098 Expr::Var(_ty, var_id) => *vars.get(&var_id).unwrap(),
1099 Expr::Term(ty, term, ref arg_exprs) => {
1100 let termdata = &termenv.terms[term.index()];
1101 let arg_values_tys = arg_exprs
1102 .iter()
1103 .map(|arg_expr| arg_expr.visit(visitor, termenv, vars))
1104 .zip(termdata.arg_tys.iter().copied())
1105 .collect();
1106 match &termdata.kind {
1107 TermKind::EnumVariant { variant } => {
1108 visitor.add_create_variant(arg_values_tys, ty, *variant)
1109 }
1110 TermKind::Struct => visitor.add_create_struct(arg_values_tys, ty),
1111 TermKind::Decl {
1112 constructor_kind: Some(_),
1113 flags,
1114 ..
1115 } => {
1116 visitor.add_construct(
1117 arg_values_tys,
1118 ty,
1119 term,
1120 flags.pure,
1121 !flags.partial,
1122 flags.multi,
1123 flags.rec,
1124 )
1125 }
1126 TermKind::Decl {
1127 constructor_kind: None,
1128 ..
1129 } => panic!("Should have been caught by typechecking"),
1130 }
1131 }
1132 }
1133 }
1134
1135 fn visit_in_rule<V: RuleVisitor>(
1136 &self,
1137 visitor: &mut V,
1138 termenv: &TermEnv,
1139 vars: &HashMap<VarId, <V::PatternVisitor as PatternVisitor>::PatternId>,
1140 ) -> V::Expr {
1141 let var_exprs = vars
1142 .iter()
1143 .map(|(&var, &val)| (var, visitor.pattern_as_expr(val)))
1144 .collect();
1145 visitor.add_expr(|visitor| VisitedExpr {
1146 ty: self.ty(),
1147 value: self.visit(visitor, termenv, &var_exprs),
1148 })
1149 }
1150}
1151
1152#[derive(Clone, Copy)]
1154pub struct VisitedExpr<V: ExprVisitor> {
1155 pub ty: TypeId,
1157 pub value: V::ExprId,
1159}
1160
1161pub trait RuleVisitor {
1164 type PatternVisitor: PatternVisitor;
1166 type ExprVisitor: ExprVisitor;
1168 type Expr;
1171
1172 fn add_arg(
1174 &mut self,
1175 index: usize,
1176 ty: TypeId,
1177 ) -> <Self::PatternVisitor as PatternVisitor>::PatternId;
1178
1179 fn add_pattern<F>(&mut self, visitor: F)
1183 where
1184 F: FnOnce(&mut Self::PatternVisitor);
1185
1186 fn add_expr<F>(&mut self, visitor: F) -> Self::Expr
1188 where
1189 F: FnOnce(&mut Self::ExprVisitor) -> VisitedExpr<Self::ExprVisitor>;
1190
1191 fn expr_as_pattern(
1194 &mut self,
1195 expr: Self::Expr,
1196 ) -> <Self::PatternVisitor as PatternVisitor>::PatternId;
1197
1198 fn pattern_as_expr(
1201 &mut self,
1202 pattern: <Self::PatternVisitor as PatternVisitor>::PatternId,
1203 ) -> <Self::ExprVisitor as ExprVisitor>::ExprId;
1204}
1205
1206impl Rule {
1207 pub fn visit<V: RuleVisitor>(&self, visitor: &mut V, termenv: &TermEnv) -> V::Expr {
1211 let mut vars = HashMap::new();
1212
1213 let termdata = &termenv.terms[self.root_term.index()];
1215 for (i, (subpat, &arg_ty)) in self.args.iter().zip(termdata.arg_tys.iter()).enumerate() {
1216 let value = visitor.add_arg(i, arg_ty);
1217 visitor.add_pattern(|visitor| subpat.visit(visitor, value, termenv, &mut vars));
1218 }
1219
1220 for iflet in self.iflets.iter() {
1222 let subexpr = iflet.rhs.visit_in_rule(visitor, termenv, &vars);
1223 let value = visitor.expr_as_pattern(subexpr);
1224 visitor.add_pattern(|visitor| iflet.lhs.visit(visitor, value, termenv, &mut vars));
1225 }
1226
1227 self.rhs.visit_in_rule(visitor, termenv, &vars)
1229 }
1230
1231 pub fn identifier(&self, tyenv: &TypeEnv, files: &Files) -> String {
1233 match self.name {
1234 Some(sym) => tyenv.syms[sym.index()].clone(),
1235 None => self.pos.pretty_print_line(files),
1236 }
1237 }
1238}
1239
1240macro_rules! unwrap_or_continue {
1248 ($e:expr) => {
1249 match $e {
1250 Some(x) => x,
1251 None => continue,
1252 }
1253 };
1254}
1255
1256impl Default for TypeEnv {
1257 fn default() -> Self {
1258 Self {
1259 syms: BuiltinType::ALL
1260 .iter()
1261 .map(|bt| String::from(bt.name()))
1262 .collect(),
1263 sym_map: BuiltinType::ALL
1264 .iter()
1265 .enumerate()
1266 .map(|(idx, bt)| (String::from(bt.name()), Sym(idx)))
1267 .collect(),
1268 types: BuiltinType::ALL
1269 .iter()
1270 .map(|bt| Type::Builtin(*bt))
1271 .collect(),
1272 type_map: BuiltinType::ALL
1273 .iter()
1274 .enumerate()
1275 .map(|(idx, _)| (Sym(idx), TypeId(idx)))
1276 .collect(),
1277 const_types: StableMap::new(),
1278 errors: vec![],
1279 }
1280 }
1281}
1282
1283impl TypeEnv {
1284 pub fn from_ast(defs: &[ast::Def]) -> Result<TypeEnv, Vec<Error>> {
1286 let mut tyenv = TypeEnv::default();
1287
1288 for def in defs {
1291 match def {
1292 &ast::Def::Type(ref td) => {
1293 let tid = TypeId(tyenv.type_map.len());
1294 let name = tyenv.intern_mut(&td.name);
1295
1296 if let Some(existing) = tyenv.type_map.get(&name).copied() {
1297 tyenv.report_error(
1298 td.pos,
1299 format!("Type with name '{}' defined more than once", td.name.0),
1300 );
1301 let pos = unwrap_or_continue!(tyenv.types.get(existing.index())).pos();
1302 match pos {
1303 Some(pos) => tyenv.report_error(
1304 pos,
1305 format!("Type with name '{}' already defined here", td.name.0),
1306 ),
1307 None => tyenv.report_error(
1308 td.pos,
1309 format!("Type with name '{}' is a built-in type", td.name.0),
1310 ),
1311 }
1312 continue;
1313 }
1314
1315 tyenv.type_map.insert(name, tid);
1316 }
1317 _ => {}
1318 }
1319 }
1320
1321 for def in defs {
1325 match def {
1326 &ast::Def::Type(ref td) => {
1327 let tid = tyenv.types.len();
1328 if let Some(ty) = tyenv.type_from_ast(TypeId(tid), td) {
1329 tyenv.types.push(ty);
1330 }
1331 }
1332 _ => {}
1333 }
1334 }
1335
1336 for def in defs {
1338 if let &ast::Def::Extern(ast::Extern::Const {
1339 ref name,
1340 ref ty,
1341 pos,
1342 }) = def
1343 {
1344 let ty = match tyenv.get_type_by_name(ty) {
1345 Some(ty) => ty,
1346 None => {
1347 tyenv.report_error(pos, "Unknown type for constant");
1348 continue;
1349 }
1350 };
1351 let name = tyenv.intern_mut(name);
1352 tyenv.const_types.insert(name, ty);
1353 }
1354 }
1355
1356 tyenv.return_errors()?;
1357
1358 Ok(tyenv)
1359 }
1360
1361 fn return_errors(&mut self) -> Result<(), Vec<Error>> {
1362 if self.errors.is_empty() {
1363 Ok(())
1364 } else {
1365 Err(std::mem::take(&mut self.errors))
1366 }
1367 }
1368
1369 fn type_from_ast(&mut self, tid: TypeId, ty: &ast::Type) -> Option<Type> {
1370 let name = self.intern(&ty.name).unwrap();
1371 match &ty.ty {
1372 &ast::TypeValue::Primitive(ref id, ..) => {
1373 if ty.is_nodebug {
1374 self.report_error(ty.pos, "primitive types cannot be marked `nodebug`");
1375 return None;
1376 }
1377 if ty.is_extern {
1378 self.report_error(ty.pos, "primitive types cannot be marked `extern`");
1379 return None;
1380 }
1381 Some(Type::Primitive(tid, self.intern_mut(id), ty.pos))
1382 }
1383 &ast::TypeValue::Enum(ref ty_variants, ..) => {
1384 if ty.is_extern && ty.is_nodebug {
1385 self.report_error(ty.pos, "external types cannot be marked `nodebug`");
1386 return None;
1387 }
1388
1389 let mut variants = vec![];
1390 for variant in ty_variants {
1391 let combined_ident = ast::Variant::full_name(&ty.name, &variant.name);
1392 let fullname = self.intern_mut(&combined_ident);
1393 let name = self.intern_mut(&variant.name);
1394 let id = VariantId(variants.len());
1395 if variants.iter().any(|v: &Variant| v.name == name) {
1396 self.report_error(
1397 variant.pos,
1398 format!("Duplicate variant name in type: '{}'", variant.name.0),
1399 );
1400 return None;
1401 }
1402 let fields = self.fields_from_ast(&variant.fields, Some(&variant.name))?;
1403 variants.push(Variant {
1404 name,
1405 fullname,
1406 id,
1407 fields,
1408 pos: variant.pos,
1409 });
1410 }
1411 Some(Type::Enum {
1412 name,
1413 id: tid,
1414 is_extern: ty.is_extern,
1415 is_nodebug: ty.is_nodebug,
1416 variants,
1417 pos: ty.pos,
1418 })
1419 }
1420 &ast::TypeValue::Struct(ref fields, _) => {
1421 if ty.is_extern && ty.is_nodebug {
1422 self.report_error(ty.pos, "external types cannot be marked `nodebug`");
1423 return None;
1424 }
1425 Some(Type::Struct {
1426 name,
1427 id: tid,
1428 is_extern: ty.is_extern,
1429 is_nodebug: ty.is_nodebug,
1430 fields: self.fields_from_ast(&fields, None)?,
1431 pos: ty.pos,
1432 })
1433 }
1434 }
1435 }
1436
1437 fn fields_from_ast(
1438 &mut self,
1439 fields: &ast::Fields,
1440 variant_name: Option<&ast::Ident>,
1441 ) -> Option<Fields> {
1442 match fields {
1443 ast::Fields::Unit => Some(Fields::Unit),
1444 ast::Fields::Struct(fields) => Some(Fields::Struct(
1445 self.struct_fields_from_ast(fields, variant_name)?,
1446 )),
1447 ast::Fields::Tuple(fields) => Some(Fields::Tuple(
1448 self.tuple_fields_from_ast(fields, variant_name)?,
1449 )),
1450 }
1451 }
1452
1453 fn struct_fields_from_ast(
1454 &mut self,
1455 fields: &ast::StructFields,
1456 variant_name: Option<&ast::Ident>,
1457 ) -> Option<StructFields> {
1458 let mut out = Vec::with_capacity(fields.fields.len());
1459 for field in &fields.fields {
1460 let field_name = self.intern_mut(&field.name);
1461 if out.iter().any(|f: &StructField| f.name == field_name) {
1462 let msg = if let Some(variant_name) = variant_name {
1463 format!(
1464 "Duplicate field name '{}' in variant '{}' of type",
1465 field.name.0, variant_name.0
1466 )
1467 } else {
1468 format!("Duplicate field name '{}'", field.name.0)
1469 };
1470 self.report_error(field.pos, msg);
1471 return None;
1472 }
1473 let field_tid = match self.get_type_by_name(&field.ty) {
1474 Some(tid) => tid,
1475 None => {
1476 let msg = if let Some(variant_name) = variant_name {
1477 format!(
1478 "Unknown type '{}' for field '{}' in variant '{}'",
1479 field.ty.0, field.name.0, variant_name.0
1480 )
1481 } else {
1482 format!("Unknown type '{}' for field '{}'", field.ty.0, field.name.0)
1483 };
1484 self.report_error(field.ty.1, msg);
1485 return None;
1486 }
1487 };
1488 out.push(StructField {
1489 name: field_name,
1490 id: FieldId(out.len()),
1491 ty: field_tid,
1492 });
1493 }
1494 Some(StructFields { fields: out })
1495 }
1496
1497 fn tuple_fields_from_ast(
1498 &mut self,
1499 fields: &ast::TupleFields,
1500 variant_name: Option<&ast::Ident>,
1501 ) -> Option<TupleFields> {
1502 let mut out = Vec::with_capacity(fields.fields.len());
1503 for field in &fields.fields {
1504 let field_tid = match self.get_type_by_name(&field.ty) {
1505 Some(tid) => tid,
1506 None => {
1507 let msg = if let Some(variant_name) = variant_name {
1508 format!(
1509 "Unknown type '{}' for tuple field '{}' in variant '{}'",
1510 field.ty.0, field.index, variant_name.0
1511 )
1512 } else {
1513 format!(
1514 "Unknown type '{}' for tuple field '{}'",
1515 field.ty.0, field.index
1516 )
1517 };
1518 self.report_error(field.ty.1, msg);
1519 return None;
1520 }
1521 };
1522 out.push(TupleField {
1523 id: FieldId(out.len()),
1524 ty: field_tid,
1525 });
1526 }
1527 Some(TupleFields { fields: out })
1528 }
1529
1530 fn error(&self, pos: Pos, msg: impl Into<String>) -> Error {
1531 Error::TypeError {
1532 msg: msg.into(),
1533 span: Span::new_single(pos),
1534 }
1535 }
1536
1537 fn report_error(&mut self, pos: Pos, msg: impl Into<String>) {
1538 let err = self.error(pos, msg);
1539 self.errors.push(err);
1540 }
1541
1542 fn intern_mut(&mut self, ident: &ast::Ident) -> Sym {
1543 if let Some(s) = self.sym_map.get(&ident.0).copied() {
1544 s
1545 } else {
1546 let s = Sym(self.syms.len());
1547 self.syms.push(ident.0.clone());
1548 self.sym_map.insert(ident.0.clone(), s);
1549 s
1550 }
1551 }
1552
1553 pub fn intern(&self, ident: &ast::Ident) -> Option<Sym> {
1555 self.sym_map.get(&ident.0).copied()
1556 }
1557
1558 pub fn get_type_by_name(&self, sym: &ast::Ident) -> Option<TypeId> {
1560 self.intern(sym)
1561 .and_then(|sym| self.type_map.get(&sym))
1562 .copied()
1563 }
1564
1565 pub fn get_variant(&self, ty: TypeId, variant: VariantId) -> &Variant {
1567 let ty = &self.types[ty.index()];
1568 let Type::Enum { variants, .. } = ty else {
1569 unreachable!("provided type must be an enum")
1570 };
1571 &variants[variant.index()]
1572 }
1573}
1574
1575#[derive(Clone, Debug, Default)]
1576struct Bindings {
1577 seen: Vec<BoundVar>,
1580 next_scope: usize,
1582 in_scope: Vec<usize>,
1584}
1585
1586impl Bindings {
1587 fn enter_scope(&mut self) {
1588 self.in_scope.push(self.next_scope);
1589 self.next_scope += 1;
1590 }
1591
1592 fn exit_scope(&mut self) {
1593 self.in_scope.pop();
1594 }
1595
1596 fn add_var(&mut self, name: Sym, ty: TypeId) -> VarId {
1597 let id = VarId(self.seen.len());
1598 let var = BoundVar {
1599 id,
1600 name,
1601 ty,
1602 scope: *self
1603 .in_scope
1604 .last()
1605 .expect("enter_scope should be called before add_var"),
1606 };
1607 log!("binding var {:?}", var);
1608 self.seen.push(var);
1609 id
1610 }
1611
1612 fn lookup(&self, name: Sym) -> Option<&BoundVar> {
1613 self.seen
1614 .iter()
1615 .rev()
1616 .find(|binding| binding.name == name && self.in_scope.contains(&binding.scope))
1617 }
1618}
1619
1620impl TermEnv {
1621 pub fn from_ast(
1623 tyenv: &mut TypeEnv,
1624 defs: &[ast::Def],
1625 expand_internal_extractors: bool,
1626 ) -> Result<TermEnv, Vec<Error>> {
1627 let mut env = TermEnv {
1628 terms: vec![],
1629 term_map: StableMap::new(),
1630 rules: vec![],
1631 rule_map: StableMap::new(),
1632 converters: StableMap::new(),
1633 expand_internal_extractors,
1634 };
1635
1636 env.collect_pragmas(defs);
1637 env.collect_term_sigs(tyenv, defs);
1638 env.collect_enum_variant_terms(tyenv);
1639 tyenv.return_errors()?;
1640 env.collect_constructors(tyenv, defs);
1641 env.collect_extractor_templates(tyenv, defs);
1642 tyenv.return_errors()?;
1643 env.collect_converters(tyenv, defs);
1644 tyenv.return_errors()?;
1645 env.collect_externs(tyenv, defs);
1646 tyenv.return_errors()?;
1647 env.collect_rules(tyenv, defs);
1648 env.check_for_undefined_decls(tyenv, defs);
1649 env.check_for_expr_terms_without_constructors(tyenv, defs);
1650 tyenv.return_errors()?;
1651
1652 Ok(env)
1653 }
1654
1655 fn collect_pragmas(&mut self, _: &[ast::Def]) {
1656 return;
1658 }
1659
1660 fn collect_term_sigs(&mut self, tyenv: &mut TypeEnv, defs: &[ast::Def]) {
1661 for def in defs {
1662 match def {
1663 &ast::Def::Decl(ref decl) => {
1664 let name = tyenv.intern_mut(&decl.term);
1665 if let Some(tid) = self.term_map.get(&name) {
1666 tyenv.report_error(
1667 decl.pos,
1668 format!("Duplicate decl for '{}'", decl.term.0),
1669 );
1670 tyenv.report_error(
1671 self.terms[tid.index()].decl_pos,
1672 format!("Duplicate decl for '{}'", decl.term.0),
1673 );
1674 }
1675
1676 if decl.multi && decl.partial {
1677 tyenv.report_error(
1678 decl.pos,
1679 format!("Term '{}' can't be both multi and partial", decl.term.0),
1680 );
1681 }
1682
1683 let arg_tys = decl
1684 .arg_tys
1685 .iter()
1686 .map(|id| {
1687 tyenv.get_type_by_name(id).ok_or_else(|| {
1688 tyenv.report_error(id.1, format!("Unknown arg type: '{}'", id.0));
1689 })
1690 })
1691 .collect::<Result<Vec<_>, _>>();
1692 let arg_tys = match arg_tys {
1693 Ok(a) => a,
1694 Err(_) => {
1695 continue;
1696 }
1697 };
1698 let ret_ty = match tyenv.get_type_by_name(&decl.ret_ty) {
1699 Some(t) => t,
1700 None => {
1701 tyenv.report_error(
1702 decl.ret_ty.1,
1703 format!("Unknown return type: '{}'", decl.ret_ty.0),
1704 );
1705 continue;
1706 }
1707 };
1708
1709 let tid = TermId(self.terms.len());
1710 self.term_map.insert(name, tid);
1711 let flags = TermFlags {
1712 pure: decl.pure,
1713 multi: decl.multi,
1714 partial: decl.partial,
1715 rec: decl.rec,
1716 };
1717 self.terms.push(Term {
1718 id: tid,
1719 decl_pos: decl.pos,
1720 name,
1721 arg_tys,
1722 ret_ty,
1723 kind: TermKind::Decl {
1724 flags,
1725 constructor_kind: None,
1726 extractor_kind: None,
1727 },
1728 });
1729 }
1730 _ => {}
1731 }
1732 }
1733 }
1734
1735 fn collect_enum_variant_terms(&mut self, tyenv: &mut TypeEnv) {
1736 'types: for i in 0..tyenv.types.len() {
1737 let ty = &tyenv.types[i];
1738 match ty {
1739 &Type::Enum {
1740 pos,
1741 id,
1742 ref variants,
1743 ..
1744 } => {
1745 for variant in variants {
1746 if self.term_map.contains_key(&variant.fullname) {
1747 let variant_name = tyenv.syms[variant.fullname.index()].clone();
1748 tyenv.report_error(
1749 pos,
1750 format!("Duplicate enum variant constructor: '{variant_name}'",),
1751 );
1752 continue 'types;
1753 }
1754 let tid = TermId(self.terms.len());
1755 let arg_tys = variant.fields.types();
1756 let ret_ty = id;
1757 self.terms.push(Term {
1758 id: tid,
1759 decl_pos: variant.pos,
1760 name: variant.fullname,
1761 arg_tys,
1762 ret_ty,
1763 kind: TermKind::EnumVariant {
1764 variant: variant.id,
1765 },
1766 });
1767 self.term_map.insert(variant.fullname, tid);
1768 }
1769 }
1770 &Type::Struct {
1771 pos,
1772 id,
1773 name,
1774 ref fields,
1775 ..
1776 } => {
1777 if self.term_map.contains_key(&name) {
1778 let name = tyenv.syms[name.index()].clone();
1779 tyenv.report_error(pos, format!("Duplicate struct constructor: '{name}'",));
1780 continue 'types;
1781 }
1782 let tid = TermId(self.terms.len());
1783 let arg_tys = fields.types();
1784 let ret_ty = id;
1785 self.terms.push(Term {
1786 id: tid,
1787 decl_pos: pos,
1788 name,
1789 arg_tys,
1790 ret_ty,
1791 kind: TermKind::Struct,
1792 });
1793 self.term_map.insert(name, tid);
1794 }
1795 _ => {}
1796 }
1797 }
1798 }
1799
1800 fn collect_constructors(&mut self, tyenv: &mut TypeEnv, defs: &[ast::Def]) {
1801 for def in defs {
1802 log!("collect_constructors from def: {:?}", def);
1803 match def {
1804 &ast::Def::Rule(ref rule) => {
1805 let pos = rule.pos;
1806 let term = match rule.pattern.root_term() {
1807 Some(t) => t,
1808 None => {
1809 tyenv.report_error(
1810 pos,
1811 "Rule does not have a term at the LHS root".to_string(),
1812 );
1813 continue;
1814 }
1815 };
1816 let term = match self.get_term_by_name(tyenv, &term) {
1817 Some(tid) => tid,
1818 None => {
1819 tyenv
1820 .report_error(pos, "Rule LHS root term is not defined".to_string());
1821 continue;
1822 }
1823 };
1824 let termdata = &mut self.terms[term.index()];
1825 match &mut termdata.kind {
1826 TermKind::Decl {
1827 constructor_kind, ..
1828 } => {
1829 match constructor_kind {
1830 None => {
1831 *constructor_kind = Some(ConstructorKind::InternalConstructor);
1832 }
1833 Some(ConstructorKind::InternalConstructor) => {
1834 }
1837 Some(ConstructorKind::ExternalConstructor { .. }) => {
1838 tyenv.report_error(
1839 pos,
1840 "Rule LHS root term is incorrect kind; cannot \
1841 be external constructor"
1842 .to_string(),
1843 );
1844 continue;
1845 }
1846 }
1847 }
1848 TermKind::EnumVariant { .. } => {
1849 tyenv.report_error(
1850 pos,
1851 "Rule LHS root term is incorrect kind; cannot be enum variant"
1852 .to_string(),
1853 );
1854 continue;
1855 }
1856 TermKind::Struct => {
1857 tyenv.report_error(
1858 pos,
1859 "Rule LHS root term is incorrect kind; cannot be struct"
1860 .to_string(),
1861 );
1862 continue;
1863 }
1864 }
1865 }
1866 _ => {}
1867 }
1868 }
1869 }
1870
1871 fn collect_extractor_templates(&mut self, tyenv: &mut TypeEnv, defs: &[ast::Def]) {
1872 let mut extractor_call_graph = BTreeMap::new();
1873
1874 for def in defs {
1875 if let &ast::Def::Extractor(ref ext) = def {
1876 let term = match self.get_term_by_name(tyenv, &ext.term) {
1877 Some(x) => x,
1878 None => {
1879 tyenv.report_error(
1880 ext.pos,
1881 "Extractor macro body definition on a non-existent term".to_string(),
1882 );
1883 return;
1884 }
1885 };
1886
1887 let template = ext.template.make_macro_template(&ext.args[..]);
1888 log!("extractor def: {:?} becomes template {:?}", def, template);
1889
1890 let mut callees = BTreeSet::new();
1891 template.terms(&mut |pos, t| {
1892 if let Some(term) = self.get_term_by_name(tyenv, t) {
1893 callees.insert(term);
1894 } else {
1895 tyenv.report_error(
1896 pos,
1897 format!(
1898 "`{}` extractor definition references unknown term `{}`",
1899 ext.term.0, t.0
1900 ),
1901 );
1902 }
1903 });
1904 extractor_call_graph.insert(term, callees);
1905
1906 let termdata = &mut self.terms[term.index()];
1907 match &mut termdata.kind {
1908 TermKind::EnumVariant { .. } => {
1909 tyenv.report_error(
1910 ext.pos,
1911 "Extractor macro body defined on term of incorrect kind; cannot be an \
1912 enum variant",
1913 );
1914 continue;
1915 }
1916 TermKind::Struct { .. } => {
1917 tyenv.report_error(
1918 ext.pos,
1919 "Extractor macro body defined on term of incorrect kind; cannot be a \
1920 struct",
1921 );
1922 continue;
1923 }
1924 TermKind::Decl {
1925 flags,
1926 extractor_kind,
1927 ..
1928 } => match extractor_kind {
1929 None => {
1930 if flags.multi {
1931 tyenv.report_error(
1932 ext.pos,
1933 "A term declared with `multi` cannot have an internal extractor.".to_string());
1934 continue;
1935 }
1936 *extractor_kind = Some(ExtractorKind::InternalExtractor { template });
1937 }
1938 Some(ext_kind) => {
1939 tyenv.report_error(
1940 ext.pos,
1941 "Duplicate extractor definition".to_string(),
1942 );
1943 let pos = match ext_kind {
1944 ExtractorKind::InternalExtractor { template } => template.pos(),
1945 ExtractorKind::ExternalExtractor { pos, .. } => *pos,
1946 };
1947 tyenv.report_error(
1948 pos,
1949 "Extractor was already defined here".to_string(),
1950 );
1951 continue;
1952 }
1953 },
1954 }
1955 }
1956 }
1957
1958 let mut stack = vec![];
1960 'outer: for root in extractor_call_graph.keys().copied() {
1961 stack.clear();
1962 stack.push((root, vec![root], StableSet::new()));
1963
1964 while let Some((caller, path, mut seen)) = stack.pop() {
1965 let is_new = seen.insert(caller);
1966 if is_new {
1967 if let Some(callees) = extractor_call_graph.get(&caller) {
1968 stack.extend(callees.iter().map(|callee| {
1969 let mut path = path.clone();
1970 path.push(*callee);
1971 (*callee, path, seen.clone())
1972 }));
1973 }
1974 } else {
1975 let pos = match &self.terms[caller.index()].kind {
1976 TermKind::Decl {
1977 extractor_kind: Some(ExtractorKind::InternalExtractor { template }),
1978 ..
1979 } => template.pos(),
1980 _ => {
1981 assert!(!tyenv.errors.is_empty());
1983 continue 'outer;
1984 }
1985 };
1986
1987 let path: Vec<_> = path
1988 .iter()
1989 .map(|sym| tyenv.syms[sym.index()].as_str())
1990 .collect();
1991 let msg = format!(
1992 "`{}` extractor definition is recursive: {}",
1993 tyenv.syms[root.index()],
1994 path.join(" -> ")
1995 );
1996 tyenv.report_error(pos, msg);
1997 continue 'outer;
1998 }
1999 }
2000 }
2001 }
2002
2003 fn collect_converters(&mut self, tyenv: &mut TypeEnv, defs: &[ast::Def]) {
2004 for def in defs {
2005 match def {
2006 &ast::Def::Converter(ast::Converter {
2007 ref term,
2008 ref inner_ty,
2009 ref outer_ty,
2010 pos,
2011 }) => {
2012 let inner_ty_id = match tyenv.get_type_by_name(inner_ty) {
2013 Some(ty) => ty,
2014 None => {
2015 tyenv.report_error(
2016 inner_ty.1,
2017 format!("Unknown inner type for converter: '{}'", inner_ty.0),
2018 );
2019 continue;
2020 }
2021 };
2022
2023 let outer_ty_id = match tyenv.get_type_by_name(outer_ty) {
2024 Some(ty) => ty,
2025 None => {
2026 tyenv.report_error(
2027 outer_ty.1,
2028 format!("Unknown outer type for converter: '{}'", outer_ty.0),
2029 );
2030 continue;
2031 }
2032 };
2033
2034 let term_id = match self.get_term_by_name(tyenv, term) {
2035 Some(term_id) => term_id,
2036 None => {
2037 tyenv.report_error(
2038 term.1,
2039 format!("Unknown term for converter: '{}'", term.0),
2040 );
2041 continue;
2042 }
2043 };
2044
2045 match self.converters.entry((inner_ty_id, outer_ty_id)) {
2046 Entry::Vacant(v) => {
2047 v.insert(term_id);
2048 }
2049 Entry::Occupied(_) => {
2050 tyenv.report_error(
2051 pos,
2052 format!(
2053 "Converter already exists for this type pair: '{}', '{}'",
2054 inner_ty.0, outer_ty.0
2055 ),
2056 );
2057 continue;
2058 }
2059 }
2060 }
2061 _ => {}
2062 }
2063 }
2064 }
2065
2066 fn collect_externs(&mut self, tyenv: &mut TypeEnv, defs: &[ast::Def]) {
2067 for def in defs {
2068 match def {
2069 &ast::Def::Extern(ast::Extern::Constructor {
2070 ref term,
2071 ref func,
2072 pos,
2073 }) => {
2074 let func_sym = tyenv.intern_mut(func);
2075 let term_id = match self.get_term_by_name(tyenv, term) {
2076 Some(term) => term,
2077 None => {
2078 tyenv.report_error(
2079 pos,
2080 format!("Constructor declared on undefined term '{}'", term.0),
2081 );
2082 continue;
2083 }
2084 };
2085 let termdata = &mut self.terms[term_id.index()];
2086 match &mut termdata.kind {
2087 TermKind::Decl {
2088 constructor_kind, ..
2089 } => match constructor_kind {
2090 None => {
2091 *constructor_kind =
2092 Some(ConstructorKind::ExternalConstructor { name: func_sym });
2093 }
2094 Some(ConstructorKind::InternalConstructor) => {
2095 tyenv.report_error(
2096 pos,
2097 format!(
2098 "External constructor declared on term that already has rules: {}",
2099 term.0,
2100 ),
2101 );
2102 }
2103 Some(ConstructorKind::ExternalConstructor { .. }) => {
2104 tyenv.report_error(
2105 pos,
2106 "Duplicate external constructor definition".to_string(),
2107 );
2108 }
2109 },
2110 TermKind::EnumVariant { .. } => {
2111 tyenv.report_error(
2112 pos,
2113 format!(
2114 "External constructor cannot be defined on enum variant: {}",
2115 term.0,
2116 ),
2117 );
2118 }
2119 TermKind::Struct { .. } => {
2120 tyenv.report_error(
2121 pos,
2122 format!(
2123 "External constructor cannot be defined on a struct: {}",
2124 term.0,
2125 ),
2126 );
2127 }
2128 }
2129 }
2130 &ast::Def::Extern(ast::Extern::Extractor {
2131 ref term,
2132 ref func,
2133 pos,
2134 infallible,
2135 }) => {
2136 let func_sym = tyenv.intern_mut(func);
2137 let term_id = match self.get_term_by_name(tyenv, term) {
2138 Some(term) => term,
2139 None => {
2140 tyenv.report_error(
2141 pos,
2142 format!("Extractor declared on undefined term '{}'", term.0),
2143 );
2144 continue;
2145 }
2146 };
2147
2148 let termdata = &mut self.terms[term_id.index()];
2149
2150 match &mut termdata.kind {
2151 TermKind::Decl { extractor_kind, .. } => match extractor_kind {
2152 None => {
2153 *extractor_kind = Some(ExtractorKind::ExternalExtractor {
2154 name: func_sym,
2155 infallible,
2156 pos,
2157 });
2158 }
2159 Some(ExtractorKind::ExternalExtractor { pos: pos2, .. }) => {
2160 tyenv.report_error(
2161 pos,
2162 "Duplicate external extractor definition".to_string(),
2163 );
2164 tyenv.report_error(
2165 *pos2,
2166 "External extractor already defined".to_string(),
2167 );
2168 continue;
2169 }
2170 Some(ExtractorKind::InternalExtractor { template }) => {
2171 tyenv.report_error(
2172 pos,
2173 "Cannot define external extractor for term that already has an \
2174 internal extractor macro body defined"
2175 .to_string(),
2176 );
2177 tyenv.report_error(
2178 template.pos(),
2179 "Internal extractor macro body already defined".to_string(),
2180 );
2181 continue;
2182 }
2183 },
2184 TermKind::EnumVariant { .. } => {
2185 tyenv.report_error(
2186 pos,
2187 format!("Cannot define extractor for enum variant '{}'", term.0),
2188 );
2189 continue;
2190 }
2191 TermKind::Struct { .. } => {
2192 tyenv.report_error(
2193 pos,
2194 format!("Cannot define extractor for struct '{}'", term.0),
2195 );
2196 continue;
2197 }
2198 }
2199 }
2200 _ => {}
2201 }
2202 }
2203 }
2204
2205 fn collect_rules(&mut self, tyenv: &mut TypeEnv, defs: &[ast::Def]) {
2206 for def in defs {
2207 match def {
2208 &ast::Def::Rule(ref rule) => {
2209 let pos = rule.pos;
2210 let mut bindings = Bindings::default();
2211 bindings.enter_scope();
2212
2213 let (sym, args) = if let ast::Pattern::Term { sym, args, .. } = &rule.pattern {
2214 (sym, args)
2215 } else {
2216 tyenv.report_error(
2217 pos,
2218 "Rule does not have a term at the root of its left-hand side"
2219 .to_string(),
2220 );
2221 continue;
2222 };
2223
2224 let root_term = if let Some(term) = self.get_term_by_name(tyenv, sym) {
2225 term
2226 } else {
2227 tyenv.report_error(
2228 pos,
2229 "Cannot define a rule for an unknown term".to_string(),
2230 );
2231 continue;
2232 };
2233
2234 let termdata = &self.terms[root_term.index()];
2235
2236 let flags = match &termdata.kind {
2237 TermKind::Decl { flags, .. } => *flags,
2238 _ => {
2239 tyenv.report_error(
2240 pos,
2241 "Cannot define a rule on a left-hand-side that is an enum variant"
2242 .to_string(),
2243 );
2244 continue;
2245 }
2246 };
2247
2248 termdata.check_args_count(args, tyenv, pos, sym);
2249 let args = self.translate_args(args, termdata, tyenv, &mut bindings);
2250
2251 let iflets = rule
2252 .iflets
2253 .iter()
2254 .filter_map(|iflet| {
2255 self.translate_iflet(tyenv, iflet, &mut bindings, flags)
2256 })
2257 .collect();
2258 let rhs = unwrap_or_continue!(self.translate_expr(
2259 tyenv,
2260 &rule.expr,
2261 Some(termdata.ret_ty),
2262 &mut bindings,
2263 flags,
2264 ));
2265
2266 bindings.exit_scope();
2267
2268 let prio = if let Some(prio) = rule.prio {
2269 if flags.multi {
2270 tyenv.report_error(
2271 pos,
2272 "Cannot set rule priorities in multi-terms".to_string(),
2273 );
2274 }
2275 prio
2276 } else {
2277 0
2278 };
2279
2280 let rid = RuleId(self.rules.len());
2281 self.rules.push(Rule {
2282 id: rid,
2283 root_term,
2284 args,
2285 iflets,
2286 rhs,
2287 vars: bindings.seen,
2288 prio,
2289 name: rule.name.as_ref().map(|i| tyenv.intern_mut(i)),
2290 pos,
2291 });
2292 }
2293 _ => {}
2294 }
2295 }
2296
2297 let mut term_rule_count: HashMap<TermId, usize> = HashMap::new();
2302 for rule in &self.rules {
2303 *term_rule_count.entry(rule.root_term).or_default() += 1;
2304 }
2305
2306 for rule in &mut self.rules {
2307 if rule.name.is_none()
2308 && term_rule_count
2309 .get(&rule.root_term)
2310 .copied()
2311 .unwrap_or_default()
2312 == 1
2313 {
2314 let term = &self.terms[rule.root_term.index()];
2315 rule.name = Some(term.name);
2316 }
2317 }
2318
2319 for rule in &self.rules {
2321 let Some(name) = rule.name else { continue };
2322 match self.rule_map.entry(name) {
2323 Entry::Vacant(e) => {
2324 e.insert(rule.id);
2325 }
2326 Entry::Occupied(_) => {
2327 tyenv.report_error(
2328 rule.pos,
2329 format!("Duplicate rule name: '{}'", tyenv.syms[name.index()]),
2330 );
2331 }
2332 }
2333 }
2334 }
2335
2336 fn check_for_undefined_decls(&self, tyenv: &mut TypeEnv, defs: &[ast::Def]) {
2337 for def in defs {
2338 if let ast::Def::Decl(decl) = def {
2339 let term = self.get_term_by_name(tyenv, &decl.term).unwrap();
2340 let term = &self.terms[term.index()];
2341 if !term.has_constructor() && !term.has_extractor() {
2342 tyenv.report_error(
2343 decl.pos,
2344 format!(
2345 "no rules, extractor, or external definition for declaration '{}'",
2346 decl.term.0
2347 ),
2348 );
2349 }
2350 }
2351 }
2352 }
2353
2354 fn check_for_expr_terms_without_constructors(&self, tyenv: &mut TypeEnv, defs: &[ast::Def]) {
2355 for def in defs {
2356 if let ast::Def::Rule(rule) = def {
2357 rule.expr.terms(&mut |pos, ident| {
2358 let term = match self.get_term_by_name(tyenv, ident) {
2359 None => {
2360 debug_assert!(!tyenv.errors.is_empty());
2361 return;
2362 }
2363 Some(t) => t,
2364 };
2365 let term = &self.terms[term.index()];
2366 if !term.has_constructor() {
2367 tyenv.report_error(
2368 pos,
2369 format!(
2370 "term `{}` cannot be used in an expression because \
2371 it does not have a constructor",
2372 ident.0
2373 ),
2374 )
2375 }
2376 });
2377 }
2378 }
2379 }
2380
2381 fn maybe_implicit_convert_pattern(
2382 &self,
2383 tyenv: &mut TypeEnv,
2384 pattern: &ast::Pattern,
2385 inner_ty: TypeId,
2386 outer_ty: TypeId,
2387 ) -> Option<ast::Pattern> {
2388 if let Some(converter_term) = self.converters.get(&(inner_ty, outer_ty)) {
2389 if self.terms[converter_term.index()].has_extractor() {
2390 let converter_term_ident = ast::Ident(
2396 tyenv.syms[self.terms[converter_term.index()].name.index()].clone(),
2397 pattern.pos(),
2398 );
2399 let expanded_pattern = ast::Pattern::Term {
2400 sym: converter_term_ident,
2401 pos: pattern.pos(),
2402 args: vec![pattern.clone()],
2403 };
2404
2405 return Some(expanded_pattern);
2406 }
2407 }
2408 None
2409 }
2410
2411 fn translate_pattern(
2412 &self,
2413 tyenv: &mut TypeEnv,
2414 pat: &ast::Pattern,
2415 expected_ty: TypeId,
2416 bindings: &mut Bindings,
2417 ) -> Option<Pattern> {
2418 log!("translate_pattern: {:?}", pat);
2419 log!("translate_pattern: bindings = {:?}", bindings);
2420 match pat {
2421 &ast::Pattern::ConstInt { val, pos } => {
2423 let ty = &tyenv.types[expected_ty.index()];
2424 if !ty.is_int() && !ty.is_prim() {
2425 tyenv.report_error(
2426 pos,
2427 format!(
2428 "expected non-integer type {}, but found integer literal '{}'",
2429 ty.name(tyenv),
2430 val,
2431 ),
2432 );
2433 }
2434 Some(Pattern::ConstInt(expected_ty, val))
2435 }
2436 &ast::Pattern::ConstBool { val, pos } => {
2437 if expected_ty != TypeId::BOOL {
2438 tyenv.report_error(
2439 pos,
2440 format!(
2441 "Boolean literal '{val}' has type {} but we need {} in context",
2442 BuiltinType::Bool.name(),
2443 tyenv.types[expected_ty.index()].name(tyenv)
2444 ),
2445 )
2446 }
2447 Some(Pattern::ConstBool(TypeId::BOOL, val))
2448 }
2449 &ast::Pattern::ConstPrim { ref val, pos } => {
2450 let val = tyenv.intern_mut(val);
2451 let const_ty = match tyenv.const_types.get(&val) {
2452 Some(ty) => *ty,
2453 None => {
2454 tyenv.report_error(pos, "Unknown constant");
2455 return None;
2456 }
2457 };
2458 if expected_ty != const_ty {
2459 tyenv.report_error(pos, "Type mismatch for constant");
2460 }
2461 Some(Pattern::ConstPrim(const_ty, val))
2462 }
2463 &ast::Pattern::Wildcard { .. } => Some(Pattern::Wildcard(expected_ty)),
2464 &ast::Pattern::And { ref subpats, .. } => {
2465 let children = subpats
2469 .iter()
2470 .filter_map(|subpat| {
2471 self.translate_pattern(tyenv, subpat, expected_ty, bindings)
2472 })
2473 .collect();
2474 Some(Pattern::And(expected_ty, children))
2475 }
2476 &ast::Pattern::BindPattern {
2477 ref var,
2478 ref subpat,
2479 pos,
2480 } => {
2481 let subpat = self.translate_pattern(tyenv, subpat, expected_ty, bindings)?;
2482
2483 let ty = subpat.ty();
2488
2489 let name = tyenv.intern_mut(var);
2490 if bindings.lookup(name).is_some() {
2491 tyenv.report_error(
2492 pos,
2493 format!("Re-bound variable name in LHS pattern: '{}'", var.0),
2494 );
2495 }
2497 let id = bindings.add_var(name, ty);
2498 Some(Pattern::BindPattern(ty, id, Box::new(subpat)))
2499 }
2500 &ast::Pattern::Var { ref var, pos } => {
2501 let name = tyenv.intern_mut(var);
2507 match bindings.lookup(name) {
2508 None => {
2509 let id = bindings.add_var(name, expected_ty);
2510 Some(Pattern::BindPattern(
2511 expected_ty,
2512 id,
2513 Box::new(Pattern::Wildcard(expected_ty)),
2514 ))
2515 }
2516 Some(bv) => {
2517 if expected_ty != bv.ty {
2518 tyenv.report_error(
2519 pos,
2520 format!(
2521 "Mismatched types: pattern expects type '{}' but already-bound var '{}' has type '{}'",
2522 tyenv.types[expected_ty.index()].name(tyenv),
2523 var.0,
2524 tyenv.types[bv.ty.index()].name(tyenv),
2525 ),
2526 );
2527 }
2529 Some(Pattern::Var(bv.ty, bv.id))
2530 }
2531 }
2532 }
2533 &ast::Pattern::Term {
2534 ref sym,
2535 ref args,
2536 pos,
2537 } => {
2538 let tid = match self.get_term_by_name(tyenv, sym) {
2540 Some(t) => t,
2541 None => {
2542 tyenv.report_error(pos, format!("Unknown term in pattern: '{}'", sym.0));
2543 return None;
2544 }
2545 };
2546
2547 let termdata = &self.terms[tid.index()];
2548
2549 let ret_ty = termdata.ret_ty;
2554 if expected_ty != ret_ty {
2555 if let Some(expanded_pattern) =
2561 self.maybe_implicit_convert_pattern(tyenv, pat, ret_ty, expected_ty)
2562 {
2563 return self.translate_pattern(
2564 tyenv,
2565 &expanded_pattern,
2566 expected_ty,
2567 bindings,
2568 );
2569 }
2570
2571 tyenv.report_error(
2572 pos,
2573 format!(
2574 "Mismatched types: pattern expects type '{}' but term has return type '{}'",
2575 tyenv.types[expected_ty.index()].name(tyenv),
2576 tyenv.types[ret_ty.index()].name(tyenv),
2577 ),
2578 );
2579 }
2581
2582 termdata.check_args_count(args, tyenv, pos, sym);
2583
2584 match &termdata.kind {
2587 TermKind::EnumVariant { .. } | TermKind::Struct => {}
2588 TermKind::Decl {
2589 extractor_kind: Some(ExtractorKind::ExternalExtractor { .. }),
2590 ..
2591 } => {}
2592 TermKind::Decl {
2593 extractor_kind: Some(ExtractorKind::InternalExtractor { template }),
2594 ..
2595 } => {
2596 if self.expand_internal_extractors {
2597 log!("internal extractor macro args = {:?}", args);
2602 let pat = template.subst_macro_args(&args)?;
2603 return self.translate_pattern(tyenv, &pat, expected_ty, bindings);
2604 }
2605 }
2606 TermKind::Decl {
2607 extractor_kind: None,
2608 ..
2609 } => {
2610 tyenv.report_error(
2611 pos,
2612 format!(
2613 "Cannot use term '{}' that does not have a defined extractor in a \
2614 left-hand side pattern",
2615 sym.0
2616 ),
2617 );
2618 }
2619 }
2620
2621 let subpats = self.translate_args(args, termdata, tyenv, bindings);
2622 Some(Pattern::Term(ret_ty, tid, subpats))
2623 }
2624 &ast::Pattern::MacroArg { .. } => unreachable!(),
2625 }
2626 }
2627
2628 fn translate_args(
2629 &self,
2630 args: &Vec<ast::Pattern>,
2631 termdata: &Term,
2632 tyenv: &mut TypeEnv,
2633 bindings: &mut Bindings,
2634 ) -> Vec<Pattern> {
2635 args.iter()
2636 .zip(termdata.arg_tys.iter())
2637 .filter_map(|(arg, &arg_ty)| self.translate_pattern(tyenv, arg, arg_ty, bindings))
2638 .collect()
2639 }
2640
2641 fn maybe_implicit_convert_expr(
2642 &self,
2643 tyenv: &mut TypeEnv,
2644 expr: &ast::Expr,
2645 inner_ty: TypeId,
2646 outer_ty: TypeId,
2647 ) -> Option<ast::Expr> {
2648 if let Some(converter_term) = self.converters.get(&(inner_ty, outer_ty)) {
2650 if self.terms[converter_term.index()].has_constructor() {
2651 let converter_ident = ast::Ident(
2652 tyenv.syms[self.terms[converter_term.index()].name.index()].clone(),
2653 expr.pos(),
2654 );
2655 return Some(ast::Expr::Term {
2656 sym: converter_ident,
2657 pos: expr.pos(),
2658 args: vec![expr.clone()],
2659 });
2660 }
2661 }
2662 None
2663 }
2664
2665 fn translate_expr(
2666 &self,
2667 tyenv: &mut TypeEnv,
2668 expr: &ast::Expr,
2669 ty: Option<TypeId>,
2670 bindings: &mut Bindings,
2671 root_flags: TermFlags,
2672 ) -> Option<Expr> {
2673 log!("translate_expr: {:?}", expr);
2674 match expr {
2675 &ast::Expr::Term {
2676 ref sym,
2677 ref args,
2678 pos,
2679 } => {
2680 let name = tyenv.intern_mut(&sym);
2682 let tid = match self.term_map.get(&name) {
2683 Some(&t) => t,
2684 None => {
2685 if bindings.lookup(name).is_some() {
2688 tyenv.report_error(
2689 pos,
2690 format!(
2691 "Unknown term in expression: '{}'. Variable binding under this name exists; try removing the parens?", sym.0));
2692 } else {
2693 tyenv.report_error(
2694 pos,
2695 format!("Unknown term in expression: '{}'", sym.0),
2696 );
2697 }
2698 return None;
2699 }
2700 };
2701 let termdata = &self.terms[tid.index()];
2702
2703 let ret_ty = termdata.ret_ty;
2709 let ty = if ty.is_some() && ret_ty != ty.unwrap() {
2710 if let Some(expanded_expr) =
2712 self.maybe_implicit_convert_expr(tyenv, expr, ret_ty, ty.unwrap())
2713 {
2714 return self.translate_expr(
2715 tyenv,
2716 &expanded_expr,
2717 ty,
2718 bindings,
2719 root_flags,
2720 );
2721 }
2722
2723 tyenv.report_error(
2724 pos,
2725 format!("Mismatched types: expression expects type '{}' but term has return type '{}'",
2726 tyenv.types[ty.unwrap().index()].name(tyenv),
2727 tyenv.types[ret_ty.index()].name(tyenv)));
2728
2729 ret_ty
2731 } else {
2732 ret_ty
2733 };
2734
2735 if let TermKind::Decl { flags, .. } = &termdata.kind {
2736 let pure_required = root_flags.pure;
2739 if pure_required && !flags.pure {
2740 tyenv.report_error(
2741 pos,
2742 format!(
2743 "Used non-pure constructor '{}' in pure expression context",
2744 sym.0
2745 ),
2746 );
2747 }
2748
2749 if !root_flags.multi && flags.multi {
2751 tyenv.report_error(
2752 pos,
2753 format!(
2754 "Used multi-constructor '{}' but this rule is not in a multi-term",
2755 sym.0
2756 ),
2757 );
2758 }
2759
2760 let partial_allowed = root_flags.partial;
2763 if !partial_allowed && flags.partial {
2764 tyenv.report_error(
2765 pos,
2766 format!(
2767 "Rule can't use partial constructor '{}' on RHS; \
2768 try moving it to if-let{}",
2769 sym.0,
2770 if root_flags.multi {
2771 ""
2772 } else {
2773 " or make this rule's term partial too"
2774 }
2775 ),
2776 );
2777 }
2778 }
2779
2780 termdata.check_args_count(args, tyenv, pos, sym);
2781
2782 let subexprs = args
2784 .iter()
2785 .zip(termdata.arg_tys.iter())
2786 .filter_map(|(arg, &arg_ty)| {
2787 self.translate_expr(tyenv, arg, Some(arg_ty), bindings, root_flags)
2788 })
2789 .collect();
2790
2791 Some(Expr::Term(ty, tid, subexprs))
2792 }
2793 &ast::Expr::Var { ref name, pos } => {
2794 let sym = tyenv.intern_mut(name);
2795 let bv = match bindings.lookup(sym) {
2797 None => {
2798 tyenv.report_error(pos, format!("Unknown variable '{}'", name.0));
2799 return None;
2800 }
2801 Some(bv) => bv,
2802 };
2803
2804 if ty.is_some() && bv.ty != ty.unwrap() {
2806 if let Some(expanded_expr) =
2808 self.maybe_implicit_convert_expr(tyenv, expr, bv.ty, ty.unwrap())
2809 {
2810 return self.translate_expr(
2811 tyenv,
2812 &expanded_expr,
2813 ty,
2814 bindings,
2815 root_flags,
2816 );
2817 }
2818
2819 tyenv.report_error(
2820 pos,
2821 format!(
2822 "Variable '{}' has type {} but we need {} in context",
2823 name.0,
2824 tyenv.types[bv.ty.index()].name(tyenv),
2825 tyenv.types[ty.unwrap().index()].name(tyenv)
2826 ),
2827 );
2828 }
2829
2830 Some(Expr::Var(bv.ty, bv.id))
2831 }
2832 &ast::Expr::ConstBool { val, pos } => {
2833 match ty {
2834 Some(ty) if ty != TypeId::BOOL => tyenv.report_error(
2835 pos,
2836 format!(
2837 "Boolean literal '{val}' has type {} but we need {} in context",
2838 BuiltinType::Bool.name(),
2839 tyenv.types[ty.index()].name(tyenv)
2840 ),
2841 ),
2842 Some(..) | None => {}
2843 };
2844 Some(Expr::ConstBool(TypeId::BOOL, val))
2845 }
2846 &ast::Expr::ConstInt { val, pos } => {
2847 let Some(ty) = ty else {
2848 tyenv.report_error(
2849 pos,
2850 "integer literal in a context that needs an explicit type".to_string(),
2851 );
2852 return None;
2853 };
2854
2855 let typ = &tyenv.types[ty.index()];
2856
2857 if !typ.is_int() && !typ.is_prim() {
2858 tyenv.report_error(
2859 pos,
2860 format!(
2861 "expected non-integer type {}, but found integer literal '{}'",
2862 tyenv.types[ty.index()].name(tyenv),
2863 val,
2864 ),
2865 );
2866 }
2867 Some(Expr::ConstInt(ty, val))
2868 }
2869 &ast::Expr::ConstPrim { ref val, pos } => {
2870 let val = tyenv.intern_mut(val);
2871 let const_ty = match tyenv.const_types.get(&val) {
2872 Some(ty) => *ty,
2873 None => {
2874 tyenv.report_error(pos, "Unknown constant");
2875 return None;
2876 }
2877 };
2878 if ty.is_some() && const_ty != ty.unwrap() {
2879 tyenv.report_error(
2880 pos,
2881 format!(
2882 "Constant '{}' has wrong type: expected {}, but is actually {}",
2883 tyenv.syms[val.index()],
2884 tyenv.types[ty.unwrap().index()].name(tyenv),
2885 tyenv.types[const_ty.index()].name(tyenv)
2886 ),
2887 );
2888 return None;
2889 }
2890 Some(Expr::ConstPrim(const_ty, val))
2891 }
2892 &ast::Expr::Let {
2893 ref defs,
2894 ref body,
2895 pos,
2896 } => {
2897 bindings.enter_scope();
2898
2899 let mut let_defs = vec![];
2901 for def in defs {
2902 let name = tyenv.intern_mut(&def.var);
2904
2905 let tid = match tyenv.get_type_by_name(&def.ty) {
2907 Some(tid) => tid,
2908 None => {
2909 tyenv.report_error(
2910 pos,
2911 format!("Unknown type {} for variable '{}'", def.ty.0, def.var.0),
2912 );
2913 continue;
2914 }
2915 };
2916
2917 let val = Box::new(unwrap_or_continue!(self.translate_expr(
2919 tyenv,
2920 &def.val,
2921 Some(tid),
2922 bindings,
2923 root_flags,
2924 )));
2925
2926 let id = bindings.add_var(name, tid);
2928 let_defs.push((id, tid, val));
2929 }
2930
2931 let body = Box::new(self.translate_expr(tyenv, body, ty, bindings, root_flags)?);
2933 let body_ty = body.ty();
2934
2935 bindings.exit_scope();
2937
2938 Some(Expr::Let {
2939 ty: body_ty,
2940 bindings: let_defs,
2941 body,
2942 })
2943 }
2944 }
2945 }
2946
2947 fn translate_iflet(
2948 &self,
2949 tyenv: &mut TypeEnv,
2950 iflet: &ast::IfLet,
2951 bindings: &mut Bindings,
2952 root_flags: TermFlags,
2953 ) -> Option<IfLet> {
2954 let rhs = self.translate_expr(tyenv, &iflet.expr, None, bindings, root_flags.on_lhs())?;
2957 let lhs = self.translate_pattern(tyenv, &iflet.pattern, rhs.ty(), bindings)?;
2958
2959 Some(IfLet { lhs, rhs })
2960 }
2961
2962 pub fn get_term_by_name(&self, tyenv: &TypeEnv, sym: &ast::Ident) -> Option<TermId> {
2964 tyenv
2965 .intern(sym)
2966 .and_then(|sym| self.term_map.get(&sym))
2967 .copied()
2968 }
2969
2970 pub fn get_rule_by_name(&self, tyenv: &TypeEnv, sym: &ast::Ident) -> Option<RuleId> {
2972 tyenv
2973 .intern(sym)
2974 .and_then(|sym| self.rule_map.get(&sym))
2975 .copied()
2976 }
2977
2978 pub fn get_variant_term(&self, tyenv: &TypeEnv, ty: TypeId, variant: VariantId) -> TermId {
2980 let variant = tyenv.get_variant(ty, variant);
2981 self.term_map[&variant.fullname]
2982 }
2983}
2984
2985#[cfg(test)]
2986mod test {
2987 use super::*;
2988 use crate::ast::Ident;
2989 use crate::lexer::Lexer;
2990 use crate::parser::parse;
2991
2992 #[test]
2993 fn build_type_env() {
2994 let text = r"
2995 (type UImm8 (primitive UImm8))
2996 (type A extern (enum (B (f1 u32) (f2 u32)) (C (f1 u32))))
2997 ";
2998 let ast = parse(Lexer::new(0, text).unwrap()).expect("should parse");
2999 let tyenv = TypeEnv::from_ast(&ast).expect("should not have type-definition errors");
3000
3001 let sym_a = tyenv
3002 .intern(&Ident("A".to_string(), Default::default()))
3003 .unwrap();
3004 let sym_b = tyenv
3005 .intern(&Ident("B".to_string(), Default::default()))
3006 .unwrap();
3007 let sym_c = tyenv
3008 .intern(&Ident("C".to_string(), Default::default()))
3009 .unwrap();
3010 let sym_a_b = tyenv
3011 .intern(&Ident("A.B".to_string(), Default::default()))
3012 .unwrap();
3013 let sym_a_c = tyenv
3014 .intern(&Ident("A.C".to_string(), Default::default()))
3015 .unwrap();
3016 let sym_uimm8 = tyenv
3017 .intern(&Ident("UImm8".to_string(), Default::default()))
3018 .unwrap();
3019 let sym_f1 = tyenv
3020 .intern(&Ident("f1".to_string(), Default::default()))
3021 .unwrap();
3022 let sym_f2 = tyenv
3023 .intern(&Ident("f2".to_string(), Default::default()))
3024 .unwrap();
3025
3026 assert_eq!(tyenv.type_map.get(&sym_uimm8).unwrap(), &TypeId(13));
3027 assert_eq!(tyenv.type_map.get(&sym_a).unwrap(), &TypeId(14));
3028
3029 let expected_types = vec![
3030 Type::Primitive(
3031 TypeId(13),
3032 sym_uimm8,
3033 Pos {
3034 file: 0,
3035 offset: 19,
3036 },
3037 ),
3038 Type::Enum {
3039 name: sym_a,
3040 id: TypeId(14),
3041 is_extern: true,
3042 is_nodebug: false,
3043 variants: vec![
3044 Variant {
3045 name: sym_b,
3046 fullname: sym_a_b,
3047 id: VariantId(0),
3048 fields: Fields::Struct(StructFields {
3049 fields: vec![
3050 StructField {
3051 name: sym_f1,
3052 id: FieldId(0),
3053 ty: TypeId::U32,
3054 },
3055 StructField {
3056 name: sym_f2,
3057 id: FieldId(1),
3058 ty: TypeId::U32,
3059 },
3060 ],
3061 }),
3062 pos: Pos {
3063 file: 0,
3064 offset: 77,
3065 },
3066 },
3067 Variant {
3068 name: sym_c,
3069 fullname: sym_a_c,
3070 id: VariantId(1),
3071 fields: Fields::Struct(StructFields {
3072 fields: vec![StructField {
3073 name: sym_f1,
3074 id: FieldId(0),
3075 ty: TypeId::U32,
3076 }],
3077 }),
3078 pos: Pos {
3079 file: 0,
3080 offset: 99,
3081 },
3082 },
3083 ],
3084 pos: Pos {
3085 file: 0,
3086 offset: 62,
3087 },
3088 },
3089 ];
3090
3091 assert_eq!(
3092 tyenv.types.len(),
3093 expected_types.len() + BuiltinType::ALL.len()
3094 );
3095 for (i, (actual, expected)) in tyenv
3096 .types
3097 .iter()
3098 .skip(BuiltinType::ALL.len())
3099 .zip(&expected_types)
3100 .enumerate()
3101 {
3102 assert_eq!(expected, actual, "`{i}`th type is not equal!");
3103 }
3104 }
3105}