1use super::derivation::{derive_all, Candidate, Derived, WrittenInstance};
21use super::environment::{Environment, RootEnvironment};
22use super::{
23 binding_value, validate_context, Error, InstanceHeadProblem, NameTakenBy, Type, Value,
24};
25use crate::name::{Name, QualName};
26use crate::{ModuleName, SourceSpan, SpanLabel};
27use std::collections::{HashMap, HashSet};
28use zelkova_syntax::parser;
29use zelkova_syntax::position::NodeSpan;
30use zelkova_syntax::tuple::Tuple;
31
32#[derive(Debug, Clone, PartialEq)]
37pub struct Constraint {
38 pub class: QualName,
40 pub variable: Name,
42 pub span: NodeSpan,
44}
45
46#[derive(Debug, Clone, PartialEq)]
48pub struct Member {
49 pub name: Name,
50 pub tpe: Type,
54 pub span: NodeSpan,
56}
57
58#[derive(Debug, Clone, PartialEq)]
67pub struct ClassSignature {
68 pub variable: Name,
70 pub superclasses: Vec<Constraint>,
72 pub members: Vec<Member>,
74 pub derivations: Vec<Derivation>,
78 pub derivations_rejected: bool,
85 pub span: NodeSpan,
87}
88
89impl ClassSignature {
90 pub fn derivation(&self, member: &Name) -> Option<&Derivation> {
92 self.derivations
93 .iter()
94 .find(|derivation| &derivation.member == member)
95 }
96
97 pub fn derivable(&self) -> bool {
102 !self.members.is_empty()
103 && self
104 .members
105 .iter()
106 .all(|member| self.derivation(&member.name).is_some())
107 }
108
109 pub fn walks_one_value(&self) -> bool {
112 self.derivations
113 .iter()
114 .any(|derivation| matches!(derivation.bindings, DerivationBindings::Single { .. }))
115 }
116}
117
118#[derive(Debug, PartialEq)]
120pub struct Class {
121 pub signature: ClassSignature,
122}
123
124#[derive(Debug, Clone, PartialEq)]
127pub struct Derivation {
128 pub member: Name,
130 pub result: Type,
134 pub bindings: DerivationBindings,
136 pub span: NodeSpan,
138}
139
140#[derive(Debug, Clone, PartialEq)]
144pub enum DerivationBindings {
145 Pair {
147 matched: Box<Value>,
148 differed: Box<Value>,
149 combine: Box<Value>,
150 },
151 Single {
153 at_constructor: Box<Value>,
154 combine: Box<Value>,
155 },
156}
157
158#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
162pub enum DerivationRole {
163 Matched,
165 Differed,
167 AtConstructor,
169 Combine,
171}
172
173impl DerivationRole {
174 pub fn name(&self) -> &'static str {
176 match self {
177 DerivationRole::Matched => "matched",
178 DerivationRole::Differed => "differed",
179 DerivationRole::AtConstructor => "atConstructor",
180 DerivationRole::Combine => "combine",
181 }
182 }
183
184 pub fn parameters(&self) -> usize {
189 match self {
190 DerivationRole::Matched => 0,
191 DerivationRole::AtConstructor => 1,
192 DerivationRole::Differed | DerivationRole::Combine => 2,
193 }
194 }
195}
196
197impl DerivationBindings {
198 pub fn roles(&self) -> Vec<(DerivationRole, &Value)> {
200 match self {
201 DerivationBindings::Pair {
202 matched,
203 differed,
204 combine,
205 } => vec![
206 (DerivationRole::Matched, matched.as_ref()),
207 (DerivationRole::Differed, differed.as_ref()),
208 (DerivationRole::Combine, combine.as_ref()),
209 ],
210 DerivationBindings::Single {
211 at_constructor,
212 combine,
213 } => vec![
214 (DerivationRole::AtConstructor, at_constructor.as_ref()),
215 (DerivationRole::Combine, combine.as_ref()),
216 ],
217 }
218 }
219}
220
221#[derive(Debug, Clone, PartialEq, Eq, Hash)]
224pub enum InstanceHead {
225 Type(QualName, Vec<Name>),
227 Tuple(Tuple<Name>),
228 Unit,
229}
230
231impl InstanceHead {
232 pub fn name(&self) -> HeadName {
235 match self {
236 InstanceHead::Type(name, _) => HeadName::Type(name.clone()),
237 InstanceHead::Tuple(Tuple::Two(..)) => HeadName::TwoTuple,
238 InstanceHead::Tuple(Tuple::Three(..)) => HeadName::ThreeTuple,
239 InstanceHead::Unit => HeadName::Unit,
240 }
241 }
242
243 pub fn variables(&self) -> Vec<&Name> {
245 match self {
246 InstanceHead::Type(_, variables) => variables.iter().collect(),
247 InstanceHead::Tuple(tuple) => tuple.iter().collect(),
248 InstanceHead::Unit => Vec::new(),
249 }
250 }
251}
252
253#[derive(Debug, Clone, PartialEq, Eq, Hash)]
256pub enum HeadName {
257 Type(QualName),
258 TwoTuple,
259 ThreeTuple,
260 Unit,
261}
262
263impl HeadName {
264 pub fn describe(&self) -> String {
266 match self {
267 HeadName::Type(name) => format!("`{}`", name.unqualified_name()),
268 HeadName::TwoTuple => "a tuple of two".to_owned(),
269 HeadName::ThreeTuple => "a tuple of three".to_owned(),
270 HeadName::Unit => "`()`".to_owned(),
271 }
272 }
273
274 pub fn module(&self) -> Option<ModuleName> {
277 match self {
278 HeadName::Type(name) => Some(declaring_module(name)),
279 HeadName::TwoTuple | HeadName::ThreeTuple | HeadName::Unit => None,
280 }
281 }
282}
283
284#[derive(Debug, Clone, PartialEq)]
286pub struct InstanceName {
287 pub class: QualName,
288 pub head: HeadName,
289}
290
291#[derive(Debug, Clone, PartialEq)]
293pub struct InstanceSignature {
294 pub class: QualName,
296 pub head: InstanceHead,
297 pub context: Vec<Constraint>,
302 pub module: ModuleName,
305 pub span: NodeSpan,
308}
309
310#[derive(Debug, PartialEq)]
316pub struct Instance {
317 pub signature: InstanceSignature,
318 pub derived: bool,
322 pub bindings: Vec<Value>,
328}
329
330#[derive(Debug, Clone, PartialEq)]
333pub struct PublishedInstance {
334 pub signature: InstanceSignature,
335 pub source: Option<SourceSpan>,
336}
337
338impl PublishedInstance {
339 pub(crate) fn same_declaration(&self, other: &PublishedInstance) -> bool {
341 self.signature.class == other.signature.class
342 && self.signature.head.name() == other.signature.head.name()
343 && self.signature.module == other.signature.module
344 }
345}
346
347#[derive(Debug, Clone, Copy, PartialEq)]
350pub enum DeclarationSite {
351 InThisModule(NodeSpan),
352 InImportedModule(SourceSpan),
353 Unknown,
354}
355
356impl DeclarationSite {
357 pub fn label(&self, message: String) -> Option<SpanLabel> {
359 match self {
360 DeclarationSite::InThisModule(span) => span.span().map(|span| SpanLabel {
361 span,
362 message,
363 primary: false,
364 file: None,
365 }),
366 DeclarationSite::InImportedModule(source) => Some(SpanLabel {
367 span: source.span,
368 message,
369 primary: false,
370 file: Some(source.file),
371 }),
372 DeclarationSite::Unknown => None,
373 }
374 }
375}
376
377pub(crate) fn declaring_module(name: &QualName) -> ModuleName {
379 ModuleName::new(name.package().clone(), name.module_name())
380}
381
382fn class_head(head: &parser::Type) -> Option<(&Name, &Name)> {
385 let parser::TypeKind::Unqualified(name, args) = &head.kind else {
386 return None;
387 };
388
389 match args.as_slice() {
390 [parser::Type {
391 kind: parser::TypeKind::Variable(variable),
392 ..
393 }] => Some((name, variable)),
394 _ => None,
395 }
396}
397
398pub(super) fn member_names(class: &parser::ClassDecl) -> impl Iterator<Item = (&Name, NodeSpan)> {
402 class.members.iter().filter_map(|member| match member {
403 parser::ClassMember::Signature(signature) => Some((&signature.name, signature.span)),
404 parser::ClassMember::Derivation(_) => None,
405 })
406}
407
408pub(super) fn declare_classes<'a>(
416 env: &mut RootEnvironment,
417 classes: &'a [parser::ClassDecl],
418 types: &[parser::UnionType],
419) -> (Vec<(usize, &'a Name, &'a Name)>, Vec<Error>) {
420 let mut declared: Vec<(usize, &Name, &Name)> = Vec::new();
421 let mut first: HashMap<&Name, NodeSpan> = HashMap::new();
422 let mut errors = Vec::new();
423
424 for (index, class) in classes.iter().enumerate() {
425 let Some((name, variable)) = class_head(&class.head) else {
426 errors.push(Error::InvalidClassHead(class.head.span));
427 continue;
428 };
429
430 if let Some(tpe) = types.iter().find(|tpe| &tpe.name == name) {
431 errors.push(Error::ClassNameTaken(
432 name.clone(),
433 NameTakenBy::Type,
434 class.span,
435 tpe.span,
436 ));
437 continue;
438 }
439
440 if let Some(earlier) = first.get(name) {
441 errors.push(Error::ClassNameTaken(
442 name.clone(),
443 NameTakenBy::Class,
444 class.span,
445 *earlier,
446 ));
447 continue;
448 }
449
450 first.insert(name, class.span);
451 env.insert_declared_class(name);
452 declared.push((index, name, variable));
453 }
454
455 (declared, errors)
456}
457
458pub(super) fn class_signature(
461 env: &RootEnvironment,
462 class: &parser::ClassDecl,
463 name: &Name,
464 variable: &Name,
465) -> Result<ClassSignature, Vec<Error>> {
466 let mut errors = Vec::new();
467
468 let superclasses = match constraints(
469 env,
470 class.context.as_ref(),
471 &[variable],
472 Error::ConstraintVariableUnbound,
473 ) {
474 Ok(superclasses) => superclasses,
475 Err(context_errors) => {
476 errors.extend(context_errors);
477 Vec::new()
478 }
479 };
480
481 let mut members = Vec::new();
482 let mut first: HashMap<&Name, NodeSpan> = HashMap::new();
483
484 for member in class.members.iter() {
485 let parser::ClassMember::Signature(signature) = member else {
486 continue;
487 };
488
489 if let Some(earlier) = first.get(&signature.name) {
490 errors.push(Error::MemberDeclaredTwice(
491 signature.name.clone(),
492 signature.span,
493 *earlier,
494 ));
495 continue;
496 }
497 first.insert(&signature.name, signature.span);
498
499 if let Some(context) = &signature.context {
500 errors.push(Error::MemberConstrained(
501 signature.name.clone(),
502 context.span,
503 ));
504 }
505
506 if signature.marked_unsafe {
507 errors.push(Error::MemberUnsafe(signature.name.clone(), signature.span));
508 }
509
510 match Type::from_parser_type(env, &signature.tpe) {
511 Ok(tpe) if !mentions(&tpe, variable) => {
512 errors.push(Error::MemberMissesClassVariable(
513 signature.name.clone(),
514 name.clone(),
515 variable.clone(),
516 signature.span,
517 ));
518 }
519 Ok(tpe) => members.push(Member {
520 name: signature.name.clone(),
521 tpe,
522 span: signature.span,
523 }),
524 Err(error) => errors.push(error),
525 }
526 }
527
528 if errors.is_empty() {
529 Ok(ClassSignature {
530 variable: variable.clone(),
531 superclasses,
532 members,
533 derivations: Vec::new(),
534 derivations_rejected: false,
535 span: class.span,
536 })
537 } else {
538 Err(errors)
539 }
540}
541
542pub(super) fn mentions(tpe: &Type, variable: &Name) -> bool {
544 match tpe {
545 Type::Variable(name) => name == variable,
546 Type::Type(_, args) => args.iter().any(|arg| mentions(arg, variable)),
547 Type::Record(fields) => fields.values().any(|field| mentions(field, variable)),
548 Type::Arrow(param, result) => mentions(param, variable) || mentions(result, variable),
549 Type::Tuple(tuple) => tuple.iter().any(|element| mentions(element, variable)),
550 Type::Unit => false,
551 }
552}
553
554pub(super) fn written_variables(tpe: &parser::Type) -> Vec<&Name> {
559 fn walk<'a>(tpe: &'a parser::Type, into: &mut Vec<&'a Name>) {
560 match &tpe.kind {
561 parser::TypeKind::Variable(name) => {
562 if !into.contains(&name) {
563 into.push(name);
564 }
565 }
566 parser::TypeKind::Unqualified(_, args) => args.iter().for_each(|arg| walk(arg, into)),
567 parser::TypeKind::Arrow(param, result) => {
568 walk(param, into);
569 walk(result, into);
570 }
571 parser::TypeKind::Tuple(tuple) => tuple.iter().for_each(|element| walk(element, into)),
572 parser::TypeKind::Record(fields) => {
573 fields.iter().for_each(|field| walk(&field.value, into))
574 }
575 parser::TypeKind::Unit => {}
576 }
577 }
578
579 let mut variables = Vec::new();
580 walk(tpe, &mut variables);
581 variables
582}
583
584pub(super) fn constraints(
593 env: &RootEnvironment,
594 context: Option<&parser::Context>,
595 bound: &[&Name],
596 unbound: fn(Name, NodeSpan) -> Error,
597) -> Result<Vec<Constraint>, Vec<Error>> {
598 let Some(context) = context else {
599 return Ok(Vec::new());
600 };
601
602 let shaped = validate_context(context)?;
603 let mut constraints = Vec::new();
604 let mut errors = Vec::new();
605
606 for ((class, args), written) in shaped.into_iter().zip(context.constraints.iter()) {
607 let resolved = env.find_class(class).cloned();
608 if resolved.is_none() {
609 errors.push(Error::ClassNotFound(class.clone(), written.span));
610 }
611
612 let variable = match args {
613 [parser::Type {
614 kind: parser::TypeKind::Variable(variable),
615 span,
616 }] => {
617 if bound.contains(&variable) {
618 Some(variable.clone())
619 } else {
620 errors.push(unbound(variable.clone(), *span));
621 None
622 }
623 }
624 _ => {
625 errors.push(Error::ConstraintNotOnVariable(written.span));
626 None
627 }
628 };
629
630 if let (Some(class), Some(variable)) = (resolved, variable) {
631 constraints.push(Constraint {
632 class,
633 variable,
634 span: written.span,
635 });
636 }
637 }
638
639 if errors.is_empty() {
640 Ok(constraints)
641 } else {
642 Err(errors)
643 }
644}
645
646fn instance_head(
649 env: &RootEnvironment,
650 instance: &parser::InstanceDecl,
651) -> Result<(QualName, InstanceHead), Vec<Error>> {
652 let head = &instance.head;
653 let parser::TypeKind::Unqualified(class, args) = &head.kind else {
654 return Err(vec![Error::InvalidInstanceHead(
655 InstanceHeadProblem::NotAClass,
656 head.span,
657 )]);
658 };
659
660 let [argument] = args.as_slice() else {
661 return Err(vec![Error::InvalidInstanceHead(
662 InstanceHeadProblem::ClassApplied(args.len()),
663 head.span,
664 )]);
665 };
666
667 let mut errors = Vec::new();
668 let written = class;
669 let class = env.find_class(written).cloned();
670 if class.is_none() {
671 errors.push(Error::ClassNotFound(written.clone(), head.span));
672 }
673
674 let tpe = instance_head_type(env, argument);
675 match (class, tpe) {
676 (Some(class), Ok(tpe)) if errors.is_empty() => Ok((class, tpe)),
677 (_, tpe) => {
678 errors.extend(tpe.err().into_iter().flatten());
679 Err(errors)
680 }
681 }
682}
683
684fn instance_head_type(
687 env: &RootEnvironment,
688 argument: &parser::Type,
689) -> Result<InstanceHead, Vec<Error>> {
690 match &argument.kind {
691 parser::TypeKind::Unqualified(name, args) => {
692 let Some(declared) = env.find_type(name) else {
693 return Err(vec![Error::TypeNotFound(name.clone(), argument.span)]);
694 };
695 if declared.arity() != args.len() {
696 return Err(vec![Error::TypeArityMismatch(
697 name.clone(),
698 declared.arity(),
699 args.len(),
700 argument.span,
701 )]);
702 }
703
704 let name = declared.name.clone();
705 Ok(InstanceHead::Type(name, distinct_variables(args.iter())?))
706 }
707 parser::TypeKind::Tuple(tuple) => {
708 distinct_variables(tuple.iter())?;
709 let tuple = tuple.try_map(|element| match &element.kind {
710 parser::TypeKind::Variable(name) => Ok(name.clone()),
711 _ => Err(vec![Error::InvalidInstanceHead(
712 InstanceHeadProblem::ArgumentNotVariable,
713 element.span,
714 )]),
715 })?;
716 Ok(InstanceHead::Tuple(tuple))
717 }
718 parser::TypeKind::Unit => Ok(InstanceHead::Unit),
719 parser::TypeKind::Variable(name) => Err(vec![Error::InvalidInstanceHead(
720 InstanceHeadProblem::Variable(name.clone()),
721 argument.span,
722 )]),
723 parser::TypeKind::Arrow(..) => Err(vec![Error::InvalidInstanceHead(
724 InstanceHeadProblem::Function,
725 argument.span,
726 )]),
727 parser::TypeKind::Record(..) => Err(vec![Error::InvalidInstanceHead(
728 InstanceHeadProblem::Record,
729 argument.span,
730 )]),
731 }
732}
733
734fn distinct_variables<'a>(
738 args: impl Iterator<Item = &'a parser::Type>,
739) -> Result<Vec<Name>, Vec<Error>> {
740 let mut seen: HashSet<&Name> = HashSet::new();
741 let mut variables = Vec::new();
742 let mut errors = Vec::new();
743
744 for arg in args {
745 match &arg.kind {
746 parser::TypeKind::Variable(name) if seen.contains(name) => {
747 errors.push(Error::InvalidInstanceHead(
748 InstanceHeadProblem::RepeatedVariable(name.clone()),
749 arg.span,
750 ));
751 }
752 parser::TypeKind::Variable(name) => {
753 seen.insert(name);
754 variables.push(name.clone());
755 }
756 _ => errors.push(Error::InvalidInstanceHead(
757 InstanceHeadProblem::ArgumentNotVariable,
758 arg.span,
759 )),
760 }
761 }
762
763 if errors.is_empty() {
764 Ok(variables)
765 } else {
766 Err(errors)
767 }
768}
769
770pub(super) struct Instances {
772 pub instances: Vec<Instance>,
774 pub errors: Vec<Error>,
778}
779
780pub(super) fn do_instances(
797 env: &RootEnvironment,
798 instances: &[parser::InstanceDecl],
799 unresolved: &mut Vec<Error>,
800) -> Instances {
801 let module = env.module_name().clone();
802 let mut errors = Vec::new();
803
804 let heads: Vec<Result<(QualName, InstanceHead), Vec<Error>>> = instances
805 .iter()
806 .map(|instance| instance_head(env, instance))
807 .collect();
808
809 let mut in_scope: HashSet<(QualName, HeadName)> = heads
814 .iter()
815 .filter_map(|head| head.as_ref().ok())
816 .map(|(class, head)| (class.clone(), head.name()))
817 .collect();
818 in_scope.extend(env.imported_instances().iter().map(|published| {
819 (
820 published.signature.class.clone(),
821 published.signature.head.name(),
822 )
823 }));
824
825 let mut contexts: Vec<Option<Result<Vec<Constraint>, Vec<Error>>>> = instances
828 .iter()
829 .zip(&heads)
830 .map(|(instance, head)| {
831 let (_, head) = head.as_ref().ok()?;
832 Some(constraints(
833 env,
834 instance.context.as_ref(),
835 &head.variables(),
836 Error::ConstraintVariableUnbound,
837 ))
838 })
839 .collect();
840
841 let written: Vec<WrittenInstance> = heads
844 .iter()
845 .zip(&contexts)
846 .filter_map(|(head, context)| {
847 let (class, head) = head.as_ref().ok()?;
848 let context = match context {
851 Some(Ok(context)) => context
852 .iter()
853 .map(|constraint| (constraint.class.clone(), constraint.variable.clone()))
854 .collect(),
855 _ => Vec::new(),
856 };
857
858 Some(WrittenInstance {
859 class: class.clone(),
860 head: head.clone(),
861 context,
862 })
863 })
864 .collect();
865
866 let candidates: Vec<(usize, Candidate)> = instances
867 .iter()
868 .zip(&heads)
869 .zip(&contexts)
870 .enumerate()
871 .filter_map(|(index, ((instance, head), context))| {
872 let parser::InstanceBody::Derived(span) = &instance.body else {
873 return None;
874 };
875 let (class, head) = head.as_ref().ok()?;
876 let context = match (&instance.context, context) {
877 (Some(written), Some(Ok(context))) => Some((context.as_slice(), written.span)),
878 _ => None,
879 };
880
881 Some((
882 index,
883 Candidate {
884 class,
885 head,
886 context,
887 span: *span,
888 },
889 ))
890 })
891 .collect();
892 let (indices, candidates): (Vec<usize>, Vec<Candidate>) = candidates.into_iter().unzip();
893 let signatures: Vec<Option<&ClassSignature>> = candidates
894 .iter()
895 .map(|candidate| env.class_signature(candidate.class))
896 .collect();
897 let mut derived: HashMap<usize, Result<Derived, Vec<Error>>> = indices
898 .into_iter()
899 .zip(derive_all(env, &candidates, &signatures, &written))
900 .collect();
901
902 let mut declared: Vec<(QualName, HeadName, NodeSpan)> = Vec::new();
903 let mut kept = Vec::new();
904
905 for (index, (instance, head)) in instances.iter().zip(heads).enumerate() {
906 let (class, head) = match head {
909 Ok(resolved) => resolved,
910 Err(head_errors) => {
911 errors.extend(head_errors);
912 continue;
913 }
914 };
915 let class = &class;
916
917 let mut instance_errors = Vec::new();
918 let mut failed_silently = false;
919 let signature = env.class_signature(class);
920
921 let mut context = match contexts[index].take() {
922 Some(Ok(context)) => context,
923 Some(Err(context_errors)) => {
924 instance_errors.extend(context_errors);
925 Vec::new()
926 }
927 None => Vec::new(),
928 };
929
930 let bindings = match &instance.body {
931 parser::InstanceBody::Derived(_) => {
932 match derived.remove(&index) {
935 Some(Ok(derived)) => {
936 context = derived.context;
937 derived.bindings
938 }
939 Some(Err(derive_errors)) => {
940 failed_silently |= derive_errors.is_empty();
943 instance_errors.extend(derive_errors);
944 Vec::new()
945 }
946 None => Vec::new(),
947 }
948 }
949 parser::InstanceBody::Bindings(bindings) => {
950 let (values, binding_errors) =
951 instance_bindings(env, class, signature, instance, bindings, unresolved);
952 instance_errors.extend(binding_errors);
953 values
954 }
955 };
956
957 let head_name = head.name();
958
959 let class_module = declaring_module(class);
960 let head_module = head_name.module();
961 if class_module != module && head_module.as_ref() != Some(&module) {
962 instance_errors.push(Error::OrphanInstance(
963 Box::new(InstanceName {
964 class: class.clone(),
965 head: head_name.clone(),
966 }),
967 instance.span,
968 ));
969 }
970
971 let first = declared
972 .iter()
973 .find(|(c, h, _)| c == class && *h == head_name)
974 .map(|(_, _, span)| DeclarationSite::InThisModule(*span))
975 .or_else(|| {
976 env.imported_instances()
977 .iter()
978 .find(|published| {
979 &published.signature.class == class
980 && published.signature.head.name() == head_name
981 })
982 .map(|published| match published.source {
983 Some(source) => DeclarationSite::InImportedModule(source),
984 None => DeclarationSite::Unknown,
985 })
986 });
987 if let Some(first) = first {
988 instance_errors.push(Error::DuplicateInstance(
989 Box::new(InstanceName {
990 class: class.clone(),
991 head: head_name.clone(),
992 }),
993 instance.span,
994 first,
995 ));
996 }
997 declared.push((class.clone(), head_name.clone(), instance.span));
998
999 if let Some(signature) = signature {
1000 for superclass in &signature.superclasses {
1001 if !in_scope.contains(&(superclass.class.clone(), head_name.clone())) {
1002 instance_errors.push(Error::MissingSuperclassInstance(
1003 Box::new(InstanceName {
1004 class: class.clone(),
1005 head: head_name.clone(),
1006 }),
1007 superclass.class.clone(),
1008 instance.span,
1009 ));
1010 }
1011 }
1012 }
1013
1014 if instance_errors.is_empty() && !failed_silently {
1015 kept.push(Instance {
1016 signature: InstanceSignature {
1017 class: class.clone(),
1018 head: head.clone(),
1019 context,
1020 module: module.clone(),
1021 span: instance.span,
1022 },
1023 bindings,
1024 derived: matches!(instance.body, parser::InstanceBody::Derived(_)),
1025 });
1026 } else {
1027 errors.extend(instance_errors);
1028 }
1029 }
1030
1031 Instances {
1032 instances: kept,
1033 errors,
1034 }
1035}
1036
1037fn instance_bindings(
1045 env: &RootEnvironment,
1046 class: &QualName,
1047 signature: Option<&ClassSignature>,
1048 instance: &parser::InstanceDecl,
1049 bindings: &[parser::FunBinding],
1050 unresolved: &mut Vec<Error>,
1051) -> (Vec<Value>, Vec<Error>) {
1052 let mut values = Vec::new();
1053 let mut errors = Vec::new();
1054 let mut first: HashMap<&Name, NodeSpan> = HashMap::new();
1055 let class_name = class.unqualified_name();
1056
1057 for binding in bindings {
1058 if let Some(signature) = signature {
1059 if !signature.members.iter().any(|m| m.name == binding.name) {
1060 errors.push(Error::InstanceBindingNotMember(
1061 binding.name.clone(),
1062 class_name.clone(),
1063 binding.span,
1064 ));
1065 continue;
1066 }
1067 }
1068
1069 if let Some(earlier) = first.get(&binding.name) {
1070 errors.push(Error::InstanceMemberBoundTwice(
1071 binding.name.clone(),
1072 binding.span,
1073 *earlier,
1074 ));
1075 continue;
1076 }
1077 first.insert(&binding.name, binding.span);
1078
1079 match binding_value(env, binding, unresolved) {
1080 Ok(value) => values.push(value),
1081 Err(error) => errors.push(error),
1082 }
1083 }
1084
1085 if let Some(signature) = signature {
1086 for member in &signature.members {
1087 if !first.contains_key(&member.name) {
1088 errors.push(Error::InstanceMemberMissing(
1089 member.name.clone(),
1090 class_name.clone(),
1091 instance.span,
1092 ));
1093 }
1094 }
1095 }
1096
1097 (values, errors)
1098}