zelkova_compiler/canonical/derivation.rs
1//! Derivation: what a class says about how it is derived, and what a `derived` instance is
2//! made of.
3//!
4//! [Type classes](../../../docs/spec/type-classes.md#an-instance-may-be-derived) is the
5//! rule, and this module is its three halves, each run during canonicalization.
6//!
7//! # A derivation is checked where it is written
8//!
9//! [`class_derivations`] holds each `derived member` of a class body to what the chapter
10//! asks of it: it names a member, once; the member's signature is `a -> a -> R` or
11//! `a -> R` with `R` free of the class variable; its bindings are exactly the two or three
12//! that signature calls for; and the derivations cover every member or none. What passes
13//! is kept on the [`ClassSignature`], so an importing module reads it from the interface.
14//!
15//! # What a derived instance requires
16//!
17//! [`derive_all`] takes every `derived` instance of a module together. Each is read for
18//! the shape its head gives a walk — a union's constructors, a tuple, `()` — and for what
19//! every argument of every variant needs, which is an instance of the derived class at the
20//! argument's type. An argument that is a variable of the head is a constraint on the
21//! instance: that is the context, inferred. An argument of a concrete type needs an
22//! instance in scope, and one that is an application needs the instance of its head and
23//! whatever that instance's context asks of the arguments, down to the variables.
24//!
25//! An instance that writes a context has that context and no other. What its arguments
26//! need is still read, and each constraint of it has to be one the written context
27//! provides, itself or through a class it is a superclass of ([`provides`]); one that is
28//! not is [`Error::DerivedInstanceContextTooNarrow`].
29//!
30//! A recursive type asks for its own instance, and a group of types may ask for each
31//! other's, so the instances being derived count as in scope with the contexts being
32//! inferred, and the contexts are computed together as a fixed point: each starts empty
33//! and grows by what the others' contexts ask, until nothing grows. A written context is
34//! where its instance starts and stays. A context holds pairs of a class and one of the
35//! head's variables, and the classes that can appear in one are not only the derived one:
36//! a written or imported instance's context names whatever its parameters need, and that
37//! is followed too. The set of such pairs is finite, the classes in scope times the
38//! head's variables, so it stops. What the instance ends with is read off once more from
39//! scratch, which is what makes its order the order the type's arguments are written in
40//! and not the order the iteration happened to find them.
41//!
42//! # A derived instance is given its members
43//!
44//! The walk is written out as canonical code ([`Generated`]) and the instance carries it
45//! as bindings, where a written instance's would be. From there the typer checks them
46//! against the member's signature with the inferred context given, and nothing after
47//! canonicalization knows the instance was derived.
48//!
49//! The class's bindings are *placed*, not called
50//! ([*The bindings are inlined*](../../../docs/spec/type-classes.md#the-bindings-are-inlined-not-called)).
51//! `combine`'s first parameter is bound once, by a `case` of one branch whose scrutinee is
52//! the answer for one part, and its second is replaced by the rest of the walk, so that
53//! the rest is evaluated where the body reaches it and nowhere else
54//! ([`DEC-24` decision 8](../../../docs/decisions/dec-24.md#8--combines-first-parameter-is-a-value-and-its-second-is-the-rest-of-the-walk)).
55//! `matched`, `differed` and `atConstructor` are placed the same way, their parameters
56//! bound to the values the walk hands them.
57//!
58//! Three things make that safe.
59//!
60//! - **Capture.** The rest of the walk mentions the names the definition gave the
61//! arguments, and a class author's binding may bind any name a source file can spell.
62//! The names the definition gives are `$left`, `$right`, `$value`, `$a1`, `$b1`, and so
63//! on, and every name a placed body binds is replaced by one of its own, `$3$x`: a `$`, a
64//! serial and the name the class wrote. No source file can write a `$`, so no binding of
65//! a class can bind one of these. What that makes true is that no generated binder is ever
66//! in the scope of another binding of the same name, however many copies of a body nest in
67//! each other. A name is still bound in more than one place: each alternative of a walk
68//! binds `$a1`, `$b1` and so on in its own branch, and the rest of the walk is copied at
69//! every mention of `combine`'s second parameter, carrying the names it binds with it. Those
70//! are sibling scopes, in which nothing is captured. The JavaScript emitter leaves a name
71//! that is not a reserved word as it is, so each is an identifier there, and none is a name
72//! the emitter makes for itself: those are a `$` and a word (`$curry`), a `$` and digits,
73//! and names with a package, `companion` or `is` as their first segment, where the first
74//! segment of these is a serial.
75//! - **`Position` values.** A constructor's place in its declaration is a value of
76//! `Basics.Position`, whose one constructor is exposed to no module. The definition
77//! names it by [`scalars::POSITION`], the way the compiler names a scalar, and never
78//! through scope.
79//! - **Spans.** A class's bindings were written in the class's file and the instance is in
80//! another's, so a span carried over would point at unrelated text. Every node of a
81//! generated definition, the placed bodies included, is given the span of the word
82//! `derived`, which is where an error in one is blamed.
83//!
84//! What a placed body may name is what its home module exposes, and a body that names a
85//! value its home module does not expose is not checked where it is placed: the typer
86//! reads only what the module it checks imports, so such a binding is left unchecked, as
87//! one naming any other name the typer cannot read is.
88//!
89//! # What the code costs
90//!
91//! The rest of the walk is copied at every place `combine`'s body names its second
92//! parameter. A body that names it `k` times, in a constructor of `n` arguments, makes
93//! `k^n` copies of the rest, so the size of a derived member is exponential in a
94//! constructor's arity whenever `k` is more than one, and nothing here bounds it. At run
95//! time each path evaluates the rest at most once, which is what the rule asks; it is the
96//! generated code that is large. `LANG-88` tracks it.
97
98use super::classes::mentions;
99use super::environment::{Environment, RootEnvironment};
100use super::{
101 binding_value, CaseBranch, ClassSignature, Constraint, DeclarationSite, Derivation,
102 DerivationBindings, DerivationRole, Error, Expression, ExpressionKind, Field, HeadName,
103 InstanceHead, Member, Pattern, PatternField, PatternKind, Type, TypeConstructor, UnionType,
104 Value,
105};
106use crate::name::{Name, QualName};
107use crate::scalars;
108use std::cell::Cell;
109use std::collections::HashMap;
110use std::convert::TryFrom;
111use zelkova_syntax::parser;
112use zelkova_syntax::position::NodeSpan;
113use zelkova_syntax::tuple::Tuple;
114
115// ── The class side ───────────────────────────────────────────────────────────
116
117/// What is wrong with the signature of a member a derivation was written for — see
118/// [`Error::DerivationSignature`].
119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
120pub enum DerivationSignatureProblem {
121 /// No parameter of the member holds the class variable: `bottom : a` and
122 /// `allValues : List a`. A derivation walks values of the type, and there is none to
123 /// walk, so it would have to build one from a description of the type's constructors.
124 NoClassValue,
125 /// The class variable is in the answer: `add : a -> a -> a`. The walk would be asked
126 /// for another value of the type it is walking.
127 ResultMentionsClassVariable,
128 /// Some other shape: a derivation is for `a -> a -> R` and `a -> R`.
129 Shape,
130}
131
132/// Which walk a member's signature gives its derivation, and the type it answers with.
133enum Walk {
134 /// `a -> a -> R`.
135 Pair(Type),
136 /// `a -> R`.
137 Single(Type),
138}
139
140/// The walk the signature `tpe` of a member of a class over `variable` admits, or why it
141/// admits none.
142fn walk_of(tpe: &Type, variable: &Name) -> Result<Walk, DerivationSignatureProblem> {
143 let is_class_variable = |tpe: &Type| matches!(tpe, Type::Variable(name) if name == variable);
144
145 if let Type::Arrow(first, rest) = tpe {
146 if is_class_variable(first) {
147 if let Type::Arrow(second, result) = rest.as_ref() {
148 if is_class_variable(second) && !mentions(result, variable) {
149 return Ok(Walk::Pair(result.as_ref().clone()));
150 }
151 }
152 if !mentions(rest, variable) {
153 return Ok(Walk::Single(rest.as_ref().clone()));
154 }
155 }
156 }
157
158 let mut parameters = Vec::new();
159 let mut result = tpe;
160 while let Type::Arrow(parameter, rest) = result {
161 parameters.push(parameter.as_ref());
162 result = rest;
163 }
164
165 Err(
166 if !parameters
167 .iter()
168 .any(|parameter| mentions(parameter, variable))
169 {
170 DerivationSignatureProblem::NoClassValue
171 } else if mentions(result, variable) {
172 DerivationSignatureProblem::ResultMentionsClassVariable
173 } else {
174 DerivationSignatureProblem::Shape
175 },
176 )
177}
178
179/// The names a derivation's bindings are written under for `walk`, in the order the
180/// chapter lists them.
181fn required(walk: &Walk) -> &'static [DerivationRole] {
182 match walk {
183 Walk::Pair(_) => &[
184 DerivationRole::Matched,
185 DerivationRole::Differed,
186 DerivationRole::Combine,
187 ],
188 Walk::Single(_) => &[DerivationRole::AtConstructor, DerivationRole::Combine],
189 }
190}
191
192/// The derivations of `class`, each held to the rules a derivation follows, and every error
193/// of the ones that do not pass.
194///
195/// `signature` is `class` as `class_signature` built it, so the members are known. Every
196/// binding of every derivation is canonicalized, a derivation that fails its checks
197/// included, so that a name one cannot resolve is reported whatever else is wrong with it;
198/// every such name is pushed onto `unresolved`.
199///
200/// A derivation that fails is left out of what comes back, and its member is one the class
201/// does not derive. A class that derives some of its members and not all is its own
202/// error, naming the ones left out ([`Error::DerivationIncomplete`]); a member whose
203/// derivation is there and failed is not named in it, since that derivation has its own.
204pub(super) fn class_derivations(
205 env: &RootEnvironment,
206 class: &parser::ClassDecl,
207 class_name: &Name,
208 signature: &ClassSignature,
209 unresolved: &mut Vec<Error>,
210) -> (Vec<Derivation>, Vec<Error>) {
211 let mut errors = Vec::new();
212 let mut derivations: Vec<Derivation> = Vec::new();
213 // The span of the first derivation written for each member, valid or not.
214 let mut first: HashMap<&Name, NodeSpan> = HashMap::new();
215
216 for derivation in class.members.iter().filter_map(|member| match member {
217 parser::ClassMember::Derivation(derivation) => Some(derivation),
218 parser::ClassMember::Signature(_) => None,
219 }) {
220 // Every binding is read, so that what it names is resolved and reported. A binding
221 // that did not canonicalize is a binding that was written: its name is kept, so
222 // the derivation is not also reported as missing it.
223 let mut bindings: Vec<(&parser::FunBinding, Option<Value>)> = Vec::new();
224 for binding in &derivation.bindings {
225 match binding_value(env, binding, unresolved) {
226 Ok(value) => bindings.push((binding, Some(value))),
227 Err(error) => {
228 errors.push(error);
229 bindings.push((binding, None));
230 }
231 }
232 }
233
234 let Some(member) = signature
235 .members
236 .iter()
237 .find(|member| member.name == derivation.member)
238 else {
239 errors.push(Error::DerivationForNonMember(
240 derivation.member.clone(),
241 class_name.clone(),
242 derivation.span,
243 ));
244 continue;
245 };
246
247 if let Some(earlier) = first.get(&derivation.member) {
248 errors.push(Error::DerivationRepeated(
249 derivation.member.clone(),
250 derivation.span,
251 *earlier,
252 ));
253 continue;
254 }
255 first.insert(&derivation.member, derivation.span);
256
257 let walk = match walk_of(&member.tpe, &signature.variable) {
258 Ok(walk) => walk,
259 Err(problem) => {
260 errors.push(Error::DerivationSignature(
261 derivation.member.clone(),
262 problem,
263 derivation.span,
264 member.span,
265 ));
266 continue;
267 }
268 };
269
270 let before = errors.len();
271 let mut found: HashMap<DerivationRole, Value> = HashMap::new();
272 let mut written: HashMap<DerivationRole, NodeSpan> = HashMap::new();
273 let mut failed: Vec<DerivationRole> = Vec::new();
274
275 for (binding, value) in bindings {
276 let Some(role) = required(&walk)
277 .iter()
278 .find(|role| role.name() == binding.name.as_str())
279 else {
280 errors.push(Error::DerivationBindingUnexpected(
281 binding.name.clone(),
282 derivation.member.clone(),
283 required(&walk)
284 .iter()
285 .map(|role| Name::new(role.name()))
286 .collect(),
287 binding.span,
288 ));
289 continue;
290 };
291
292 if let Some(earlier) = written.get(role) {
293 errors.push(Error::DerivationBindingRepeated(
294 binding.name.clone(),
295 derivation.member.clone(),
296 binding.span,
297 *earlier,
298 ));
299 continue;
300 }
301 written.insert(*role, binding.span);
302
303 match value {
304 Some(value) => {
305 if value.arity() > role.parameters() {
306 errors.push(Error::DerivationBindingTakesTooMany(
307 binding.name.clone(),
308 derivation.member.clone(),
309 role.parameters(),
310 binding.span,
311 ));
312 } else {
313 found.insert(*role, value);
314 }
315 }
316 None => failed.push(*role),
317 }
318 }
319
320 for role in required(&walk) {
321 if !written.contains_key(role) {
322 errors.push(Error::DerivationBindingMissing(
323 Name::new(role.name()),
324 derivation.member.clone(),
325 derivation.span,
326 ));
327 }
328 }
329
330 if errors.len() > before || !failed.is_empty() {
331 continue;
332 }
333
334 let bindings = match walk {
335 Walk::Pair(_) => match (
336 found.remove(&DerivationRole::Matched),
337 found.remove(&DerivationRole::Differed),
338 found.remove(&DerivationRole::Combine),
339 ) {
340 (Some(matched), Some(differed), Some(combine)) => DerivationBindings::Pair {
341 matched: Box::new(matched),
342 differed: Box::new(differed),
343 combine: Box::new(combine),
344 },
345 _ => continue,
346 },
347 Walk::Single(_) => match (
348 found.remove(&DerivationRole::AtConstructor),
349 found.remove(&DerivationRole::Combine),
350 ) {
351 (Some(at_constructor), Some(combine)) => DerivationBindings::Single {
352 at_constructor: Box::new(at_constructor),
353 combine: Box::new(combine),
354 },
355 _ => continue,
356 },
357 };
358 let result = match walk {
359 Walk::Pair(result) | Walk::Single(result) => result,
360 };
361
362 derivations.push(Derivation {
363 member: derivation.member.clone(),
364 result,
365 bindings,
366 span: derivation.span,
367 });
368 }
369
370 // A class that derives some of its members and not the rest could only be half derived
371 // and half written.
372 let covered = signature
373 .members
374 .iter()
375 .filter(|member| first.contains_key(&member.name))
376 .count();
377 if covered > 0 && covered < signature.members.len() {
378 let left_out: Vec<Name> = signature
379 .members
380 .iter()
381 .filter(|member| !first.contains_key(&member.name))
382 .map(|member| member.name.clone())
383 .collect();
384 errors.push(Error::DerivationIncomplete(
385 class_name.clone(),
386 left_out,
387 class.span,
388 ));
389 }
390
391 (derivations, errors)
392}
393
394// ── The instance side ────────────────────────────────────────────────────────
395
396/// What is wrong with the type a `derived` instance is for, that it has no shape to walk —
397/// see [`Error::DerivedInstanceNoShape`].
398#[derive(Debug, Clone, PartialEq)]
399pub enum DerivedShapeProblem {
400 /// A [scalar type](../../docs/spec/types.md#scalar-types) has no shape for a walk to
401 /// read, so its instances are written: the type.
402 Scalar(Name),
403 /// A type whose constructors are not in scope — one imported without them: the type.
404 NoConstructors(Name),
405 /// `()` for a class with a member whose derivation walks one value, which has no
406 /// element to begin at: the class.
407 UnitHasNoElement(Name),
408}
409
410/// The part of a type a walk found an argument in: where a requirement of a derived
411/// instance came from.
412#[derive(Debug, Clone, PartialEq)]
413pub enum DerivedPart {
414 /// An argument of a variant of a union.
415 Variant(Name),
416 /// An element of a tuple, counting from one.
417 Element(usize),
418}
419
420/// An argument of a derived instance's type with no instance of the derived class — see
421/// [`Error::DerivedInstanceRequires`].
422#[derive(Debug, Clone, PartialEq)]
423pub struct DerivedRequirement {
424 /// The class being derived.
425 pub class: Name,
426 /// What the argument was found in.
427 pub part: DerivedPart,
428 /// The type of the argument, as written in the type's declaration.
429 pub argument: String,
430 /// The type that has no instance: the argument itself, or what an instance an
431 /// application of it needs asks for.
432 pub missing: String,
433 /// Whether `missing` is a function type, which no instance can be declared for.
434 pub function: bool,
435 /// Where the type being derived for was declared, when that is in this module.
436 pub declared: DeclarationSite,
437}
438
439/// A constraint a `derived` instance needs and the context written on it does not provide —
440/// see [`Error::DerivedInstanceContextTooNarrow`].
441#[derive(Debug, Clone, PartialEq)]
442pub struct DerivedContextGap {
443 /// The class being derived.
444 pub class: Name,
445 /// The constraint the context does not provide, as a context writes it: `Eq a`.
446 pub missing: String,
447 /// The first argument that needs it was found in this.
448 pub part: DerivedPart,
449 /// The type of that argument, as written in the type's declaration.
450 pub argument: String,
451}
452
453/// A `derived` instance of the module under check, as [`derive_all`] reads it.
454pub(super) struct Candidate<'a> {
455 /// The class being derived.
456 pub class: &'a QualName,
457 pub head: &'a InstanceHead,
458 /// The context written on the instance and where, when one is written and resolved.
459 pub context: Option<(&'a [Constraint], NodeSpan)>,
460 /// Where the word `derived` was written.
461 pub span: NodeSpan,
462}
463
464/// What a derived instance comes to: its context and its members.
465pub(super) struct Derived {
466 /// The context the instance wrote, when it wrote one. Otherwise the constraints the
467 /// instance needs of its head's variables, in the order the type's arguments are
468 /// written in, each once.
469 pub context: Vec<Constraint>,
470 /// One binding per member of the class, in the order the class declares them.
471 pub bindings: Vec<Value>,
472}
473
474/// What the walk of one derived instance reads: the alternatives a value may be and, for
475/// each, the types of its arguments.
476enum Shape<'a> {
477 /// A declared union and where it was declared, when that is the module under check.
478 Union(&'a UnionType, DeclarationSite),
479 /// A tuple of two or three elements.
480 Tuple(usize),
481 /// `()`.
482 Unit,
483}
484
485/// One way a value of a type may be built: a constructor of a union, or the one way a
486/// tuple or `()` is.
487struct Alternative<'a> {
488 /// The constructor, for a union.
489 constructor: Option<&'a TypeConstructor>,
490 /// How many arguments it has.
491 arity: usize,
492}
493
494impl Shape<'_> {
495 fn alternatives(&self) -> Vec<Alternative<'_>> {
496 match self {
497 Shape::Union(union, _) => union
498 .variants
499 .iter()
500 .map(|constructor| Alternative {
501 constructor: Some(constructor),
502 arity: constructor.type_parameters.len(),
503 })
504 .collect(),
505 Shape::Tuple(arity) => vec![Alternative {
506 constructor: None,
507 arity: *arity,
508 }],
509 Shape::Unit => vec![Alternative {
510 constructor: None,
511 arity: 0,
512 }],
513 }
514 }
515}
516
517/// An argument a derived instance's type holds, and what it asks.
518struct Requirement {
519 part: DerivedPart,
520 /// The argument's type, over the head's variables.
521 tpe: Type,
522}
523
524/// One derived instance, read for its shape and what that shape asks.
525struct Plan<'a> {
526 candidate: &'a Candidate<'a>,
527 shape: Shape<'a>,
528 requirements: Vec<Requirement>,
529}
530
531/// What an instance in scope needs of its head's variables.
532struct Known {
533 /// The head's variables, in the order the head writes them.
534 variables: Vec<Name>,
535 /// The constraints on them, each a class and a variable of the head.
536 context: Vec<(QualName, Name)>,
537}
538
539type Table = HashMap<(QualName, HeadName), Known>;
540
541/// An instance of the module under check as it is written: its class and head, and the
542/// context it writes of its own. A derived instance that writes none has an empty one here,
543/// which is where its inferred context starts.
544pub(super) struct WrittenInstance {
545 pub class: QualName,
546 pub head: InstanceHead,
547 pub context: Vec<(QualName, Name)>,
548}
549
550/// Derive every instance of `candidates`: the context each needs, and the members each is
551/// made of, or why it cannot be.
552///
553/// The answer is one entry per candidate, in order. `written` is every instance of the module
554/// with the context it writes, which an argument's type may need; the instances imported are
555/// read from `env`. An instance that has an error in its own right — `signature` has no derivation
556/// for it, the type has no shape — is one entry's errors, and is still counted as in scope
557/// for the others, so that one failure is not restated by every type that holds it.
558///
559/// `signature` is the class each candidate derives, as the module that declares it
560/// published it, or `None` when that declaration did not canonicalize and the error behind
561/// it has been reported.
562pub(super) fn derive_all<'a>(
563 env: &'a RootEnvironment,
564 candidates: &'a [Candidate<'a>],
565 signatures: &[Option<&ClassSignature>],
566 written: &[WrittenInstance],
567) -> Vec<Result<Derived, Vec<Error>>> {
568 let mut table: Table = HashMap::new();
569 for published in env.imported_instances() {
570 let signature = &published.signature;
571 table.insert(
572 (signature.class.clone(), signature.head.name()),
573 Known {
574 variables: signature.head.variables().into_iter().cloned().collect(),
575 context: signature
576 .context
577 .iter()
578 .map(|constraint| (constraint.class.clone(), constraint.variable.clone()))
579 .collect(),
580 },
581 );
582 }
583 for instance in written {
584 table.insert(
585 (instance.class.clone(), instance.head.name()),
586 Known {
587 variables: instance.head.variables().into_iter().cloned().collect(),
588 context: instance.context.clone(),
589 },
590 );
591 }
592 // Every candidate is in scope for the others, needing what it writes of its own and
593 // nothing more yet.
594 for candidate in candidates {
595 table
596 .entry((candidate.class.clone(), candidate.head.name()))
597 .or_insert_with(|| Known {
598 variables: candidate.head.variables().into_iter().cloned().collect(),
599 context: Vec::new(),
600 });
601 }
602
603 let plans: Vec<Result<Plan, Vec<Error>>> = candidates
604 .iter()
605 .zip(signatures)
606 .map(|(candidate, signature)| plan(env, candidate, *signature))
607 .collect();
608
609 // The fixed point. A context only grows, from nothing, by what an instance asks given
610 // every context as it stands. A written context is the whole of its instance's and does
611 // not grow.
612 loop {
613 let mut grown = false;
614
615 for plan in plans.iter().filter_map(|plan| plan.as_ref().ok()) {
616 if plan.candidate.context.is_some() {
617 continue;
618 }
619 let mut needed = Vec::new();
620 for requirement in &plan.requirements {
621 // A failure is the final pass's to report; here it asks nothing more.
622 let _ = reduce(&table, plan.candidate.class, &requirement.tpe, &mut needed);
623 }
624
625 let key = (plan.candidate.class.clone(), plan.candidate.head.name());
626 if let Some(known) = table.get_mut(&key) {
627 for constraint in needed {
628 if !known.context.contains(&constraint) {
629 known.context.push(constraint);
630 grown = true;
631 }
632 }
633 }
634 }
635
636 if !grown {
637 break;
638 }
639 }
640
641 plans
642 .into_iter()
643 .zip(signatures)
644 .map(|(plan, signature)| {
645 let plan = plan?;
646 let candidate = plan.candidate;
647
648 // What is read now is the context the fixed point reached, read from scratch.
649 let mut context: Vec<(QualName, Name)> = Vec::new();
650 let mut errors = Vec::new();
651 for requirement in &plan.requirements {
652 let read = context.len();
653 let reduced = reduce(&table, candidate.class, &requirement.tpe, &mut context);
654
655 // `context` holds each constraint once, so what this argument added is what
656 // no earlier argument asked, and a gap is reported at the first that needs it.
657 if let Some((written, written_span)) = candidate.context {
658 for (class, variable) in &context[read..] {
659 if !provides(env, written, class, variable) {
660 errors.push(Error::DerivedInstanceContextTooNarrow(
661 Box::new(DerivedContextGap {
662 class: candidate.class.unqualified_name(),
663 missing: format!("{} {}", class.unqualified_name(), variable),
664 part: requirement.part.clone(),
665 argument: type_text(&requirement.tpe),
666 }),
667 written_span,
668 candidate.span,
669 ));
670 }
671 }
672 }
673
674 if let Err(missing) = reduced {
675 errors.push(Error::DerivedInstanceRequires(
676 Box::new(DerivedRequirement {
677 class: candidate.class.unqualified_name(),
678 part: requirement.part.clone(),
679 argument: type_text(&requirement.tpe),
680 function: matches!(missing, Type::Arrow(..)),
681 missing: type_text(&missing),
682 declared: match &plan.shape {
683 Shape::Union(_, declared) => *declared,
684 Shape::Tuple(_) | Shape::Unit => DeclarationSite::Unknown,
685 },
686 }),
687 candidate.span,
688 ));
689 }
690 }
691 if !errors.is_empty() {
692 return Err(errors);
693 }
694
695 // A class that is not derivable stopped the plan, so there is a signature.
696 let Some(signature) = signature else {
697 return Err(Vec::new());
698 };
699 let bindings = Generated::new(env, candidate, &plan.shape, signature).members();
700
701 Ok(Derived {
702 context: match candidate.context {
703 Some((written, _)) => written.to_vec(),
704 None => context
705 .into_iter()
706 .map(|(class, variable)| Constraint {
707 class,
708 variable,
709 span: candidate.span,
710 })
711 .collect(),
712 },
713 bindings,
714 })
715 })
716 .collect()
717}
718
719/// Whether `context` provides `class` of `variable`: it writes that constraint, or one on
720/// the same variable for a class `class` is a superclass of, however many classes away.
721///
722/// A class whose declaration is not in scope has no superclasses to follow here.
723fn provides(
724 env: &RootEnvironment,
725 context: &[Constraint],
726 class: &QualName,
727 variable: &Name,
728) -> bool {
729 let mut pending: Vec<&QualName> = context
730 .iter()
731 .filter(|constraint| &constraint.variable == variable)
732 .map(|constraint| &constraint.class)
733 .collect();
734 let mut seen: Vec<&QualName> = Vec::new();
735
736 while let Some(candidate) = pending.pop() {
737 if candidate == class {
738 return true;
739 }
740 if seen.contains(&candidate) {
741 continue;
742 }
743 seen.push(candidate);
744 if let Some(signature) = env.class_signature(candidate) {
745 pending.extend(
746 signature
747 .superclasses
748 .iter()
749 .map(|superclass| &superclass.class),
750 );
751 }
752 }
753
754 false
755}
756
757/// Read one derived instance for its shape and what that shape asks, or say why it cannot
758/// be derived.
759///
760/// An empty list of errors is a failure already reported: the class's own declaration did
761/// not canonicalize, or the head's type did not.
762fn plan<'a>(
763 env: &'a RootEnvironment,
764 candidate: &'a Candidate<'a>,
765 signature: Option<&ClassSignature>,
766) -> Result<Plan<'a>, Vec<Error>> {
767 let Some(signature) = signature else {
768 return Err(Vec::new());
769 };
770
771 let class = candidate.class.unqualified_name();
772 if !signature.derivable() {
773 // A class whose derivations were rejected has said so where it is declared, and an
774 // instance asking to be derived does not say it again.
775 return Err(if signature.derivations_rejected {
776 Vec::new()
777 } else {
778 vec![Error::DerivedInstanceNotDerivable(class, candidate.span)]
779 });
780 }
781
782 let (shape, requirements) = match candidate.head {
783 InstanceHead::Type(name, variables) => {
784 if scalars::scalar_of(name).is_some() {
785 return Err(vec![Error::DerivedInstanceNoShape(
786 DerivedShapeProblem::Scalar(name.unqualified_name()),
787 candidate.span,
788 )]);
789 }
790
791 let Some(union) = env.find_union(name) else {
792 return Err(Vec::new());
793 };
794 if union.variants.is_empty() {
795 return Err(vec![Error::DerivedInstanceNoShape(
796 DerivedShapeProblem::NoConstructors(name.unqualified_name()),
797 candidate.span,
798 )]);
799 }
800
801 // The union's own variables stand for the head's, whatever it names them.
802 let renamed: HashMap<&Name, &Name> = union.variables.iter().zip(variables).collect();
803 let requirements = union
804 .variants
805 .iter()
806 .flat_map(|constructor| {
807 let renamed = &renamed;
808 constructor
809 .type_parameters
810 .iter()
811 .map(move |tpe| Requirement {
812 part: DerivedPart::Variant(constructor.name.clone()),
813 tpe: rename(tpe, renamed),
814 })
815 })
816 .collect();
817
818 let declared = if super::classes::declaring_module(name) == *env.module_name() {
819 DeclarationSite::InThisModule(union.span)
820 } else {
821 DeclarationSite::Unknown
822 };
823 (Shape::Union(union, declared), requirements)
824 }
825 InstanceHead::Tuple(tuple) => {
826 let requirements = tuple
827 .iter()
828 .enumerate()
829 .map(|(index, variable)| Requirement {
830 part: DerivedPart::Element(index + 1),
831 tpe: Type::Variable(variable.clone()),
832 })
833 .collect();
834 (Shape::Tuple(tuple.iter().count()), requirements)
835 }
836 InstanceHead::Unit => {
837 if signature.walks_one_value() {
838 return Err(vec![Error::DerivedInstanceNoShape(
839 DerivedShapeProblem::UnitHasNoElement(class),
840 candidate.span,
841 )]);
842 }
843 (Shape::Unit, Vec::new())
844 }
845 };
846
847 Ok(Plan {
848 candidate,
849 shape,
850 requirements,
851 })
852}
853
854/// `tpe` with each variable of `renamed` written as the variable it maps to.
855fn rename(tpe: &Type, renamed: &HashMap<&Name, &Name>) -> Type {
856 match tpe {
857 Type::Variable(name) => Type::Variable(
858 renamed
859 .get(name)
860 .map(|name| (*name).clone())
861 .unwrap_or_else(|| name.clone()),
862 ),
863 Type::Type(name, args) => Type::Type(
864 name.clone(),
865 args.iter().map(|arg| rename(arg, renamed)).collect(),
866 ),
867 Type::Record(fields) => Type::Record(
868 fields
869 .iter()
870 .map(|(label, tpe)| (label.clone(), rename(tpe, renamed)))
871 .collect(),
872 ),
873 Type::Arrow(parameter, result) => Type::Arrow(
874 Box::new(rename(parameter, renamed)),
875 Box::new(rename(result, renamed)),
876 ),
877 Type::Tuple(tuple) => Type::Tuple(tuple.map(|element| rename(element, renamed))),
878 Type::Unit => Type::Unit,
879 }
880}
881
882/// Reduce `class` required of `tpe` to what it asks of the variables of the instance being
883/// derived, added to `needed` as a class and a variable, each once. `Err` is the type that
884/// has no instance.
885///
886/// A variable is a constraint. A declared type, a tuple and `()` need the instance of
887/// their head, and what that instance's context asks of its variables is asked of the type's
888/// arguments in turn, which are smaller than the type. A function type has no instance, and
889/// a record is [accepted without being checked](../../../docs/tickets/lang-85.md), as the
890/// solver accepts an obligation at one.
891fn reduce(
892 table: &Table,
893 class: &QualName,
894 tpe: &Type,
895 needed: &mut Vec<(QualName, Name)>,
896) -> Result<(), Type> {
897 let (head, arguments): (HeadName, Vec<&Type>) = match tpe {
898 Type::Variable(variable) => {
899 let constraint = (class.clone(), variable.clone());
900 if !needed.contains(&constraint) {
901 needed.push(constraint);
902 }
903 return Ok(());
904 }
905 Type::Arrow(..) => return Err(tpe.clone()),
906 Type::Record(_) => return Ok(()),
907 Type::Type(name, arguments) => (HeadName::Type(name.clone()), arguments.iter().collect()),
908 Type::Tuple(Tuple::Two(first, second)) => (HeadName::TwoTuple, vec![first, second]),
909 Type::Tuple(Tuple::Three(first, second, third)) => {
910 (HeadName::ThreeTuple, vec![first, second, third])
911 }
912 Type::Unit => (HeadName::Unit, Vec::new()),
913 };
914
915 let Some(known) = table.get(&(class.clone(), head)) else {
916 return Err(tpe.clone());
917 };
918 if known.variables.len() != arguments.len() {
919 return Err(tpe.clone());
920 }
921
922 for (class, variable) in &known.context {
923 let Some(position) = known.variables.iter().position(|bound| bound == variable) else {
924 continue;
925 };
926 reduce(table, class, arguments[position], needed)?;
927 }
928
929 Ok(())
930}
931
932/// `tpe` as the source writes it, for a message.
933fn type_text(tpe: &Type) -> String {
934 fn go(tpe: &Type, nested: bool) -> String {
935 match tpe {
936 Type::Variable(name) => name.to_string(),
937 Type::Type(name, args) if args.is_empty() => name.unqualified_name().to_string(),
938 Type::Type(name, args) => {
939 let text = std::iter::once(name.unqualified_name().to_string())
940 .chain(args.iter().map(|arg| go(arg, true)))
941 .collect::<Vec<_>>()
942 .join(" ");
943 if nested {
944 format!("({})", text)
945 } else {
946 text
947 }
948 }
949 Type::Arrow(parameter, result) => {
950 let text = format!("{} -> {}", go(parameter, true), go(result, false));
951 if nested {
952 format!("({})", text)
953 } else {
954 text
955 }
956 }
957 Type::Tuple(tuple) => format!(
958 "({})",
959 tuple
960 .iter()
961 .map(|element| go(element, false))
962 .collect::<Vec<_>>()
963 .join(", ")
964 ),
965 Type::Unit => "()".to_owned(),
966 Type::Record(fields) => format!(
967 "{{ {} }}",
968 fields
969 .iter()
970 .map(|(label, tpe)| format!("{} : {}", label, go(tpe, false)))
971 .collect::<Vec<_>>()
972 .join(", ")
973 ),
974 }
975 }
976
977 go(tpe, false)
978}
979
980// ── Generating the members ───────────────────────────────────────────────────
981
982/// The names a generated definition gives its parameters and the arguments it takes apart.
983/// Each starts with a `$`, which no source file can write and no class author's binding can
984/// therefore bind.
985const LEFT: &str = "$left";
986const RIGHT: &str = "$right";
987const VALUE: &str = "$value";
988
989fn left_argument(index: usize) -> Name {
990 Name::new(format!("$a{}", index + 1))
991}
992
993fn right_argument(index: usize) -> Name {
994 Name::new(format!("$b{}", index + 1))
995}
996
997/// The members of one derived instance, written out as canonical code.
998struct Generated<'a> {
999 /// Where the word `derived` was written: the span of every node generated.
1000 span: NodeSpan,
1001 shape: &'a Shape<'a>,
1002 class: &'a QualName,
1003 signature: &'a ClassSignature,
1004 /// Whether the class is declared in the module the instance is in, which decides how a
1005 /// member is named.
1006 class_here: bool,
1007 /// How many fresh names the instance's members have used: see [`Generated::fresh`].
1008 serial: Cell<usize>,
1009}
1010
1011/// What a placed body's names stand for: the fresh name each local the body bound has, and
1012/// the one local that is replaced by an expression.
1013#[derive(Clone, Default)]
1014struct Scope<'a> {
1015 renames: HashMap<Name, Name>,
1016 /// The second parameter of `combine`, and the rest of the walk it stands for.
1017 replaced: Option<(&'a Name, &'a Expression)>,
1018}
1019
1020impl<'a> Scope<'a> {
1021 /// `name`, bound again from here on, to `fresh`.
1022 fn rename(&mut self, name: &Name, fresh: Name) {
1023 self.renames.insert(name.clone(), fresh);
1024 // What a pattern binds is what the name means now, and not what it replaced.
1025 if matches!(self.replaced, Some((replaced, _)) if replaced == name) {
1026 self.replaced = None;
1027 }
1028 }
1029
1030 /// The fresh name `name` is bound to, or `name` where nothing here bound it.
1031 fn renamed(&self, name: &Name) -> Name {
1032 self.renames
1033 .get(name)
1034 .cloned()
1035 .unwrap_or_else(|| name.clone())
1036 }
1037}
1038
1039impl<'a> Generated<'a> {
1040 fn new(
1041 env: &RootEnvironment,
1042 candidate: &'a Candidate<'a>,
1043 shape: &'a Shape<'a>,
1044 signature: &'a ClassSignature,
1045 ) -> Generated<'a> {
1046 Generated {
1047 span: candidate.span,
1048 shape,
1049 class: candidate.class,
1050 signature,
1051 class_here: super::classes::declaring_module(candidate.class) == *env.module_name(),
1052 serial: Cell::new(0),
1053 }
1054 }
1055
1056 /// One definition per member of the class, in the order it declares them.
1057 fn members(&self) -> Vec<Value> {
1058 self.signature
1059 .members
1060 .iter()
1061 .filter_map(|member| {
1062 let derivation = self.signature.derivation(&member.name)?;
1063 Some(self.member(member, derivation))
1064 })
1065 .collect()
1066 }
1067
1068 fn member(&self, member: &Member, derivation: &Derivation) -> Value {
1069 let (parameters, body) = match &derivation.bindings {
1070 DerivationBindings::Pair {
1071 matched,
1072 differed,
1073 combine,
1074 } => (
1075 vec![LEFT, RIGHT],
1076 self.walk_pair(member, matched, differed, combine),
1077 ),
1078 DerivationBindings::Single {
1079 at_constructor,
1080 combine,
1081 } => (
1082 vec![VALUE],
1083 self.walk_single(member, at_constructor, combine),
1084 ),
1085 };
1086
1087 Value::Value {
1088 name: member.name.clone(),
1089 patterns: parameters
1090 .into_iter()
1091 .map(|name| self.pattern(PatternKind::Variable(Name::new(name))))
1092 .collect(),
1093 body,
1094 span: self.span,
1095 }
1096 }
1097
1098 /// The walk over two values: take the first apart, take the second apart, and fold the
1099 /// arguments of the pair when the two are of one constructor.
1100 fn walk_pair(
1101 &self,
1102 member: &Member,
1103 matched: &Value,
1104 differed: &Value,
1105 combine: &Value,
1106 ) -> Expression {
1107 let alternatives = self.shape.alternatives();
1108
1109 let branches = alternatives
1110 .iter()
1111 .enumerate()
1112 .map(|(index, alternative)| {
1113 let left_names: Vec<Name> = (0..alternative.arity).map(left_argument).collect();
1114 let right_names: Vec<Name> = (0..alternative.arity).map(right_argument).collect();
1115
1116 // The answer for each pair of arguments, folded right-nested onto what the
1117 // walk ends at when nothing told the two values apart.
1118 let mut rest = self.place(matched, Vec::new());
1119 for (left, right) in left_names.iter().zip(&right_names).rev() {
1120 let answer = self.apply(
1121 self.apply(self.member_reference(member), self.local(left)),
1122 self.local(right),
1123 );
1124 rest = self.place_combine(combine, answer, rest);
1125 }
1126
1127 // The second value is the same constructor, or it is not and `differed`
1128 // answers for the pair, handed where each was declared.
1129 let mut same_or_not = vec![(
1130 self.alternative_pattern(alternative, Some(&right_names)),
1131 rest,
1132 )];
1133 for (other_index, other) in alternatives.iter().enumerate() {
1134 if other_index != index {
1135 same_or_not.push((
1136 self.alternative_pattern(other, None),
1137 self.place(
1138 differed,
1139 vec![self.position(index), self.position(other_index)],
1140 ),
1141 ));
1142 }
1143 }
1144
1145 (
1146 self.alternative_pattern(alternative, Some(&left_names)),
1147 self.case(self.local_str(RIGHT), same_or_not),
1148 )
1149 })
1150 .collect();
1151
1152 self.case(self.local_str(LEFT), branches)
1153 }
1154
1155 /// The walk over one value: take it apart, and fold the answer for its constructor with
1156 /// the answer for each argument.
1157 fn walk_single(&self, member: &Member, at_constructor: &Value, combine: &Value) -> Expression {
1158 let alternatives = self.shape.alternatives();
1159
1160 let branches = alternatives
1161 .iter()
1162 .enumerate()
1163 .map(|(index, alternative)| {
1164 let names: Vec<Name> = (0..alternative.arity).map(left_argument).collect();
1165
1166 // `combine p (combine a1 (… an))`: the constructor's answer when it has
1167 // one, and each argument's, the last of them standing for the rest of the
1168 // walk where the one before it asks for it.
1169 let mut answers: Vec<Expression> = Vec::new();
1170 if alternative.constructor.is_some() {
1171 answers.push(self.place(at_constructor, vec![self.position(index)]));
1172 }
1173 for name in &names {
1174 answers.push(self.apply(self.member_reference(member), self.local(name)));
1175 }
1176
1177 let body = match answers.pop() {
1178 Some(last) => answers.into_iter().rev().fold(last, |rest, answer| {
1179 self.place_combine(combine, answer, rest)
1180 }),
1181 // A tuple or `()` with no element to begin at has no answer; a class
1182 // that walks one value is not derived for `()`, and a tuple has
1183 // elements, so this is not reached.
1184 None => self.expression(ExpressionKind::Unit),
1185 };
1186
1187 (self.alternative_pattern(alternative, Some(&names)), body)
1188 })
1189 .collect();
1190
1191 self.case(self.local_str(VALUE), branches)
1192 }
1193
1194 /// The binding of the derivation placed for `arguments`: each parameter bound, by a
1195 /// `case` of one branch, to the argument it receives, and any argument beyond the
1196 /// parameters the binding was written with applied to the body.
1197 fn place(&self, binding: &Value, arguments: Vec<Expression>) -> Expression {
1198 let (patterns, body) = value_parts(binding);
1199
1200 let mut scope = Scope::default();
1201 let mut arguments = arguments.into_iter();
1202 let mut bound: Vec<(Pattern, Expression)> = Vec::new();
1203 for pattern in patterns {
1204 let Some(argument) = arguments.next() else {
1205 break;
1206 };
1207 bound.push((self.bind_pattern(pattern, &mut scope), argument));
1208 }
1209
1210 let applied = arguments.fold(self.rewrite(body, &scope), |function, argument| {
1211 self.apply(function, argument)
1212 });
1213
1214 self.bind(bound, applied)
1215 }
1216
1217 /// `combine` placed for the answer to one part and the rest of the walk.
1218 ///
1219 /// The first parameter is bound once, to the answer. The second is replaced by the
1220 /// rest, wherever the body names it and nowhere else, so that the rest is evaluated
1221 /// where the body reaches it. A binding written with fewer parameters is applied to
1222 /// what it did not bind, which makes the rest an argument as a call would.
1223 fn place_combine(&self, combine: &Value, answer: Expression, rest: Expression) -> Expression {
1224 let (patterns, body) = value_parts(combine);
1225 let mut scope = Scope::default();
1226
1227 match patterns.as_slice() {
1228 [] => self.apply(self.apply(self.rewrite(body, &scope), answer), rest),
1229 [first] => {
1230 let first = self.bind_pattern(first, &mut scope);
1231 let applied = self.apply(self.rewrite(body, &scope), rest);
1232 self.bind(vec![(first, answer)], applied)
1233 }
1234 [first, second, ..] => {
1235 let first = self.bind_pattern(first, &mut scope);
1236 match &second.kind {
1237 PatternKind::Variable(name) => {
1238 scope.replaced = Some((name, &rest));
1239 let placed = self.rewrite(body, &scope);
1240 self.bind(vec![(first, answer)], placed)
1241 }
1242 // The rest is never named, so it is never evaluated.
1243 PatternKind::Anything => {
1244 let placed = self.rewrite(body, &scope);
1245 self.bind(vec![(first, answer)], placed)
1246 }
1247 // A pattern that takes the rest apart has to have it to do so.
1248 _ => {
1249 let second = self.bind_pattern(second, &mut scope);
1250 let placed = self.rewrite(body, &scope);
1251 self.bind(vec![(first, answer), (second, rest)], placed)
1252 }
1253 }
1254 }
1255 }
1256 }
1257
1258 /// `body` under one `case` of one branch for each of `bound`, the first outermost.
1259 fn bind(&self, bound: Vec<(Pattern, Expression)>, body: Expression) -> Expression {
1260 bound
1261 .into_iter()
1262 .rev()
1263 .fold(body, |body, (pattern, scrutinee)| {
1264 self.case(scrutinee, vec![(pattern, body)])
1265 })
1266 }
1267
1268 // ── Rewriting a placed body ──────────────────────────────────────────────
1269
1270 /// A name for one variable a placed body binds, which no other binder of the instance
1271 /// shares: `$` and a serial, then the name the class wrote — `$3$x`.
1272 ///
1273 /// A body is placed once for every part the walk meets, and a part's body is placed
1274 /// inside the one before it, so copies of one body would each bind the same spelling
1275 /// inside the others' scope. No generated binder is ever in the scope of another binding
1276 /// of the same name, so generated code does not depend on how a later phase scopes a name
1277 /// that is bound again, which matters while the typer drops a shadowed outer binder when
1278 /// an inner scope ends (`BUG-49`). The same name is bound in more than one place all the same, since
1279 /// the rest of the walk is copied at each mention of `combine`'s second parameter; those
1280 /// are sibling scopes.
1281 fn fresh(&self, original: &Name) -> Name {
1282 let serial = self.serial.get();
1283 self.serial.set(serial + 1);
1284
1285 Name::new(format!("${}${}", serial, original))
1286 }
1287
1288 /// `pattern` as a placed body binds it: every node carries the span of `derived`, and
1289 /// every variable is a fresh one, which `scope` now maps the written name to.
1290 fn bind_pattern(&self, pattern: &Pattern, scope: &mut Scope) -> Pattern {
1291 let kind = match &pattern.kind {
1292 PatternKind::Variable(name) => {
1293 let fresh = self.fresh(name);
1294 scope.rename(name, fresh.clone());
1295 PatternKind::Variable(fresh)
1296 }
1297 PatternKind::Constructor { ctor, args } => PatternKind::Constructor {
1298 ctor: ctor.clone(),
1299 args: args
1300 .iter()
1301 .map(|arg| self.bind_pattern(arg, scope))
1302 .collect(),
1303 },
1304 PatternKind::Tuple(tuple) => {
1305 PatternKind::Tuple(tuple.map(|element| self.bind_pattern(element, scope)))
1306 }
1307 PatternKind::Hole(args) => PatternKind::Hole(
1308 args.iter()
1309 .map(|arg| self.bind_pattern(arg, scope))
1310 .collect(),
1311 ),
1312 PatternKind::Record(fields) => PatternKind::Record(
1313 fields
1314 .iter()
1315 .map(|field| PatternField {
1316 label: field.label.clone(),
1317 label_span: self.span,
1318 pattern: self.bind_pattern(&field.pattern, scope),
1319 })
1320 .collect(),
1321 ),
1322 kind @ (PatternKind::Anything
1323 | PatternKind::Int(_)
1324 | PatternKind::Float(_)
1325 | PatternKind::Char(_)
1326 | PatternKind::String(_)
1327 | PatternKind::Unit) => kind.clone(),
1328 };
1329
1330 self.pattern(kind)
1331 }
1332
1333 /// `expression` as it is placed here: every node carries the span of `derived`, a
1334 /// local is the fresh name `scope` gives it, and a reference to the local `scope`
1335 /// replaces is the expression it replaces it with.
1336 fn rewrite(&self, expression: &Expression, scope: &Scope) -> Expression {
1337 let again = |expression: &Expression| self.rewrite(expression, scope);
1338
1339 let kind = match &expression.kind {
1340 ExpressionKind::VarLocal(name) => match scope.replaced {
1341 Some((replaced, with)) if replaced == name => return with.clone(),
1342 _ => ExpressionKind::VarLocal(scope.renamed(name)),
1343 },
1344 ExpressionKind::Apply(function, argument) => {
1345 ExpressionKind::Apply(Box::new(again(function)), Box::new(again(argument)))
1346 }
1347 ExpressionKind::If(condition, then, otherwise) => ExpressionKind::If(
1348 Box::new(again(condition)),
1349 Box::new(again(then)),
1350 Box::new(again(otherwise)),
1351 ),
1352 ExpressionKind::Case(scrutinee, branches) => ExpressionKind::Case(
1353 Box::new(again(scrutinee)),
1354 branches
1355 .iter()
1356 .map(|branch| {
1357 // A branch binds its own names, which shadow what the scope
1358 // renames or replaces.
1359 let mut inner = scope.clone();
1360 let pattern = self.bind_pattern(&branch.pattern, &mut inner);
1361 CaseBranch {
1362 pattern,
1363 expression: self.rewrite(&branch.expression, &inner),
1364 span: self.span,
1365 }
1366 })
1367 .collect(),
1368 ),
1369 ExpressionKind::Accessor(label, _) => {
1370 ExpressionKind::Accessor(label.clone(), self.span)
1371 }
1372 ExpressionKind::Access(record, label, _) => {
1373 ExpressionKind::Access(Box::new(again(record)), label.clone(), self.span)
1374 }
1375 ExpressionKind::Record(fields) => ExpressionKind::Record(
1376 fields
1377 .iter()
1378 .map(|field| self.rewrite_field(field, scope))
1379 .collect(),
1380 ),
1381 ExpressionKind::Update(record, fields) => ExpressionKind::Update(
1382 Box::new(again(record)),
1383 fields
1384 .iter()
1385 .map(|field| self.rewrite_field(field, scope))
1386 .collect(),
1387 ),
1388 ExpressionKind::Tuple(tuple) => ExpressionKind::Tuple(tuple.map(again)),
1389 kind @ (ExpressionKind::VarTopLevel(_)
1390 | ExpressionKind::VarKernel(_)
1391 | ExpressionKind::VarForeign(..)
1392 | ExpressionKind::VarConstructor(..)
1393 | ExpressionKind::Char(_)
1394 | ExpressionKind::String(_)
1395 | ExpressionKind::Int(_)
1396 | ExpressionKind::Float(_)
1397 | ExpressionKind::Unit
1398 | ExpressionKind::Hole) => kind.clone(),
1399 };
1400
1401 self.expression(kind)
1402 }
1403
1404 fn rewrite_field(&self, field: &Field, scope: &Scope) -> Field {
1405 Field {
1406 label: field.label.clone(),
1407 label_span: self.span,
1408 value: self.rewrite(&field.value, scope),
1409 }
1410 }
1411
1412 // ── Building code ────────────────────────────────────────────────────────
1413
1414 fn expression(&self, kind: ExpressionKind) -> Expression {
1415 Expression::new(self.span, kind)
1416 }
1417
1418 fn pattern(&self, kind: PatternKind) -> Pattern {
1419 Pattern::new(self.span, kind)
1420 }
1421
1422 fn local(&self, name: &Name) -> Expression {
1423 self.expression(ExpressionKind::VarLocal(name.clone()))
1424 }
1425
1426 fn local_str(&self, name: &str) -> Expression {
1427 self.local(&Name::new(name))
1428 }
1429
1430 fn apply(&self, function: Expression, argument: Expression) -> Expression {
1431 self.expression(ExpressionKind::Apply(
1432 Box::new(function),
1433 Box::new(argument),
1434 ))
1435 }
1436
1437 fn case(&self, scrutinee: Expression, branches: Vec<(Pattern, Expression)>) -> Expression {
1438 self.expression(ExpressionKind::Case(
1439 Box::new(scrutinee),
1440 branches
1441 .into_iter()
1442 .map(|(pattern, expression)| CaseBranch {
1443 pattern,
1444 expression,
1445 span: self.span,
1446 })
1447 .collect(),
1448 ))
1449 }
1450
1451 /// A reference to `member`, which the module declaring the class names the way it names
1452 /// any value of its own, and every other module the way it names an imported one.
1453 fn member_reference(&self, member: &Member) -> Expression {
1454 let name = self.class.sibling(&member.name);
1455
1456 self.expression(if self.class_here {
1457 ExpressionKind::VarTopLevel(name)
1458 } else {
1459 ExpressionKind::VarForeign(name, self.class.package().clone(), member.tpe.clone())
1460 })
1461 }
1462
1463 /// The `Position` of the `index`th alternative of the type: the constructor of
1464 /// `Basics.Position`, which is exposed to no module and so is named by its
1465 /// declaration, applied to the place as an `Int`.
1466 fn position(&self, index: usize) -> Expression {
1467 let position = scalars::POSITION.qual_name();
1468 let int = scalars::INT.qual_name();
1469
1470 let constructor = self.expression(ExpressionKind::VarConstructor(
1471 position.sibling(&Name::new(scalars::POSITION.name)),
1472 Type::Arrow(
1473 Box::new(Type::Type(int, Vec::new())),
1474 Box::new(Type::Type(position, Vec::new())),
1475 ),
1476 ));
1477 // A place that does not fit an `Int` is a type with more constructors than a
1478 // module can declare.
1479 let place = i64::try_from(index).unwrap_or(i64::MAX);
1480
1481 self.apply(constructor, self.expression(ExpressionKind::Int(place)))
1482 }
1483
1484 /// The pattern for `alternative`, with each argument bound to the name of `names` or,
1485 /// with none, matching anything.
1486 fn alternative_pattern(&self, alternative: &Alternative, names: Option<&[Name]>) -> Pattern {
1487 let arguments: Vec<Pattern> = (0..alternative.arity)
1488 .map(|index| {
1489 self.pattern(match names.and_then(|names| names.get(index)) {
1490 Some(name) => PatternKind::Variable(name.clone()),
1491 None => PatternKind::Anything,
1492 })
1493 })
1494 .collect();
1495
1496 match alternative.constructor {
1497 Some(constructor) => self.pattern(PatternKind::Constructor {
1498 ctor: constructor.clone(),
1499 args: arguments,
1500 }),
1501 None => match tuple_of(arguments) {
1502 Ok(tuple) => self.pattern(PatternKind::Tuple(tuple)),
1503 Err(_) => self.pattern(PatternKind::Unit),
1504 },
1505 }
1506 }
1507}
1508
1509/// The patterns of `value` and its body, whichever form it was canonicalized as.
1510fn value_parts(value: &Value) -> (Vec<&Pattern>, &Expression) {
1511 match value {
1512 Value::Value { patterns, body, .. } => (patterns.iter().collect(), body),
1513 Value::TypedValue { patterns, body, .. } => {
1514 (patterns.iter().map(|(pattern, _)| pattern).collect(), body)
1515 }
1516 }
1517}
1518
1519/// `items` as a tuple of two or three, or handed back when it is neither.
1520fn tuple_of<T>(mut items: Vec<T>) -> Result<Tuple<T>, Vec<T>> {
1521 match items.len() {
1522 2 | 3 => {
1523 let third = if items.len() == 3 { items.pop() } else { None };
1524 match (items.pop(), items.pop(), third) {
1525 (Some(second), Some(first), Some(third)) => Ok(Tuple::three(first, second, third)),
1526 (Some(second), Some(first), None) => Ok(Tuple::two(first, second)),
1527 _ => Err(Vec::new()),
1528 }
1529 }
1530 _ => Err(items),
1531 }
1532}