1use std::collections::{BTreeSet, HashMap, HashSet};
111
112use super::{
113 Body, Declaration, Field, InstanceMember, Module, Predicate, Reference, ReferenceKind,
114 Saturation, SubPattern, Subject, TermPattern, TermPatternKind, TypeBinder, TypedTerm,
115 TypedTermKind,
116};
117use crate::canonical::HeadName;
118use crate::name::{Name, QualName};
119use crate::typer::{head_of, Type, TypeVariable};
120use crate::{CheckedModule, ModuleName, PhaseError, SpanLabel};
121use zelkova_syntax::position::NodeSpan;
122use zelkova_syntax::tuple::Tuple;
123
124pub const SPECIALISATION_LIMIT: usize = 32;
132
133#[derive(Debug, Clone, PartialEq)]
144pub enum Error {
145 Unbounded {
148 declaration: Name,
151 types: Vec<Type>,
154 span: NodeSpan,
156 used_in: Name,
158 },
159 NoInstance {
162 class: Name,
163 tpe: Type,
164 within: Name,
166 used_in: Name,
167 span: NodeSpan,
168 },
169 NotGround {
174 class: Name,
175 tpe: Type,
176 within: Name,
177 used_in: Name,
178 span: NodeSpan,
179 },
180 NoDeclaration {
183 name: Name,
184 within: Name,
185 used_in: Name,
186 span: NodeSpan,
187 },
188}
189
190impl PhaseError for Error {
191 fn message(&self) -> String {
192 match self {
193 Error::Unbounded { declaration, .. } => format!(
194 "`{}` needs itself at ever larger types, so it has no finite set of specialisations to compile",
195 declaration.as_str()
196 ),
197 Error::NoInstance {
198 class,
199 tpe,
200 within,
201 ..
202 } => format!(
203 "no instance of `{}` at `{}` was found for the use in `{}`",
204 class.as_str(),
205 tpe.written_with_letters(),
206 within.as_str()
207 ),
208 Error::NotGround {
209 class,
210 tpe,
211 within,
212 ..
213 } => format!(
214 "the use of an instance of `{}` in `{}` is at `{}`, which is not a type yet",
215 class.as_str(),
216 within.as_str(),
217 tpe.written_with_letters()
218 ),
219 Error::NoDeclaration { name, within, .. } => format!(
220 "`{}` has nothing to specialise, but `{}` uses it as a name that asks for an instance",
221 name.as_str(),
222 within.as_str()
223 ),
224 }
225 }
226
227 fn notes(&self) -> Vec<String> {
228 match self {
229 Error::Unbounded {
230 declaration,
231 types,
232 used_in,
233 ..
234 } => vec![
235 format!(
236 "{} nested specialisations of `{}`, the limit, were reached at `{}`, while compiling `{}`",
237 SPECIALISATION_LIMIT,
238 declaration.as_str(),
239 join(types),
240 used_in.as_str()
241 ),
242 "a constrained function is compiled once for each type it is used at, so the types it is used at have to be finite".to_string(),
243 ],
244 Error::NoInstance { tpe, used_in, .. } => {
245 let mut notes = vec![format!("while compiling `{}`", used_in.as_str())];
246 if matches!(tpe, Type::Record(_)) {
247 notes.push(
248 "a class at a record type is not compiled yet (`LANG-85`)".to_string(),
249 );
250 }
251 notes
252 }
253 Error::NotGround { used_in, .. } | Error::NoDeclaration { used_in, .. } => {
254 vec![format!("while compiling `{}`", used_in.as_str())]
255 }
256 }
257 }
258
259 fn labels(&self) -> Vec<SpanLabel> {
260 let (span, message) = match self {
261 Error::Unbounded { span, .. } => (span, "this declaration"),
262 Error::NoInstance { span, .. }
263 | Error::NotGround { span, .. }
264 | Error::NoDeclaration { span, .. } => (span, "this use"),
265 };
266
267 match span.span() {
268 Some(span) => vec![SpanLabel {
269 span,
270 message: message.to_owned(),
271 primary: true,
272 file: None,
273 }],
274 None => Vec::new(),
275 }
276 }
277}
278
279fn join(types: &[Type]) -> String {
281 types
282 .iter()
283 .map(|tpe| tpe.to_string())
284 .collect::<Vec<_>>()
285 .join(", ")
286}
287
288#[derive(Debug)]
291pub struct ModuleErrors {
292 pub module: ModuleName,
293 pub errors: Vec<Error>,
294}
295
296pub fn specialise(modules: &mut [&mut CheckedModule]) -> Result<(), Vec<ModuleErrors>> {
317 let outcome = {
318 let world = World::of(modules.iter().map(|module| &**module).collect());
319 world.read()
320 };
321
322 if outcome.errors.iter().any(|errors| !errors.is_empty()) {
323 return Err(outcome
324 .errors
325 .into_iter()
326 .enumerate()
327 .filter(|(_, errors)| !errors.is_empty())
328 .map(|(index, errors)| ModuleErrors {
329 module: modules[index].ir.name.clone(),
330 errors,
331 })
332 .collect());
333 }
334
335 for (module, found) in modules.iter_mut().zip(outcome.found) {
336 for (place, body) in found.roots {
337 let declaration = match place {
338 Place::Declaration(index) => module.ir.declarations.get_mut(index),
339 Place::Member { instance, member } => module
340 .ir
341 .instances
342 .get_mut(instance)
343 .and_then(|instance| instance.members.get_mut(member)),
344 };
345 if let Some(declaration) = declaration {
346 declaration.body = Some(body);
347 }
348 }
349 module.ir.specialisations = found.specialisations;
350 }
351
352 Ok(())
353}
354
355struct World<'a> {
357 modules: Vec<&'a CheckedModule>,
358 index: HashMap<ModuleName, usize>,
360 declarations: Vec<HashMap<&'a Name, usize>>,
362 members: HashMap<QualName, QualName>,
365 instances: HashMap<(QualName, HeadName), (usize, usize)>,
368}
369
370struct Outcome {
372 found: Vec<Found>,
373 errors: Vec<Vec<Error>>,
374}
375
376#[derive(Default)]
378struct Found {
379 roots: Vec<(Place, Body)>,
381 specialisations: Vec<super::Specialisation>,
382}
383
384#[derive(Debug, Clone, Copy, PartialEq, Eq)]
386enum Place {
387 Declaration(usize),
388 Member { instance: usize, member: usize },
389}
390
391#[derive(Debug, Clone, Copy)]
393struct Location {
394 module: usize,
395 place: Place,
396}
397
398type Assignment = HashMap<TypeVariable, Type>;
400
401impl<'a> World<'a> {
402 fn of(modules: Vec<&'a CheckedModule>) -> World<'a> {
403 let mut index = HashMap::new();
404 let mut declarations = Vec::new();
405 let mut members = HashMap::new();
406 let mut instances = HashMap::new();
407
408 for (position, module) in modules.iter().enumerate() {
409 index.insert(module.ir.name.clone(), position);
410 declarations.push(
411 module
412 .ir
413 .declarations
414 .iter()
415 .enumerate()
416 .map(|(at, declaration)| (&declaration.name, at))
417 .collect(),
418 );
419
420 let name = &module.canonical.name;
421 for (class_name, class) in &module.canonical.classes {
422 let class_qualified = name.qualify_name(class_name);
423 for member in &class.signature.members {
424 members.insert(name.qualify_name(&member.name), class_qualified.clone());
425 }
426 }
427
428 for (at, instance) in module.ir.instances.iter().enumerate() {
429 instances.insert(
430 (instance.class.clone(), instance.head_name.clone()),
431 (position, at),
432 );
433 }
434 }
435
436 World {
437 modules,
438 index,
439 declarations,
440 members,
441 instances,
442 }
443 }
444
445 fn module_of(&self, name: &QualName) -> Option<usize> {
447 self.index
448 .get(&ModuleName::new(name.package().clone(), name.module_name()))
449 .copied()
450 }
451
452 fn declaration(&self, location: Location) -> Option<&'a Declaration> {
454 let module = self.modules.get(location.module)?;
455 match location.place {
456 Place::Declaration(index) => module.ir.declarations.get(index),
457 Place::Member { instance, member } => {
458 module.ir.instances.get(instance)?.members.get(member)
459 }
460 }
461 }
462
463 fn read(&self) -> Outcome {
464 let mut found = Vec::new();
465 let mut errors: Vec<Vec<Error>> = self.modules.iter().map(|_| Vec::new()).collect();
466
467 for using in 0..self.modules.len() {
468 found.push(self.read_module(using, &mut errors));
469 }
470
471 Outcome { found, errors }
472 }
473
474 fn read_module(&self, using: usize, errors: &mut [Vec<Error>]) -> Found {
476 let ir = &self.modules[using].ir;
477 let mut used = Used::default();
478 let mut found = Found::default();
479
480 for (index, declaration) in ir.declarations.iter().enumerate() {
481 if !declaration.context.is_empty() || declaration.body.is_none() {
482 continue;
483 }
484 let location = Location {
485 module: using,
486 place: Place::Declaration(index),
487 };
488 if let Some(body) =
489 self.read_body(using, location, declaration, None, &mut used, errors)
490 {
491 found.roots.push((location.place, body));
492 }
493 }
494
495 for (instance_index, instance) in ir.instances.iter().enumerate() {
496 if instance.rejected || !instance.context.is_empty() {
497 continue;
498 }
499 for (member_index, member) in instance.members.iter().enumerate() {
500 if !member.context.is_empty() || member.body.is_none() {
501 continue;
502 }
503 let location = Location {
504 module: using,
505 place: Place::Member {
506 instance: instance_index,
507 member: member_index,
508 },
509 };
510 if let Some(body) = self.read_body(using, location, member, None, &mut used, errors)
511 {
512 found.roots.push((location.place, body));
513 }
514 }
515 }
516
517 while let Some(index) = used.pending.pop() {
520 let (location, assignment) = {
521 let spec = &used.specs[index];
522 (spec.location, spec.assignment.clone())
523 };
524 let Some(source) = self.declaration(location) else {
525 continue;
526 };
527 let declaration = self.read_copy(
528 using,
529 location,
530 source,
531 &assignment,
532 Some(index),
533 &mut used,
534 errors,
535 );
536 used.specs[index].declaration = declaration;
537 }
538
539 found.specialisations = used
540 .specs
541 .into_iter()
542 .filter_map(|spec| {
543 Some(super::Specialisation {
544 of: spec.subject,
545 key: spec.key,
546 declaration: spec.declaration?,
547 })
548 })
549 .collect();
550 found
551 }
552
553 fn read_body(
556 &self,
557 using: usize,
558 location: Location,
559 declaration: &Declaration,
560 parent: Option<usize>,
561 used: &mut Used,
562 errors: &mut [Vec<Error>],
563 ) -> Option<Body> {
564 let body = declaration.body.as_ref()?;
565 let assignment = Assignment::new();
566 let mut reader = Reader {
567 world: self,
568 using,
569 source: location.module,
570 assignment: &assignment,
571 within: &declaration.name,
572 parent,
573 used,
574 errors,
575 };
576 Some(reader.body(body))
577 }
578
579 #[allow(clippy::too_many_arguments)]
581 fn read_copy(
582 &self,
583 using: usize,
584 location: Location,
585 source: &Declaration,
586 assignment: &Assignment,
587 parent: Option<usize>,
588 used: &mut Used,
589 errors: &mut [Vec<Error>],
590 ) -> Option<Declaration> {
591 let body = source.body.as_ref()?;
592 let mut reader = Reader {
593 world: self,
594 using,
595 source: location.module,
596 assignment,
597 within: &source.name,
598 parent,
599 used,
600 errors,
601 };
602 let body = reader.body(body);
603
604 Some(Declaration {
605 name: source.name.clone(),
606 arity: source.arity,
607 tpe: apply(&source.tpe, assignment),
608 context: Vec::new(),
609 body: Some(body),
610 span: source.span,
611 })
612 }
613}
614
615#[derive(Default)]
617struct Used {
618 specs: Vec<Spec>,
619 table: HashMap<(Subject, Vec<Type>), usize>,
621 pending: Vec<usize>,
623 stopped: bool,
626}
627
628struct Spec {
630 subject: Subject,
631 location: Location,
633 key: Vec<Type>,
634 assignment: Assignment,
635 parent: Option<usize>,
638 arity: usize,
641 declaration: Option<Declaration>,
642}
643
644struct Reader<'r, 'a> {
649 world: &'r World<'a>,
650 using: usize,
652 source: usize,
654 assignment: &'r Assignment,
655 within: &'r Name,
657 parent: Option<usize>,
659 used: &'r mut Used,
660 errors: &'r mut [Vec<Error>],
661}
662
663impl Reader<'_, '_> {
664 fn ty(&self, tpe: &Type) -> Type {
665 apply(tpe, self.assignment)
666 }
667
668 fn binder(&self, binder: &TypeBinder) -> TypeBinder {
669 TypeBinder {
670 name: binder.name.clone(),
671 tpe: self.ty(&binder.tpe),
672 }
673 }
674
675 fn body(&mut self, body: &Body) -> Body {
676 Body {
677 parameters: body
678 .parameters
679 .iter()
680 .map(|parameter| self.binder(parameter))
681 .collect(),
682 expression: self.term(&body.expression),
683 }
684 }
685
686 fn term(&mut self, term: &TypedTerm) -> TypedTerm {
687 let kind = match &term.kind {
688 TypedTermKind::Int(value) => TypedTermKind::Int(*value),
689 TypedTermKind::Char(value) => TypedTermKind::Char(*value),
690 TypedTermKind::String(value) => TypedTermKind::String(value.clone()),
691 TypedTermKind::Float(value) => TypedTermKind::Float(*value),
692 TypedTermKind::Unit => TypedTermKind::Unit,
693 TypedTermKind::Hole => TypedTermKind::Hole,
694 TypedTermKind::Identifier { reference, context } => {
695 return self.identifier(term, reference, context);
696 }
697 TypedTermKind::Apply { .. } => return self.application(term),
698 TypedTermKind::Fun { param, body } => TypedTermKind::Fun {
699 param: self.binder(param),
700 body: Box::new(self.term(body)),
701 },
702 TypedTermKind::If {
703 cond,
704 true_branch,
705 false_branch,
706 } => TypedTermKind::If {
707 cond: Box::new(self.term(cond)),
708 true_branch: Box::new(self.term(true_branch)),
709 false_branch: Box::new(self.term(false_branch)),
710 },
711 TypedTermKind::Let {
712 binding,
713 value,
714 body,
715 } => TypedTermKind::Let {
716 binding: self.binder(binding),
717 value: Box::new(self.term(value)),
718 body: Box::new(self.term(body)),
719 },
720 TypedTermKind::Tuple(tuple) => TypedTermKind::Tuple(match tuple {
721 Tuple::Two(a, b) => Tuple::two(self.term(a), self.term(b)),
722 Tuple::Three(a, b, c) => Tuple::three(self.term(a), self.term(b), self.term(c)),
723 }),
724 TypedTermKind::Case {
725 scrutinee,
726 branches,
727 form,
728 } => TypedTermKind::Case {
729 scrutinee: Box::new(self.term(scrutinee)),
730 branches: branches
731 .iter()
732 .map(|(pattern, body)| (self.pattern(pattern), Box::new(self.term(body))))
733 .collect(),
734 form: *form,
735 },
736 TypedTermKind::Record(fields) => TypedTermKind::Record(self.fields(fields)),
737 TypedTermKind::Update { record, fields } => TypedTermKind::Update {
738 record: Box::new(self.term(record)),
739 fields: self.fields(fields),
740 },
741 TypedTermKind::Access {
742 record,
743 label,
744 label_span,
745 } => TypedTermKind::Access {
746 record: Box::new(self.term(record)),
747 label: label.clone(),
748 label_span: *label_span,
749 },
750 TypedTermKind::Accessor { label, label_span } => TypedTermKind::Accessor {
751 label: label.clone(),
752 label_span: *label_span,
753 },
754 };
755
756 TypedTerm {
757 span: term.span,
758 tpe: self.ty(&term.tpe),
759 kind,
760 }
761 }
762
763 fn fields(&mut self, fields: &[Field<TypedTerm>]) -> Vec<Field<TypedTerm>> {
764 fields
765 .iter()
766 .map(|field| Field {
767 label: field.label.clone(),
768 label_span: field.label_span,
769 value: self.term(&field.value),
770 })
771 .collect()
772 }
773
774 fn pattern(&self, pattern: &TermPattern) -> TermPattern {
775 let kind = match &pattern.kind {
776 TermPatternKind::Anything => TermPatternKind::Anything,
777 TermPatternKind::Bind(name) => TermPatternKind::Bind(name.clone()),
778 TermPatternKind::Unit => TermPatternKind::Unit,
779 TermPatternKind::Literal { tpe, value } => TermPatternKind::Literal {
780 tpe: self.ty(tpe),
781 value: value.clone(),
782 },
783 TermPatternKind::Constructor {
784 ctor,
785 adt_args,
786 args,
787 } => TermPatternKind::Constructor {
788 ctor: ctor.clone(),
789 adt_args: adt_args.iter().map(|tpe| self.ty(tpe)).collect(),
790 args: args.iter().map(|arg| self.sub_pattern(arg)).collect(),
791 },
792 TermPatternKind::Tuple { elements } => TermPatternKind::Tuple {
793 elements: elements.map(|element| self.sub_pattern(element)),
794 },
795 TermPatternKind::Hole { args } => TermPatternKind::Hole {
796 args: args.iter().map(|arg| self.sub_pattern(arg)).collect(),
797 },
798 TermPatternKind::Record { fields } => TermPatternKind::Record {
799 fields: fields
800 .iter()
801 .map(|field| Field {
802 label: field.label.clone(),
803 label_span: field.label_span,
804 value: self.sub_pattern(&field.value),
805 })
806 .collect(),
807 },
808 };
809
810 TermPattern {
811 span: pattern.span,
812 kind,
813 }
814 }
815
816 fn sub_pattern(&self, sub: &SubPattern) -> SubPattern {
817 SubPattern {
818 tpe: self.ty(&sub.tpe),
819 pattern: self.pattern(&sub.pattern),
820 }
821 }
822
823 fn application(&mut self, term: &TypedTerm) -> TypedTerm {
831 let mut spine = Vec::new();
832 let mut head = term;
833 while let TypedTermKind::Apply {
834 fun,
835 arg,
836 saturation,
837 } = &head.kind
838 {
839 spine.push((head, arg.as_ref(), *saturation));
840 head = fun;
841 }
842 spine.reverse();
843
844 let mut built = self.term(head);
845 let member_arity = self.member_arity(&built);
846
847 for (position, (node, argument, saturation)) in spine.into_iter().enumerate() {
848 let argument = self.term(argument);
849 let saturation = match member_arity {
850 Some(arity) if arity == position + 1 => Saturation::Saturated,
851 Some(_) => Saturation::Partial,
852 None => saturation,
853 };
854 built = TypedTerm {
855 span: node.span,
856 tpe: self.ty(&node.tpe),
857 kind: TypedTermKind::Apply {
858 fun: Box::new(built),
859 arg: Box::new(argument),
860 saturation,
861 },
862 };
863 }
864
865 built
866 }
867
868 fn member_arity(&self, head: &TypedTerm) -> Option<usize> {
870 let TypedTermKind::Identifier { reference, .. } = &head.kind else {
871 return None;
872 };
873 match &reference.kind {
874 ReferenceKind::InstanceMember(member) => Some(member.arity),
875 ReferenceKind::Specialised(index) => {
876 let spec = self.used.specs.get(*index)?;
877 matches!(spec.subject, Subject::InstanceMember { .. }).then_some(spec.arity)
878 }
879 _ => None,
880 }
881 }
882
883 fn error(&mut self, error: Error) {
886 self.errors[self.source].push(error);
887 }
888
889 fn used_in(&self) -> Name {
890 self.world.modules[self.using].ir.name.name().clone()
891 }
892
893 fn identifier(
896 &mut self,
897 term: &TypedTerm,
898 reference: &Reference,
899 context: &[Predicate],
900 ) -> TypedTerm {
901 let tpe = self.ty(&term.tpe);
902 let span = term.span;
903
904 if context.is_empty() {
905 return TypedTerm {
906 span,
907 tpe,
908 kind: TypedTermKind::Identifier {
909 reference: self.rebase(reference),
910 context: Vec::new(),
911 },
912 };
913 }
914
915 let ground: Vec<Predicate> = context
916 .iter()
917 .map(|predicate| Predicate {
918 class: predicate.class.clone(),
919 tpe: self.ty(&predicate.tpe),
920 })
921 .collect();
922
923 let resolved = self.resolve(reference, &ground, &tpe, span);
924
925 let (reference, context) = match resolved {
928 Some(kind) => (
929 Reference {
930 name: reference.name.clone(),
931 kind,
932 },
933 Vec::new(),
934 ),
935 None => (self.rebase(reference), ground),
936 };
937
938 TypedTerm {
939 span,
940 tpe,
941 kind: TypedTermKind::Identifier { reference, context },
942 }
943 }
944
945 fn resolve(
947 &mut self,
948 reference: &Reference,
949 ground: &[Predicate],
950 use_tpe: &Type,
951 span: NodeSpan,
952 ) -> Option<ReferenceKind> {
953 let name = match &reference.kind {
954 ReferenceKind::TopLevel(name) | ReferenceKind::Foreign(name, _, _) => name,
955 _ => {
956 self.no_declaration(Name::new(reference.name.clone()), span);
957 return None;
958 }
959 };
960
961 match self.world.members.get(name) {
962 Some(class) => self.resolve_member(name, class, ground, use_tpe, span),
963 None => self.resolve_declaration(reference, name, ground, span),
964 }
965 }
966
967 fn bind(
974 &mut self,
975 context: &[Predicate],
976 assignment: &Assignment,
977 span: NodeSpan,
978 ) -> Option<Vec<(TypeVariable, Type)>> {
979 let bound: Vec<(TypeVariable, Type)> = constrained(context)
980 .into_iter()
981 .filter_map(|variable| {
982 let tpe = assignment.get(&variable)?.clone();
983 Some((variable, tpe))
984 })
985 .collect();
986
987 let Some((variable, _)) = bound.iter().find(|(_, tpe)| !is_ground(tpe)) else {
988 return Some(bound);
989 };
990 if let Some(predicate) = context
991 .iter()
992 .find(|predicate| constrained(std::slice::from_ref(predicate)).contains(variable))
993 {
994 let tpe = apply(&predicate.tpe, assignment);
995 self.not_ground(&predicate.class, &tpe, span);
996 }
997 None
998 }
999
1000 fn not_ground(&mut self, class: &QualName, tpe: &Type, span: NodeSpan) {
1001 let error = Error::NotGround {
1002 class: class.unqualified_name(),
1003 tpe: tpe.clone(),
1004 within: self.within.clone(),
1005 used_in: self.used_in(),
1006 span,
1007 };
1008 self.error(error);
1009 }
1010
1011 fn no_declaration(&mut self, name: Name, span: NodeSpan) {
1012 let error = Error::NoDeclaration {
1013 name,
1014 within: self.within.clone(),
1015 used_in: self.used_in(),
1016 span,
1017 };
1018 self.error(error);
1019 }
1020
1021 fn no_instance(&mut self, class: &QualName, tpe: &Type, span: NodeSpan) {
1022 let error = Error::NoInstance {
1023 class: class.unqualified_name(),
1024 tpe: tpe.clone(),
1025 within: self.within.clone(),
1026 used_in: self.used_in(),
1027 span,
1028 };
1029 self.error(error);
1030 }
1031
1032 fn resolve_member(
1035 &mut self,
1036 member: &QualName,
1037 class: &QualName,
1038 ground: &[Predicate],
1039 use_tpe: &Type,
1040 span: NodeSpan,
1041 ) -> Option<ReferenceKind> {
1042 let predicate = ground
1043 .iter()
1044 .find(|predicate| &predicate.class == class)
1045 .or_else(|| ground.first())?;
1046
1047 let Some((head, _)) = head_of(&predicate.tpe) else {
1050 if matches!(predicate.tpe, Type::Variable(_)) {
1051 self.not_ground(class, &predicate.tpe, span);
1052 } else {
1053 self.no_instance(class, &predicate.tpe, span);
1054 }
1055 return None;
1056 };
1057 let Some(&(module, instance_index)) =
1058 self.world.instances.get(&(class.clone(), head.clone()))
1059 else {
1060 self.no_instance(class, &predicate.tpe, span);
1061 return None;
1062 };
1063
1064 let ir = &self.world.modules[module].ir;
1065 let instance = &ir.instances[instance_index];
1066 let member_name = member.unqualified_name();
1067 let Some(member_index) = instance
1068 .members
1069 .iter()
1070 .position(|declaration| declaration.name == member_name)
1071 else {
1072 self.no_declaration(member_name, span);
1073 return None;
1074 };
1075 if instance.rejected {
1076 self.no_instance(class, &predicate.tpe, span);
1077 return None;
1078 }
1079 let declaration = &instance.members[member_index];
1080
1081 if declaration.context.is_empty() {
1082 return Some(ReferenceKind::InstanceMember(Box::new(InstanceMember {
1083 module: ir.name.clone(),
1084 class: class.clone(),
1085 head,
1086 member: member_name,
1087 arity: declaration.arity,
1088 })));
1089 }
1090
1091 let mut assignment = Assignment::new();
1096 match_type(&declaration.tpe, use_tpe, &mut assignment);
1097 let bound = self.bind(&declaration.context, &assignment, span)?;
1098
1099 let subject = Subject::InstanceMember {
1100 class: class.clone(),
1101 head,
1102 member: member_name,
1103 };
1104 let location = Location {
1105 module,
1106 place: Place::Member {
1107 instance: instance_index,
1108 member: member_index,
1109 },
1110 };
1111 self.specialise(subject, location, declaration, bound)
1112 .map(ReferenceKind::Specialised)
1113 }
1114
1115 fn resolve_declaration(
1117 &mut self,
1118 reference: &Reference,
1119 name: &QualName,
1120 ground: &[Predicate],
1121 span: NodeSpan,
1122 ) -> Option<ReferenceKind> {
1123 let found = self.world.module_of(name).and_then(|module| {
1124 let at = *self.world.declarations[module].get(&name.unqualified_name())?;
1125 Some((module, at, &self.world.modules[module].ir.declarations[at]))
1126 });
1127 let Some((module, at, declaration)) = found else {
1128 self.no_declaration(name.unqualified_name(), span);
1129 return None;
1130 };
1131
1132 if declaration.context.is_empty() {
1134 return Some(self.rebase(reference).kind);
1135 }
1136
1137 let mut assignment = Assignment::new();
1138 for (pattern, predicate) in declaration.context.iter().zip(ground) {
1139 match_type(&pattern.tpe, &predicate.tpe, &mut assignment);
1141 }
1142 let bound = self.bind(&declaration.context, &assignment, span)?;
1143
1144 let location = Location {
1145 module,
1146 place: Place::Declaration(at),
1147 };
1148 self.specialise(
1149 Subject::Declaration(name.clone()),
1150 location,
1151 declaration,
1152 bound,
1153 )
1154 .map(ReferenceKind::Specialised)
1155 }
1156
1157 fn specialise(
1160 &mut self,
1161 subject: Subject,
1162 location: Location,
1163 declaration: &Declaration,
1164 bound: Vec<(TypeVariable, Type)>,
1165 ) -> Option<usize> {
1166 let key: Vec<Type> = bound.iter().map(|(_, tpe)| tpe.clone()).collect();
1167
1168 if let Some(&index) = self.used.table.get(&(subject.clone(), key.clone())) {
1169 return Some(index);
1170 }
1171
1172 let mut occurrences = 0;
1173 let mut ancestor = self.parent;
1174 while let Some(index) = ancestor {
1175 let spec = &self.used.specs[index];
1176 if spec.subject == subject {
1177 occurrences += 1;
1178 }
1179 ancestor = spec.parent;
1180 }
1181 if occurrences >= SPECIALISATION_LIMIT {
1182 self.used.stopped = true;
1186 self.used.pending.clear();
1187
1188 let reported = self.errors[location.module].iter().any(|error| {
1191 matches!(error, Error::Unbounded { declaration: reported, span, .. }
1192 if reported == &declaration.name && span.to_range() == declaration.span.to_range())
1193 });
1194 if !reported {
1195 let used_in = self.used_in();
1196 self.errors[location.module].push(Error::Unbounded {
1197 declaration: declaration.name.clone(),
1198 types: key,
1199 span: declaration.span,
1200 used_in,
1201 });
1202 }
1203 return None;
1204 }
1205 if self.used.stopped {
1206 return None;
1207 }
1208
1209 let index = self.used.specs.len();
1210 self.used
1211 .table
1212 .insert((subject.clone(), key.clone()), index);
1213 self.used.specs.push(Spec {
1214 subject,
1215 location,
1216 key,
1217 assignment: bound.into_iter().collect(),
1218 parent: self.parent,
1219 arity: declaration.arity,
1220 declaration: None,
1221 });
1222 self.used.pending.push(index);
1223 Some(index)
1224 }
1225
1226 fn rebase(&self, reference: &Reference) -> Reference {
1233 let kind = match &reference.kind {
1234 ReferenceKind::TopLevel(name) if self.source != self.using => {
1235 let arity = self.world.declarations[self.source]
1236 .get(&name.unqualified_name())
1237 .map(|at| self.world.modules[self.source].ir.declarations[*at].arity)
1238 .unwrap_or(0);
1239 ReferenceKind::Foreign(name.clone(), name.package().clone(), arity)
1240 }
1241 ReferenceKind::Foreign(name, _, _)
1242 if self.world.module_of(name) == Some(self.using) =>
1243 {
1244 ReferenceKind::TopLevel(name.clone())
1245 }
1246 other => other.clone(),
1247 };
1248
1249 Reference {
1250 name: reference.name.clone(),
1251 kind,
1252 }
1253 }
1254}
1255
1256fn apply(tpe: &Type, assignment: &Assignment) -> Type {
1260 if assignment.is_empty() {
1261 return tpe.clone();
1262 }
1263
1264 match tpe {
1265 Type::Variable(variable) => assignment
1266 .get(variable)
1267 .cloned()
1268 .unwrap_or_else(|| tpe.clone()),
1269 Type::Literal(_) | Type::Unit => tpe.clone(),
1270 Type::Fun {
1271 param_tpe,
1272 return_tpe,
1273 } => Type::Fun {
1274 param_tpe: Box::new(apply(param_tpe, assignment)),
1275 return_tpe: Box::new(apply(return_tpe, assignment)),
1276 },
1277 Type::Tuple(tuple) => Type::Tuple(tuple.map(|element| apply(element, assignment))),
1278 Type::Adt(name, arguments) => Type::Adt(
1279 name.clone(),
1280 arguments
1281 .iter()
1282 .map(|argument| apply(argument, assignment))
1283 .collect(),
1284 ),
1285 Type::Record(fields) => Type::Record(
1286 fields
1287 .iter()
1288 .map(|(label, tpe)| (label.clone(), apply(tpe, assignment)))
1289 .collect(),
1290 ),
1291 }
1292}
1293
1294fn is_ground(tpe: &Type) -> bool {
1296 match tpe {
1297 Type::Variable(_) => false,
1298 Type::Literal(_) | Type::Unit => true,
1299 Type::Fun {
1300 param_tpe,
1301 return_tpe,
1302 } => is_ground(param_tpe) && is_ground(return_tpe),
1303 Type::Tuple(tuple) => tuple.iter().all(is_ground),
1304 Type::Adt(_, arguments) => arguments.iter().all(is_ground),
1305 Type::Record(fields) => fields.values().all(is_ground),
1306 }
1307}
1308
1309fn match_type(pattern: &Type, ground: &Type, assignment: &mut Assignment) -> bool {
1315 match (pattern, ground) {
1316 (Type::Variable(variable), ground) => match assignment.get(variable) {
1317 Some(bound) => bound == ground,
1318 None => {
1319 assignment.insert(variable.clone(), ground.clone());
1320 true
1321 }
1322 },
1323 (Type::Literal(a), Type::Literal(b)) => a == b,
1324 (Type::Unit, Type::Unit) => true,
1325 (
1326 Type::Fun {
1327 param_tpe: a_param,
1328 return_tpe: a_return,
1329 },
1330 Type::Fun {
1331 param_tpe: b_param,
1332 return_tpe: b_return,
1333 },
1334 ) => {
1335 let param = match_type(a_param, b_param, assignment);
1338 let result = match_type(a_return, b_return, assignment);
1339 param && result
1340 }
1341 (Type::Tuple(a), Type::Tuple(b)) => match (a, b) {
1342 (Tuple::Two(a1, a2), Tuple::Two(b1, b2)) => {
1343 let first = match_type(a1, b1, assignment);
1344 let second = match_type(a2, b2, assignment);
1345 first && second
1346 }
1347 (Tuple::Three(a1, a2, a3), Tuple::Three(b1, b2, b3)) => {
1348 let first = match_type(a1, b1, assignment);
1349 let second = match_type(a2, b2, assignment);
1350 let third = match_type(a3, b3, assignment);
1351 first && second && third
1352 }
1353 _ => false,
1354 },
1355 (Type::Adt(a_name, a_args), Type::Adt(b_name, b_args)) => {
1356 if a_name != b_name || a_args.len() != b_args.len() {
1357 return false;
1358 }
1359 let mut matched = true;
1360 for (a, b) in a_args.iter().zip(b_args) {
1361 matched &= match_type(a, b, assignment);
1362 }
1363 matched
1364 }
1365 (Type::Record(a), Type::Record(b)) => {
1366 if a.len() != b.len() || !a.keys().eq(b.keys()) {
1367 return false;
1368 }
1369 let mut matched = true;
1370 for (a, b) in a.values().zip(b.values()) {
1371 matched &= match_type(a, b, assignment);
1372 }
1373 matched
1374 }
1375 _ => false,
1376 }
1377}
1378
1379fn constrained(context: &[Predicate]) -> Vec<TypeVariable> {
1381 fn collect(tpe: &Type, into: &mut Vec<TypeVariable>) {
1382 match tpe {
1383 Type::Variable(variable) => {
1384 if !into.contains(variable) {
1385 into.push(variable.clone());
1386 }
1387 }
1388 Type::Literal(_) | Type::Unit => {}
1389 Type::Fun {
1390 param_tpe,
1391 return_tpe,
1392 } => {
1393 collect(param_tpe, into);
1394 collect(return_tpe, into);
1395 }
1396 Type::Tuple(tuple) => tuple.iter().for_each(|element| collect(element, into)),
1397 Type::Adt(_, arguments) => arguments
1398 .iter()
1399 .for_each(|argument| collect(argument, into)),
1400 Type::Record(fields) => fields.values().for_each(|field| collect(field, into)),
1401 }
1402 }
1403
1404 let mut variables = Vec::new();
1405 for predicate in context {
1406 collect(&predicate.tpe, &mut variables);
1407 }
1408 variables
1409}
1410
1411fn references<'a>(term: &'a TypedTerm, into: &mut Vec<&'a Reference>) {
1415 match &term.kind {
1416 TypedTermKind::Identifier { reference, .. } => into.push(reference),
1417 TypedTermKind::Apply { fun, arg, .. } => {
1418 references(fun, into);
1419 references(arg, into);
1420 }
1421 TypedTermKind::Fun { body, .. } => references(body, into),
1422 TypedTermKind::If {
1423 cond,
1424 true_branch,
1425 false_branch,
1426 } => {
1427 references(cond, into);
1428 references(true_branch, into);
1429 references(false_branch, into);
1430 }
1431 TypedTermKind::Let { value, body, .. } => {
1432 references(value, into);
1433 references(body, into);
1434 }
1435 TypedTermKind::Tuple(tuple) => tuple.iter().for_each(|element| references(element, into)),
1436 TypedTermKind::Case {
1437 scrutinee,
1438 branches,
1439 ..
1440 } => {
1441 references(scrutinee, into);
1442 for (_, body) in branches {
1443 references(body, into);
1444 }
1445 }
1446 TypedTermKind::Record(fields) => fields
1447 .iter()
1448 .for_each(|field| references(&field.value, into)),
1449 TypedTermKind::Update { record, fields } => {
1450 references(record, into);
1451 fields
1452 .iter()
1453 .for_each(|field| references(&field.value, into));
1454 }
1455 TypedTermKind::Access { record, .. } => references(record, into),
1456 TypedTermKind::Int(_)
1457 | TypedTermKind::Char(_)
1458 | TypedTermKind::String(_)
1459 | TypedTermKind::Float(_)
1460 | TypedTermKind::Unit
1461 | TypedTermKind::Hole
1462 | TypedTermKind::Accessor { .. } => {}
1463 }
1464}
1465
1466pub fn mentioned_by_copies(module: &Module) -> Vec<Name> {
1480 let emitted: HashSet<&Name> = module
1481 .declarations
1482 .iter()
1483 .filter(|declaration| declaration.context.is_empty() && declaration.body.is_some())
1484 .map(|declaration| &declaration.name)
1485 .collect();
1486
1487 let constrained = module
1488 .declarations
1489 .iter()
1490 .filter(|declaration| !declaration.context.is_empty());
1491 let bindings = module
1492 .instances
1493 .iter()
1494 .flat_map(|instance| instance.members.iter());
1495
1496 let mut found = BTreeSet::new();
1497 for declaration in constrained.chain(bindings) {
1498 let Some(body) = &declaration.body else {
1499 continue;
1500 };
1501 let mut mentioned = Vec::new();
1502 references(&body.expression, &mut mentioned);
1503
1504 for reference in mentioned {
1505 if let ReferenceKind::TopLevel(name) = &reference.kind {
1506 let name = name.unqualified_name();
1507 if emitted.contains(&name) {
1508 found.insert(name);
1509 }
1510 }
1511 }
1512 }
1513
1514 found.into_iter().collect()
1515}
1516
1517#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
1521pub enum Item {
1522 Declaration(usize),
1524 InstanceMember { instance: usize, member: usize },
1526 Specialisation(usize),
1528}
1529
1530pub fn initialisation_items(module: &Module) -> Vec<Item> {
1547 let mut items: Vec<(Item, &Declaration)> = Vec::new();
1548 let mut declarations: HashMap<Name, Item> = HashMap::new();
1549
1550 for (index, declaration) in module.declarations.iter().enumerate() {
1551 if declaration.context.is_empty() && declaration.body.is_some() {
1552 let item = Item::Declaration(index);
1553 declarations.insert(declaration.name.clone(), item);
1554 items.push((item, declaration));
1555 }
1556 }
1557
1558 let mut members: HashMap<(QualName, HeadName, Name), Item> = HashMap::new();
1559 for (instance_index, instance) in module.instances.iter().enumerate() {
1560 if instance.rejected || !instance.context.is_empty() {
1561 continue;
1562 }
1563 let head = &instance.head_name;
1564 for (member_index, member) in instance.members.iter().enumerate() {
1565 if member.context.is_empty() && member.body.is_some() {
1566 let item = Item::InstanceMember {
1567 instance: instance_index,
1568 member: member_index,
1569 };
1570 members.insert(
1571 (instance.class.clone(), head.clone(), member.name.clone()),
1572 item,
1573 );
1574 items.push((item, member));
1575 }
1576 }
1577 }
1578
1579 for (index, specialisation) in module.specialisations.iter().enumerate() {
1580 items.push((Item::Specialisation(index), &specialisation.declaration));
1581 }
1582
1583 let mut mentions: HashMap<Item, Vec<Item>> = HashMap::new();
1585 let mut constants: HashSet<Item> = HashSet::new();
1586 for (item, declaration) in &items {
1587 let Some(body) = &declaration.body else {
1588 continue;
1589 };
1590 if body.parameters.is_empty() {
1591 constants.insert(*item);
1592 }
1593
1594 let mut found = Vec::new();
1595 references(&body.expression, &mut found);
1596 let reached: Vec<Item> = found
1597 .into_iter()
1598 .filter_map(|reference| match &reference.kind {
1599 ReferenceKind::TopLevel(name) => {
1600 declarations.get(&name.unqualified_name()).copied()
1601 }
1602 ReferenceKind::Specialised(index) => {
1603 (*index < module.specialisations.len()).then_some(Item::Specialisation(*index))
1604 }
1605 ReferenceKind::InstanceMember(member) if member.module == module.name => members
1606 .get(&(
1607 member.class.clone(),
1608 member.head.clone(),
1609 member.member.clone(),
1610 ))
1611 .copied(),
1612 _ => None,
1613 })
1614 .collect();
1615 mentions.insert(*item, reached);
1616 }
1617
1618 let dependencies = |item: Item| -> Vec<Item> {
1621 let mut seen = HashSet::from([item]);
1622 let mut reached = Vec::new();
1623 let mut pending: Vec<Item> = mentions
1624 .get(&item)
1625 .map(|mentioned| mentioned.iter().rev().copied().collect())
1626 .unwrap_or_default();
1627
1628 while let Some(next) = pending.pop() {
1629 if !seen.insert(next) {
1630 continue;
1631 }
1632 if constants.contains(&next) {
1633 reached.push(next);
1634 } else if let Some(mentioned) = mentions.get(&next) {
1635 pending.extend(mentioned.iter().rev().copied());
1636 }
1637 }
1638 reached
1639 };
1640
1641 let mut sequence: Vec<Item> = module
1642 .initialisation_order
1643 .iter()
1644 .filter_map(|name| declarations.get(name).copied())
1645 .filter(|item| constants.contains(item))
1646 .collect();
1647 let placed: HashSet<Item> = sequence.iter().copied().collect();
1648 sequence.extend(
1649 items
1650 .iter()
1651 .map(|(item, _)| *item)
1652 .filter(|item| constants.contains(item) && !placed.contains(item)),
1653 );
1654
1655 let mut order = Vec::new();
1656 let mut started: HashSet<Item> = HashSet::new();
1657 for root in sequence {
1658 if !started.insert(root) {
1659 continue;
1660 }
1661 let mut stack = vec![(root, dependencies(root).into_iter())];
1662
1663 while let Some((current, remaining)) = stack.last_mut() {
1664 let current = *current;
1665
1666 match remaining.next() {
1667 Some(dependency) => {
1668 if started.insert(dependency) {
1669 stack.push((dependency, dependencies(dependency).into_iter()));
1670 }
1671 }
1672 None => {
1673 order.push(current);
1674 stack.pop();
1675 }
1676 }
1677 }
1678 }
1679
1680 order
1681}