Skip to main content

cove_runtime/
value.rs

1//! Runtime values.
2//!
3//! Assignment and ordinary argument passing use one rule: field-wise shallow
4//! copy. That rule is encoded directly in [`Clone`]: cloning a struct or enum
5//! copies its fields, cloning an `Array` shares immutable storage, and cloning
6//! a `Vector` copies only the handle so aliases observe the same elements and
7//! length. Cove never performs an implicit deep copy.
8//!
9//! # What an embedding host should write
10//!
11//! A host builds a value through a constructor — [`Value::unit`],
12//! [`Value::bool`], [`Value::int`], [`Value::float`], [`Value::duration`],
13//! [`Value::string`], [`Value::range_of`], [`Value::array`], [`Value::set`],
14//! [`Value::map`], [`Value::structure`], [`Value::enumeration`],
15//! [`Value::from_resource`], [`Value::host_fn`], [`Value::host_module`],
16//! [`Value::type_value`], [`Value::ok`], [`Value::err`], [`Value::some`],
17//! [`Value::none`], [`Value::error`] — and reads one through a reader:
18//! [`Value::field`],
19//! [`Value::fields`], [`Value::case`], [`Value::payload`], [`Value::items`],
20//! [`Value::elements`], [`Value::entries`], [`Value::declared_type`],
21//! [`Value::range`], [`Value::resource`], [`Value::host_op`],
22//! [`Value::arity`], and the scalar `as_*` family. Between them they cover
23//! every shape that crosses the Host API boundary, and none of them says how
24//! the runtime holds one.
25//!
26//! A host that wants to be told *what kind* of value it has calls
27//! [`Value::view`] and matches [`ValueView`], which is exhaustive on purpose.
28//!
29//! **There is no variant to match, and that is the point.** [`Value`]'s
30//! variants were `pub` until ADR 0028, and every change to what a value *is*
31//! was therefore a source break for the hosts that matched one: issue #104
32//! moved a struct from a `Box` to an `Rc`, issue #109 put a bound host
33//! operation's two names behind one pointer to take every value in the
34//! program from forty bytes to twenty-four, issue #121 replaced a closure's
35//! parameter list with an arity, and issue #183 replaced an enum payload's
36//! `Vec<Value>` with [`Payload`]. Each was invisible through the constructors
37//! and visible through a `match`, and each was rescued individually — twice
38//! by luck and once by a hand-written `Deref` shim. Issue #196 asked whether
39//! that should keep being paid for; ADR 0028 decision 6 answers no, for every
40//! variant and not a chosen subset, because a partial seal leaves the API a
41//! mixture and makes "which half may I match on" a question every embedder
42//! has to hold in their head.
43//!
44//! What a host loses is the compile error that said *the language changed*,
45//! and [`ValueView`] gives exactly that back: after this a representation
46//! change is invisible and a new kind of Cove value is a compile error at
47//! every `match`, which is the right way round.
48//!
49//! The readers are issue #186's answer to the same question on the way out;
50//! what they promise, what borrowing them forecloses, and what they do with a
51//! wrong shape are stated once, on the `impl Value` block that holds them.
52
53use std::cell::RefCell;
54use std::collections::{BTreeMap, BTreeSet};
55use std::fmt;
56use std::rc::Rc;
57use std::sync::Arc;
58
59use cove_schema::builtins::{
60    BuiltinSchema, CaseSchema, ERROR, ERR_CASE, MESSAGE_FIELD, NONE_CASE, OK_CASE, OPTION, RESULT,
61    SOME_CASE,
62};
63use cove_syntax::ast::{FnDecl, Param};
64
65use crate::host::ResourceHandle;
66use crate::shared::SharedCell;
67use crate::task::{Task, TaskScope};
68
69/// A Cove value.
70///
71/// **An abstract type.** What it holds is private to this crate: a host
72/// builds one through a constructor, reads one through a reader, and
73/// classifies one through [`Value::view`]. ADR 0028 decision 6 is where that
74/// was decided and issue #196 is where it was asked. Every change to what a
75/// value *is* had been a source break for the hosts that matched on it, and
76/// the record is not that `pub` variants are survivable but that each change
77/// was individually rescued — twice by luck and once by a hand-written
78/// compatibility shim.
79///
80/// The one thing sealing takes away is the compile error a host got when a
81/// new variant arrived, and [`ValueView`] gives that back deliberately and
82/// exhaustively. What it does *not* give back is a compile error when the
83/// runtime moves a value from a `Box` to an `Rc`, which is the whole point:
84/// those two were the same error before, and they are unrelated events.
85#[derive(Clone)]
86pub struct Value(pub(crate) Repr);
87
88/// `Value` prints as the value it is, and not as a wrapper around one.
89///
90/// Forwarded rather than derived so that the newtype the seal is made of
91/// leaves no trace in a rendering: a `Debug` of an `Int` is `Int(3)`, exactly
92/// as it was when `Value` was the enum itself. Tests, traces and diagnostics
93/// all read this, and none of them should have to know.
94impl fmt::Debug for Value {
95    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96        fmt::Debug::fmt(&self.0, f)
97    }
98}
99
100/// How this crate holds a value. Private, and it is the seal.
101///
102/// The variants are exactly what `Value`'s were, and this crate matches them
103/// exactly as it did — a pattern reads `Value(Repr::Int(n))` where it read
104/// `Value::Int(n)`, and that is the whole of the difference on this side of
105/// the boundary. Nothing outside the crate can name any of it, which is what
106/// ADR 0028 decision 0 means by representations that cannot fail to differ.
107#[derive(Clone, Debug)]
108pub(crate) enum Repr {
109    Unit,
110    Bool(bool),
111    Int(i64),
112    Float(f64),
113    /// A duration in nanoseconds.
114    Duration(i64),
115    Str(Rc<str>),
116    /// Fixed-length immutable sequence; sharing its storage is unobservable.
117    Array(Rc<[Value]>),
118    /// Growable mutable sequence backed by stable shared storage. Copying the
119    /// handle is O(1) and aliases observe the same elements and length.
120    Vector(Rc<VectorStorage>),
121    /// Immutable in the MVP. Iterates in ascending key order, since that is
122    /// the natural order of its `BTreeMap` storage.
123    Map(Rc<BTreeMap<MapKey, Value>>),
124    /// Immutable in the MVP. Backed by the same key-ordered storage as `Map`,
125    /// so membership is O(log n) and iteration order is defined the same
126    /// way: ascending order. An element must satisfy the [`MapKey`]
127    /// restriction, exactly like a map key.
128    Set(Rc<BTreeSet<MapKey>>),
129    /// A struct value.
130    ///
131    /// The storage is shared and copied on write. Cloning a struct value is
132    /// the field-wise shallow copy the Language Card describes, and sharing
133    /// the fields until one of them is written is unobservable: a write goes
134    /// through a place, [`crate::interp`]'s `Place::with_mut` is the only way
135    /// to reach one, and it takes a private copy first when the storage has
136    /// another holder. Nothing else can tell the two apart, because `is` is
137    /// defined only for `Vector`.
138    ///
139    /// It is shared because it was copied on every non-mutating method call:
140    /// `self` is passed by value, and a copy was a `Box` and a `Vec` and a
141    /// clone of every field. That made a method call twice the cost of the
142    /// same code with the fields read directly, which issue #99 measured and
143    /// issue #104 set out to remove.
144    ///
145    /// This was a `Box<StructValue>` until issue #104. Nothing a Cove program
146    /// can write sees the difference, but an embedder building a struct value
147    /// writes `Rc::new` where it wrote `Box::new`, and one matching on the
148    /// variant binds an `&Rc<StructValue>` where it bound an
149    /// `&Box<StructValue>` — both deref to `StructValue`, so a body that only
150    /// reads fields needs no change. Mutating through one needs
151    /// [`Rc::make_mut`], which is what keeps the copy private.
152    Struct(Rc<StructValue>),
153    /// An enum value, including `Option` and `Result`.
154    ///
155    /// One allocation, not two: the box is the whole of it, because
156    /// [`Payload`] holds the arities an ordinary program builds inside the
157    /// [`EnumValue`] rather than in a vector beside it. Issue #183 is why,
158    /// and `benches/arrayget` is where it shows.
159    Enum(Box<EnumValue>),
160    /// A callback is an ordinary handle value.
161    Closure(Rc<Closure>),
162    /// A `dyn Trait` value: a concrete value together with the trait it was
163    /// used at.
164    ///
165    /// This is the one place where a Cove value's runtime representation
166    /// depends on its static type. A concrete value is wrapped here at the
167    /// point it is used where a `dyn Trait` is expected, and the wrapper
168    /// carries what a concrete value does not: the trait, so a diagnostic can
169    /// name it, and the value itself, whose own type is what dispatch finds
170    /// the implementation from.
171    Dyn(Rc<DynValue>),
172    /// A bound host module such as `console`.
173    HostModule(Rc<str>),
174    /// A handle to a resource the host owns, such as a database connection.
175    ///
176    /// The handle is a name, never the thing itself: what a
177    /// `database.Connection` really is stays on the host's side of the
178    /// boundary, and this value carries only the identity that addresses it.
179    /// That is what lets a handle be copied like any other value, crossed
180    /// into a task when its schema allows it, written into a trace, and
181    /// handed back by a replay — see ADR 0013 and
182    /// [`crate::host::ResourceHandle`].
183    Resource(Arc<ResourceHandle>),
184    /// A bound host operation such as `console.println`.
185    ///
186    /// The two names live behind one pointer, exactly as [`Value::Struct`]
187    /// and [`Value::Dyn`] hold their contents, and for the same kind of
188    /// reason: a variant is as wide as its widest member, and this one held
189    /// two fat pointers where every other variant holds at most one. Thirty-
190    /// two bytes for the pair set the width of every `Value` in the program,
191    /// including the `Int`s the two backends spend most of their time moving.
192    ///
193    /// The trade is an allocation for a value that is built when a host
194    /// operation is *used* as a value — `console.println` bound to a name or
195    /// passed as an argument — rather than called in place, which is rare,
196    /// against sixteen bytes off every value everywhere.
197    ///
198    /// An embedder constructing one writes `Value::HostFn(Rc::new(
199    /// HostFnValue { module, op }))` where it wrote `Value::HostFn { module,
200    /// op }`, and one matching on the variant binds an `&Rc<HostFnValue>`
201    /// whose fields have the names and the types they had.
202    HostFn(Rc<HostFnValue>),
203    /// A type used as a value, such as `Vector` in `Vector.of(1, 2)`.
204    Type(Rc<str>),
205    /// An integer range. `..` includes `end` and `..<` excludes it.
206    ///
207    /// A range is an ordinary value: it can be bound, passed, compared, and
208    /// iterated. An empty or reversed range such as `3..<0` yields nothing.
209    Range {
210        start: i64,
211        end: i64,
212        inclusive_end: bool,
213    },
214    /// The task scope `scope tasks { ... }` binds. Concurrent work belongs to
215    /// a task scope, and the scope owns the tasks spawned into it.
216    TaskScope(Rc<TaskScope>),
217    /// A handle to a spawned task. The task's value is reachable only through
218    /// `await` or through the scope settling it on exit.
219    Task(Rc<Task>),
220    /// `Shared(value)`: mutable state more than one task may reach.
221    ///
222    /// This is the one value whose storage is an [`Arc`] rather than an
223    /// [`Rc`]: a `Shared` crosses a task boundary by sharing its cell, so two
224    /// task threads address the same one. Its contents are reachable only
225    /// through `lock`; see [`crate::shared`].
226    Shared(Arc<SharedCell>),
227}
228
229// A `Value` is twenty-four bytes, and nothing else in this file says so.
230//
231// It was forty until issue #109's audit, because exactly one variant was wide:
232// `HostFn` inlined two fat pointers, so the variant that names
233// `console.println` set the width of every `Int` both backends move. Boxing it
234// was worth `field` −4.9% and `method` −6.3% on the predecessor VM and `arith`
235// −8.2% on the interpreter — the first change since that backend landed to
236// make both backends faster. Width was then measured directly, by widening
237// `Value` with a padding
238// variant nothing constructs and running the suite at 24, 32 and 40: about a
239// percent per eight bytes. See `docs/VM_ARCHITECTURE.md`, "The value
240// representation, audited".
241//
242// So this is the one number a new variant can undo silently. A second variant
243// holding two pointers takes every `Value` in the program back to 32 and costs
244// what the audit bought, and nothing about writing it would say so. This
245// refuses to compile instead.
246//
247// Twenty-four is the floor for the variants that exist — `Range` is two `i128`
248// halves reduced to `(i64, i64, bool)` whose `bool` niche holds the
249// discriminant — and sixteen is the floor for the *language*, since `Int` is a
250// full sixty-four bits with overflow a broken invariant, which is why NaN
251// boxing and pointer tagging are rejected rather than deferred. Neither number
252// is a target to shrink to: 24 → 16 was measured and not taken.
253//
254// Guarded on the pointer width because every non-scalar variant is one
255// pointer, so this says nothing on a 32-bit target.
256#[cfg(target_pointer_width = "64")]
257const _: () = assert!(
258    std::mem::size_of::<Value>() == 24,
259    "a Value is 24 bytes; a variant wider than one pointer takes every value \
260     in the program back to 32 — see docs/VM_ARCHITECTURE.md, \"The value \
261     representation, audited\""
262);
263
264/// The half-open bounds of a `Range` value, widened to `i128` so that an
265/// inclusive `i64::MAX` end cannot overflow.
266#[derive(Clone, Copy, Debug)]
267pub struct RangeBounds {
268    /// The first value the range can yield.
269    pub start: i128,
270    /// The first value past the end.
271    pub end: i128,
272}
273
274impl RangeBounds {
275    /// Normalises the AST form, where `inclusive_end` selects `..` over `..<`.
276    pub fn of(start: i64, end: i64, inclusive_end: bool) -> RangeBounds {
277        RangeBounds {
278            start: i128::from(start),
279            end: i128::from(end) + i128::from(inclusive_end),
280        }
281    }
282
283    /// The number of values the range yields. A reversed range yields none.
284    pub fn len(self) -> i64 {
285        (self.end - self.start).max(0) as i64
286    }
287
288    /// Whether the range yields no values at all.
289    pub fn is_empty(self) -> bool {
290        self.end <= self.start
291    }
292
293    /// Whether `value` is one of the values the range yields.
294    pub fn contains(self, value: i64) -> bool {
295        let value = i128::from(value);
296        self.start <= value && value < self.end
297    }
298
299    /// The values the range yields, in order.
300    pub fn items(self) -> Vec<Value> {
301        (self.start..self.end)
302            .map(|n| Value(Repr::Int(n as i64)))
303            .collect()
304    }
305}
306
307/// Growable vector storage. Length, capacity, and elements all belong to the
308/// shared storage, so growth stays visible through every alias.
309#[derive(Debug, Default)]
310pub struct VectorStorage {
311    pub elements: RefCell<Vec<Value>>,
312    /// Set by `freeze()`, which consumes uniquely owned storage.
313    pub frozen: RefCell<bool>,
314}
315
316impl VectorStorage {
317    pub fn new(elements: Vec<Value>) -> Rc<VectorStorage> {
318        Rc::new(VectorStorage {
319            elements: RefCell::new(elements),
320            frozen: RefCell::new(false),
321        })
322    }
323
324    pub fn len(&self) -> usize {
325        self.elements.borrow().len()
326    }
327
328    pub fn is_empty(&self) -> bool {
329        self.len() == 0
330    }
331}
332
333#[derive(Clone, Debug)]
334pub struct StructValue {
335    /// Fully qualified type name, such as `values.BookingDraft`.
336    pub type_name: Rc<str>,
337    /// Fields in declaration order.
338    pub fields: Vec<(Rc<str>, Value)>,
339    /// Whether the type was declared `export opaque struct`, in which case
340    /// the value renders as its name alone (ADR 0014).
341    ///
342    /// The flag rides on the value because rendering is context-free: a
343    /// `Display` has no idea which module is watching, and a value formatted
344    /// in the module that declares it can be handed to one that may not name
345    /// its fields. So the representation is hidden from every reader,
346    /// including the declaring module, which publishes a readable form by
347    /// exporting a method that builds one.
348    pub opaque: bool,
349}
350
351impl StructValue {
352    pub fn get(&self, name: &str) -> Option<&Value> {
353        self.fields
354            .iter()
355            .find(|(n, _)| &**n == name)
356            .map(|(_, v)| v)
357    }
358
359    pub fn get_mut(&mut self, name: &str) -> Option<&mut Value> {
360        self.fields
361            .iter_mut()
362            .find(|(n, _)| &**n == name)
363            .map(|(_, v)| v)
364    }
365}
366
367#[derive(Clone, Debug)]
368pub struct EnumValue {
369    /// Fully qualified type name, or `Option` / `Result` for the builtins.
370    pub type_name: Rc<str>,
371    pub case: Rc<str>,
372    pub payload: Payload,
373}
374
375/// What an enum case carries, held inline for the arities that occur.
376///
377/// This was a `Vec<Value>` until [issue
378/// #183](https://github.com/myuon/cove/issues/183). A `Value::Enum` is a
379/// `Box<EnumValue>`, so a `Some(x)` cost *two* allocations: the box for the
380/// struct, and a vector for a payload of one. Almost every enum case an
381/// ordinary program builds carries zero or one value — `Option` and `Result`
382/// are the two the language builds constantly, and `benches/arrayget`'s
383/// comment says why: an `Option` is how every indexed read answers. Holding
384/// the common arities in the box that already exists makes `Some(x)` one
385/// allocation instead of two.
386///
387/// It is an enum rather than a `Box<[Value]>` because a boxed slice still
388/// allocates for one element, and rather than a general small-vector because
389/// there are exactly two shapes worth naming: no payload, and one. Two or
390/// more is a `Box<[Value]>` rather than a `Vec` because a payload is never
391/// grown after the case is built — the length is the case declaration's, and
392/// nothing in this workspace pushes onto one.
393///
394/// **This reads as a slice.** [`std::ops::Deref`] and [`std::ops::DerefMut`]
395/// to `[Value]`, and `IntoIterator` on `&Payload` and `&mut Payload`, so
396/// `payload.len()`, `payload[0]`, `payload.first()`, `for item in &payload`
397/// and matching `&*payload` against `[inner]` all mean what they meant. [`fmt::Debug`] is
398/// written by hand to print as the list it reads as, so a `Debug` rendering
399/// of an enum value is the one it always was.
400///
401/// An embedder that built one by naming the field writes `payload:
402/// Payload::One(value)` or `payload: values.into()` where it wrote `payload:
403/// vec![value]`; one that goes through [`Value::enumeration`],
404/// [`Value::some`] or [`Value::ok`] writes nothing new, because those take
405/// what they took.
406#[derive(Clone, Default)]
407pub enum Payload {
408    /// A case with no payload, such as `None`.
409    #[default]
410    Empty,
411    /// A case carrying exactly one value, such as `Some(x)` or `Err(e)`.
412    One(Value),
413    /// A case carrying two or more.
414    Many(Box<[Value]>),
415}
416
417impl Payload {
418    /// The payload as a slice, which is what every reader wants of one.
419    pub fn as_slice(&self) -> &[Value] {
420        match self {
421            Payload::Empty => &[],
422            Payload::One(value) => std::slice::from_ref(value),
423            Payload::Many(values) => values,
424        }
425    }
426
427    /// The payload as a mutable slice.
428    pub fn as_mut_slice(&mut self) -> &mut [Value] {
429        match self {
430            Payload::Empty => &mut [],
431            Payload::One(value) => std::slice::from_mut(value),
432            Payload::Many(values) => values,
433        }
434    }
435
436    /// The payload as an owned vector, for a caller that needs one.
437    ///
438    /// This allocates, which is the thing the type exists to avoid, so it is
439    /// here for the callers that genuinely take ownership rather than as the
440    /// way to read one.
441    pub fn into_vec(self) -> Vec<Value> {
442        match self {
443            Payload::Empty => Vec::new(),
444            Payload::One(value) => vec![value],
445            Payload::Many(values) => values.into_vec(),
446        }
447    }
448}
449
450impl std::ops::Deref for Payload {
451    type Target = [Value];
452
453    fn deref(&self) -> &[Value] {
454        self.as_slice()
455    }
456}
457
458impl std::ops::DerefMut for Payload {
459    fn deref_mut(&mut self) -> &mut [Value] {
460        self.as_mut_slice()
461    }
462}
463
464impl<'a> IntoIterator for &'a Payload {
465    type Item = &'a Value;
466    type IntoIter = std::slice::Iter<'a, Value>;
467
468    fn into_iter(self) -> Self::IntoIter {
469        self.as_slice().iter()
470    }
471}
472
473impl<'a> IntoIterator for &'a mut Payload {
474    type Item = &'a mut Value;
475    type IntoIter = std::slice::IterMut<'a, Value>;
476
477    fn into_iter(self) -> Self::IntoIter {
478        self.as_mut_slice().iter_mut()
479    }
480}
481
482/// Prints as the list a payload reads as, rather than as the variant that
483/// happens to be holding it.
484///
485/// Deliberate: the arity a payload is stored at is an implementation detail
486/// of this type, and a `Debug` rendering that named it would make the same
487/// enum value print two ways depending on how many values it carries.
488impl fmt::Debug for Payload {
489    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
490        f.debug_list().entries(self.as_slice()).finish()
491    }
492}
493
494impl FromIterator<Value> for Payload {
495    fn from_iter<I: IntoIterator<Item = Value>>(values: I) -> Payload {
496        let mut values = values.into_iter();
497        let Some(first) = values.next() else {
498            return Payload::Empty;
499        };
500        let Some(second) = values.next() else {
501            return Payload::One(first);
502        };
503        let mut rest = Vec::with_capacity(2 + values.size_hint().0);
504        rest.push(first);
505        rest.push(second);
506        rest.extend(values);
507        Payload::Many(rest.into_boxed_slice())
508    }
509}
510
511impl From<Vec<Value>> for Payload {
512    fn from(mut values: Vec<Value>) -> Payload {
513        match values.len() {
514            0 => Payload::Empty,
515            1 => Payload::One(
516                values
517                    .pop()
518                    .expect("a vector of length one has a last element"),
519            ),
520            _ => Payload::Many(values.into_boxed_slice()),
521        }
522    }
523}
524
525/// The contents of a `dyn Trait` value, which [`Value::dyn_trait`] names
526/// and no other reader admits.
527#[derive(Clone, Debug)]
528pub struct DynValue {
529    /// Fully qualified trait name, such as `render.Display`.
530    pub trait_name: Rc<str>,
531    /// The concrete value. Its own type is what dynamic dispatch resolves a
532    /// method against, which is exactly what makes this dispatch dynamic.
533    pub value: Value,
534}
535
536/// The two names a bound host operation is: the host module the operation
537/// belongs to, and the operation itself.
538///
539/// Neither is the operation's implementation. A bound host operation is a
540/// name the same way a bound host module is, and what it names is looked up
541/// through the registry at the call.
542#[derive(Clone, Debug)]
543pub struct HostFnValue {
544    /// The host module, such as `console`.
545    pub module: Rc<str>,
546    /// The operation's own name, such as `println`.
547    pub op: Rc<str>,
548}
549
550/// A closure captures its environment by value at creation time.
551#[derive(Debug)]
552pub struct Closure {
553    pub is_async: bool,
554    /// How many parameters this closure declares.
555    ///
556    /// The whole of its signature that anything outside the backend that
557    /// built it asks for, and the reason it is a number rather than the
558    /// parameter list it used to be. Every reader wanted a count:
559    /// [`crate::builtins::Callable::arity`] answers out of this,
560    /// `Result.mapError` reads it to decide whether to hand its callback the
561    /// error it is replacing, and `builtins::expect_callback` refuses a
562    /// callback of the wrong shape in one place rather than at every call
563    /// site that needs the check. None of them wanted a name, a default, a
564    /// type or a span, and issue #121 is where each was asked and answered.
565    ///
566    /// It counts parameters, not arguments a call must supply: a defaulted
567    /// or a variadic parameter is one of these like any other, which is what
568    /// `params.len()` answered when this was a `Vec<Param>`.
569    pub arity: usize,
570    pub body: ClosureBody,
571    /// The module a closure body resolves names in.
572    pub module: Rc<str>,
573    pub captures: Vec<(Rc<str>, Value)>,
574}
575
576/// Where a closure's body is, which is the one thing about a closure the two
577/// backends do not agree on.
578///
579/// Everything else a closure is — what it captured, how many parameters it
580/// declares, which module it resolves names in, whether it is `async` — is
581/// the same fact whichever backend made it, and a host that receives one
582/// reads those the same way either way. The body is not: the interpreter
583/// walks a tree and the linear-memory backend runs a lowered function, and
584/// neither can run the other's.
585///
586/// **The declaration is part of the body, not part of the closure.** The
587/// parameters an interpreted call binds against and the return type it
588/// coerces to are syntax, and syntax is one backend's form of a body: a
589/// lowered function has neither, because `cove_ir::lower` spent both when it
590/// chose the slots and emitted the conversions. Keeping them beside the
591/// `Arc<Block>` they came from is what lets every field of a [`Closure`]
592/// outside this enum be a fact both backends state the same way, so that
593/// reaching syntax means reaching past the one variant that has any — which
594/// is the direction issue #109 asks for.
595///
596/// So this is an enum rather than a second `Value` variant. Issue #109 asks
597/// that the internal representation become *less* exposed to an embedder,
598/// not more, and a `Value::LoweredClosure` beside `Value::Closure` would make
599/// every host that already handles a callback handle two — while the
600/// difference between them is one field that no host reads. A host calls a
601/// closure back through [`crate::host::Reentry`], which hands it to the
602/// backend that made it, and that backend is the only party that has to know
603/// which of these it is.
604#[derive(Clone, Debug)]
605pub enum ClosureBody {
606    /// The syntax [`crate::interp::Interpreter`] walks, and the declaration
607    /// it walks it under.
608    Tree {
609        /// The parameters as source wrote them.
610        ///
611        /// `Interpreter::bind_params` reads every field of one: the name to
612        /// match a labelled argument against, `variadic` to know which
613        /// arguments to gather, `default` to evaluate in the callee's
614        /// environment when an argument was left out, and `is_var` to bind
615        /// the caller's place rather than a copy — which is also what
616        /// `Interpreter::call_shared_method` reads off the first parameter
617        /// of a `lock` closure. The lowering answers that last question when
618        /// it chooses the slots, and has no use for the other three.
619        params: Vec<Param>,
620        /// The block to evaluate.
621        block: Arc<cove_syntax::ast::Block>,
622        /// The declaration this closure came from, and `None` for a lambda,
623        /// which has none of its own.
624        ///
625        /// Read for the written return type: a `dyn Trait` in it is what
626        /// tells the interpreter to wrap what the body produced. The lowered
627        /// form needs no equivalent, because `cove_ir::lower` boxes what a
628        /// function declared as erased returns, so the answer that leaves a
629        /// lowered body is already wrapped.
630        decl: Option<Arc<FnDecl>>,
631    },
632    /// The lowered function `cove_runtime::vm` runs, addressed in the
633    /// [`cove_ir::Program`] that run was given, together with the
634    /// environment object it closes over.
635    ///
636    /// A closure built by one run cannot be called by another, which is true
637    /// of the tree form as well: both name something a particular run owns.
638    /// Which of the two a `Closure` holds is the question *which backend made
639    /// this*, and [`crate::host::Reentry`] is the only thing that asks it.
640    ///
641    /// The environment is here and the captures are not. A `cove-ir`
642    /// closure's captures are inline in a heap object, at the widths its
643    /// layout says, and copying them out into [`Closure::captures`] would be
644    /// materialising a value nothing asked for and losing the identity of the
645    /// storage they came from. So the object crosses instead, as a
646    /// [`LinearClosure`], and [`Closure::captures`] is empty.
647    Linear(LinearClosure),
648}
649
650/// A closure the linear-memory backend made: which function runs, and the
651/// environment object it reads its captures out of.
652///
653/// **It roots the object it names.** A frame is a root because a static map
654/// says which of its slots are references, and the lowering clears a
655/// temporary's slot at its last use — which for a closure handed to a host is
656/// the instruction after the call. The [`crate::host::Reentry`] contract says
657/// a host may keep a callback for later, so the value has to keep the object
658/// alive by itself, and the handle inside this is what does it. Nothing in a
659/// frame need name the object while a host holds one, and after the call
660/// nothing does.
661#[derive(Clone, Debug)]
662pub struct LinearClosure {
663    /// The body, in the program that run was given.
664    pub(crate) function: cove_ir::FunctionId,
665    /// The environment object, and the claim that keeps it a root.
666    pub(crate) env: crate::vm::mem::Rooted,
667}
668
669/// A value usable as a `Map` key or `Set` element.
670///
671/// ADR 0001 draws the line at mutability, not at primitives: "mutable
672/// handles and structs containing them are not valid map keys." A key's
673/// equality must not change while a collection holds it, so this is
674/// recursive rather than a flat list of primitive shapes — a `Struct`, an
675/// `Array`, or an enum case with a payload qualifies exactly when everything
676/// nested inside it does. `Map` and `Set` qualify too: both are immutable
677/// handles, so nesting one as a key changes nothing about the rule, only how
678/// deep the check goes. A `Range` qualifies for the same reason: it is an
679/// immutable value with a stable `eq_value`, ordered consistently by its
680/// `(start, end, inclusive_end)` fields. `Float` is rejected for an unrelated
681/// reason: `NaN` is not equal to itself, which breaks the total order every
682/// key needs.
683#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
684pub enum MapKey {
685    Unit,
686    Bool(bool),
687    Int(i64),
688    Duration(i64),
689    Str(String),
690    /// An enum case, keyed by `(type, case)`, with every payload value
691    /// converted the same way.
692    EnumCase(String, String, Vec<MapKey>),
693    /// A struct, keyed by type name, with every field converted the same
694    /// way, in declaration order, and whether its type is opaque — a key is
695    /// rendered back as a value for `keys()` and for `Display`, and a value
696    /// of an opaque type shows only its name wherever it is read from.
697    Struct(String, Vec<(String, MapKey)>, bool),
698    /// An array, with every element converted the same way. An array is
699    /// fixed-length and immutable, so its equality cannot change.
700    Array(Vec<MapKey>),
701    /// A `Set`. Its elements are already `MapKey`s by construction, so
702    /// nesting one never fails.
703    Set(BTreeSet<MapKey>),
704    /// A `Map`. Its keys are already `MapKey`s by construction; only its
705    /// values need converting, and the first one that cannot be is why
706    /// nesting a `Map` as a key can still fail.
707    Map(BTreeMap<MapKey, MapKey>),
708    /// A range. Immutable with a stable `eq_value`, so it qualifies under the
709    /// same rule as every other key: its equality cannot change while a
710    /// collection holds it. Ordered by `(start, end, inclusive_end)`, which is
711    /// a total order because every field is.
712    Range {
713        start: i64,
714        end: i64,
715        inclusive_end: bool,
716    },
717}
718
719/// Why a value cannot be a `Map` key or `Set` element.
720#[derive(Clone, Debug, PartialEq, Eq)]
721pub struct InvalidKey {
722    /// How the offending part is reached from the value that was tested,
723    /// such as `Point.tags` or `Point.tags[0]`. Empty when the value itself,
724    /// not something nested inside it, is the problem.
725    pub path: String,
726    /// The type that cannot be a key.
727    pub type_name: String,
728}
729
730impl InvalidKey {
731    /// The rule this violation breaks.
732    ///
733    /// `Float` is excluded for a reason distinct from every other rejection:
734    /// `NaN != NaN` breaks the total order a key needs, which has nothing to
735    /// do with mutability. Stating that separately keeps anyone from later
736    /// "fixing" `Float` as if it were just another mutable-handle case.
737    pub fn rule(&self) -> &'static str {
738        if self.type_name == "Float" {
739            "A `Float` cannot be a map key or set element: `NaN` is not equal to itself, which breaks the total order every key needs."
740        } else {
741            "Mutable handles and structs containing them are not valid map keys: a key's equality must not change while a collection holds it."
742        }
743    }
744
745    /// A corrected textual example, tailored to the same distinction.
746    pub fn help(&self) -> String {
747        if self.type_name == "Float" {
748            "convert it to a stable key first, such as rounding to an `Int` or formatting it as a `String`".to_string()
749        } else {
750            "use a value built only from `Bool`, `Int`, `Str`, `Duration`, `Unit`, a range, arrays, structs, enum cases, `Map`, or `Set` — all free of mutable handles".to_string()
751        }
752    }
753}
754
755impl MapKey {
756    /// Converts `value` to a map key or set element, or reports the specific
757    /// part that cannot be one, with the path to reach it.
758    pub fn from_value(value: &Value) -> Result<MapKey, InvalidKey> {
759        Self::convert(None, value)
760    }
761
762    /// `anchor` is the path to `value` from the root value under test, so a
763    /// rejection nested several levels down can still be reported precisely.
764    /// `None` at the root, since a bare value being tested has no name to
765    /// anchor a nested path to; a `Struct` or `Enum` invents one from its own
766    /// type name the first time a path is needed.
767    fn convert(anchor: Option<&str>, value: &Value) -> Result<MapKey, InvalidKey> {
768        // Through the `dyn Trait` wrapper first. Two values `==` calls equal
769        // have to be interchangeable as keys, and equality already looks
770        // through it, so a written `dyn Trait` and a lambda's inferred one
771        // key as the same thing they compare as: the value they hold.
772        match value.erased() {
773            Value(Repr::Unit) => Ok(MapKey::Unit),
774            Value(Repr::Bool(b)) => Ok(MapKey::Bool(*b)),
775            Value(Repr::Int(n)) => Ok(MapKey::Int(*n)),
776            Value(Repr::Duration(ns)) => Ok(MapKey::Duration(*ns)),
777            Value(Repr::Str(s)) => Ok(MapKey::Str(s.to_string())),
778            Value(Repr::Enum(e)) => {
779                let base = anchor
780                    .map(str::to_string)
781                    .unwrap_or_else(|| format!("{}.{}", short_name(&e.type_name), e.case));
782                let mut payload = Vec::with_capacity(e.payload.len());
783                for (i, item) in e.payload.iter().enumerate() {
784                    payload.push(Self::convert(Some(&format!("{base}({i})")), item)?);
785                }
786                Ok(MapKey::EnumCase(
787                    e.type_name.to_string(),
788                    e.case.to_string(),
789                    payload,
790                ))
791            }
792            Value(Repr::Struct(s)) => {
793                let base = anchor
794                    .map(str::to_string)
795                    .unwrap_or_else(|| short_name(&s.type_name).to_string());
796                let mut fields = Vec::with_capacity(s.fields.len());
797                for (name, field) in &s.fields {
798                    let child = Self::convert(Some(&format!("{base}.{name}")), field)?;
799                    fields.push((name.to_string(), child));
800                }
801                Ok(MapKey::Struct(s.type_name.to_string(), fields, s.opaque))
802            }
803            Value(Repr::Array(items)) => {
804                let base = anchor.unwrap_or_default();
805                let mut converted = Vec::with_capacity(items.len());
806                for (i, item) in items.iter().enumerate() {
807                    converted.push(Self::convert(Some(&format!("{base}[{i}]")), item)?);
808                }
809                Ok(MapKey::Array(converted))
810            }
811            // A `Set`'s elements are already `MapKey`s by construction, so
812            // this never fails.
813            Value(Repr::Set(items)) => Ok(MapKey::Set((**items).clone())),
814            Value(Repr::Map(entries)) => {
815                let base = anchor.unwrap_or_default();
816                let mut converted = BTreeMap::new();
817                for (key, item) in entries.iter() {
818                    let child = Self::convert(Some(&format!("{base}[{key}]")), item)?;
819                    converted.insert(key.clone(), child);
820                }
821                Ok(MapKey::Map(converted))
822            }
823            Value(Repr::Range {
824                start,
825                end,
826                inclusive_end,
827            }) => Ok(MapKey::Range {
828                start: *start,
829                end: *end,
830                inclusive_end: *inclusive_end,
831            }),
832            Value(Repr::Float(_)) => Err(InvalidKey {
833                path: anchor.map(str::to_string).unwrap_or_default(),
834                type_name: "Float".to_string(),
835            }),
836            other => Err(InvalidKey {
837                path: anchor.map(str::to_string).unwrap_or_default(),
838                type_name: other.type_name(),
839            }),
840        }
841    }
842
843    /// Renders this key back as an ordinary value, for `keys()`, `Set`
844    /// iteration, and `toArray()`.
845    pub fn to_value(&self) -> Value {
846        match self {
847            MapKey::Unit => Value(Repr::Unit),
848            MapKey::Bool(b) => Value(Repr::Bool(*b)),
849            MapKey::Int(n) => Value(Repr::Int(*n)),
850            MapKey::Duration(ns) => Value(Repr::Duration(*ns)),
851            MapKey::Str(s) => Value(Repr::Str(s.as_str().into())),
852            MapKey::EnumCase(type_name, case, payload) => Value(Repr::Enum(Box::new(EnumValue {
853                type_name: type_name.as_str().into(),
854                case: case.as_str().into(),
855                payload: payload.iter().map(MapKey::to_value).collect(),
856            }))),
857            MapKey::Struct(type_name, fields, opaque) => {
858                Value(Repr::Struct(Rc::new(StructValue {
859                    type_name: type_name.as_str().into(),
860                    fields: fields
861                        .iter()
862                        .map(|(name, key)| (name.as_str().into(), key.to_value()))
863                        .collect(),
864                    opaque: *opaque,
865                })))
866            }
867            MapKey::Array(items) => {
868                Value(Repr::Array(items.iter().map(MapKey::to_value).collect()))
869            }
870            MapKey::Set(items) => Value(Repr::Set(Rc::new(items.clone()))),
871            MapKey::Map(entries) => Value(Repr::Map(Rc::new(
872                entries
873                    .iter()
874                    .map(|(key, value)| (key.clone(), value.to_value()))
875                    .collect(),
876            ))),
877            MapKey::Range {
878                start,
879                end,
880                inclusive_end,
881            } => Value(Repr::Range {
882                start: *start,
883                end: *end,
884                inclusive_end: *inclusive_end,
885            }),
886        }
887    }
888}
889
890/// The unqualified name shown in a key path, matching how `Value`'s
891/// `Display` shortens a struct's fully qualified type name.
892fn short_name(qualified: &str) -> &str {
893    qualified.rsplit('.').next().unwrap_or(qualified)
894}
895
896/// A key displays exactly as the value it represents would, so a `Map`'s
897/// entries read the same way here as they would anywhere else in the
898/// language.
899impl fmt::Display for MapKey {
900    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
901        write!(f, "{}", self.to_value())
902    }
903}
904
905/// The eight builtin names, made once per thread and handed out by
906/// reference count.
907///
908/// `Option` and `Result` are built constantly — every `Array.get`, every
909/// `?`, every fallible builtin — and issue #104 stopped each one allocating
910/// two `Rc<str>` by keeping the strings in a thread-local list and scanning
911/// it for the one asked for. The strings never changed, but the scan stayed:
912/// a `Some(x)` cost two thread-local accesses, two `RefCell` borrows, and
913/// two linear walks comparing string contents. This is the same idea with
914/// the lookup taken out — the names are fields, so a constructor reaches the
915/// thread-local once and clones two `Rc`s out of it. Issue #193 records it
916/// as the other half of #183, which took the payload's allocation and left
917/// this.
918///
919/// Per thread rather than global, for #104's reason: `Rc` is not shareable
920/// across threads, and ADR 0008 gives each task a thread.
921struct BuiltinNames {
922    result: Rc<str>,
923    ok: Rc<str>,
924    err: Rc<str>,
925    option: Rc<str>,
926    some: Rc<str>,
927    none: Rc<str>,
928    error: Rc<str>,
929    message: Rc<str>,
930}
931
932thread_local! {
933    /// Built on the first `Ok`, `Err`, `Some`, `None` or `Error` this thread
934    /// makes, which is the same eight allocations #104's list made lazily,
935    /// paid once rather than one name at a time.
936    static BUILTIN_NAMES: BuiltinNames = BuiltinNames {
937        result: Rc::from(RESULT.name),
938        ok: Rc::from(OK_CASE.name),
939        err: Rc::from(ERR_CASE.name),
940        option: Rc::from(OPTION.name),
941        some: Rc::from(SOME_CASE.name),
942        none: Rc::from(NONE_CASE.name),
943        error: Rc::from(ERROR.name),
944        message: Rc::from(MESSAGE_FIELD.name),
945    };
946}
947
948/// The builtin `Option`, `Result`, and `Error` values, built and read through
949/// the one description of what they are made of.
950///
951/// `Ok`, `Err`, `Some`, `None`, and an `Error`'s `message` are declared in
952/// [`cove_schema::builtins`], which is also where `cove-sema` reads them to
953/// check a `match` and to type a pattern's binding. Everything in this
954/// workspace that builds one of these values or asks which case a value is
955/// goes through the constructors and readers below, so the four case names
956/// are stated once and the question "is this an `Ok`?" has one answer.
957impl Value {
958    /// `Ok(value)`
959    pub fn ok(value: Value) -> Value {
960        BUILTIN_NAMES.with(|names| {
961            Value(Repr::Enum(Box::new(EnumValue {
962                type_name: names.result.clone(),
963                case: names.ok.clone(),
964                payload: Payload::One(value),
965            })))
966        })
967    }
968
969    /// `Err(error)`
970    pub fn err(error: Value) -> Value {
971        BUILTIN_NAMES.with(|names| {
972            Value(Repr::Enum(Box::new(EnumValue {
973                type_name: names.result.clone(),
974                case: names.err.clone(),
975                payload: Payload::One(error),
976            })))
977        })
978    }
979
980    /// `Some(value)`
981    pub fn some(value: Value) -> Value {
982        BUILTIN_NAMES.with(|names| {
983            Value(Repr::Enum(Box::new(EnumValue {
984                type_name: names.option.clone(),
985                case: names.some.clone(),
986                payload: Payload::One(value),
987            })))
988        })
989    }
990
991    /// `None`
992    pub fn none() -> Value {
993        BUILTIN_NAMES.with(|names| {
994            Value(Repr::Enum(Box::new(EnumValue {
995                type_name: names.option.clone(),
996                case: names.none.clone(),
997                payload: Payload::Empty,
998            })))
999        })
1000    }
1001
1002    /// The builtin `Error` struct.
1003    pub fn error(message: impl Into<String>) -> Value {
1004        let message = Value(Repr::Str(message.into().into()));
1005        BUILTIN_NAMES.with(|names| {
1006            Value(Repr::Struct(Rc::new(StructValue {
1007                type_name: names.error.clone(),
1008                fields: vec![(names.message.clone(), message)],
1009                opaque: false,
1010            })))
1011        })
1012    }
1013
1014    /// A value of the declared struct type `type_name`, carrying `fields` in
1015    /// declaration order.
1016    ///
1017    /// `type_name` is the qualified name the declaring module gives it, such
1018    /// as `rules.policy.PullRequest`: that is the name every value of a
1019    /// declared type carries, and the name an invocation and the Host API
1020    /// boundary both check against.
1021    ///
1022    /// This exists so that a host building an argument for
1023    /// [`Vm::invoke`](crate::Vm::invoke) does not have to name
1024    /// [`StructValue`]'s layout to do it — the `Rc`, the field vector, and in
1025    /// particular `opaque`, which records that the *declaration* said `export
1026    /// opaque struct` (ADR 0014) and is therefore not a thing a caller has an
1027    /// answer for. Issue #109 asks that the internal representation become
1028    /// less exposed to embedders; this is one place it was exposed for no
1029    /// reason.
1030    pub fn structure<N: Into<Rc<str>>>(
1031        type_name: impl Into<Rc<str>>,
1032        fields: impl IntoIterator<Item = (N, Value)>,
1033    ) -> Value {
1034        Value(Repr::Struct(Rc::new(StructValue {
1035            type_name: type_name.into(),
1036            fields: fields
1037                .into_iter()
1038                .map(|(name, value)| (name.into(), value))
1039                .collect(),
1040            opaque: false,
1041        })))
1042    }
1043
1044    /// A value of the declared enum type `type_name`, in the case `case`,
1045    /// carrying `payload` in the order the case declares it.
1046    ///
1047    /// The companion of [`Value::structure`] for the other declared shape.
1048    /// [`Value::ok`] and the three beside it build the *builtin* enums, whose
1049    /// case names come from `cove_schema::builtins` and are not a caller's to
1050    /// choose; this one takes both names because a package's own enum is a
1051    /// package's own.
1052    pub fn enumeration(
1053        type_name: impl Into<Rc<str>>,
1054        case: impl Into<Rc<str>>,
1055        payload: impl IntoIterator<Item = Value>,
1056    ) -> Value {
1057        Value(Repr::Enum(Box::new(EnumValue {
1058            type_name: type_name.into(),
1059            case: case.into(),
1060            payload: payload.into_iter().collect(),
1061        })))
1062    }
1063
1064    /// An `Array` holding `items`, in order.
1065    ///
1066    /// The companion of [`Value::structure`], and there for the same reason: a
1067    /// host that builds an array should not have to know that the elements are
1068    /// stored behind a shared pointer to a slice.
1069    pub fn array(items: impl IntoIterator<Item = Value>) -> Value {
1070        Value(Repr::Array(items.into_iter().collect()))
1071    }
1072
1073    /// A `Set` holding `items`.
1074    ///
1075    /// The elements are [`MapKey`]s and not [`Value`]s, and that is the
1076    /// [`MapKey`] restriction showing through rather than an inconvenience: a
1077    /// set of values would be a constructor that could fail, and there is
1078    /// nothing sensible for it to do when it does. A host building one from
1079    /// its own data writes the key it means — `MapKey::Str(name)` for a set of
1080    /// names — and a host holding a [`Value`] it did not build converts with
1081    /// [`MapKey::from_value`], which reports the part that cannot be a key and
1082    /// the path to reach it.
1083    ///
1084    /// Duplicates collapse, exactly as they do for a `Set` a Cove program
1085    /// builds, and the order the set iterates in is ascending key order
1086    /// whatever order they arrived in.
1087    pub fn set(items: impl IntoIterator<Item = MapKey>) -> Value {
1088        Value(Repr::Set(Rc::new(items.into_iter().collect())))
1089    }
1090
1091    /// A `Map` holding `entries`.
1092    ///
1093    /// The companion of [`Value::set`], with the same reason for taking a
1094    /// [`MapKey`]: only the key carries the restriction, so the value half is
1095    /// an ordinary [`Value`]. A later entry under a key an earlier one used
1096    /// replaces it.
1097    pub fn map(entries: impl IntoIterator<Item = (MapKey, Value)>) -> Value {
1098        Value(Repr::Map(Rc::new(entries.into_iter().collect())))
1099    }
1100
1101    /// `()`, the value a statement and a function with no result answer.
1102    pub fn unit() -> Value {
1103        Value(Repr::Unit)
1104    }
1105
1106    /// The `Bool` `b`.
1107    pub fn bool(b: bool) -> Value {
1108        Value(Repr::Bool(b))
1109    }
1110
1111    /// The `Int` `n`.
1112    ///
1113    /// A full sixty-four bits, because an `Int` is one: issue #109 measured
1114    /// the alternatives that are not, and NaN boxing and pointer tagging are
1115    /// refused rather than deferred because neither can hold every `Int` and
1116    /// every `Float` at once.
1117    pub fn int(n: i64) -> Value {
1118        Value(Repr::Int(n))
1119    }
1120
1121    /// The `Float` `x`, including every NaN and both zeroes.
1122    pub fn float(x: f64) -> Value {
1123        Value(Repr::Float(x))
1124    }
1125
1126    /// The `Duration` of `nanos` nanoseconds.
1127    ///
1128    /// Nanoseconds rather than a [`std::time::Duration`], for the reason
1129    /// [`Value::as_duration_nanos`] gives on the way out: a Cove duration is
1130    /// a *signed* count of them, and `-1s` is an ordinary value that
1131    /// `std::time::Duration` cannot hold.
1132    pub fn duration(nanos: i64) -> Value {
1133        Value(Repr::Duration(nanos))
1134    }
1135
1136    /// The `String` `text`.
1137    ///
1138    /// Named for the Cove type and not for Rust's, which is why it takes
1139    /// anything a string can be made from rather than a `String`
1140    /// specifically: `Value::string("hi")` copies the characters once and
1141    /// says nothing about where they end up.
1142    pub fn string(text: impl Into<Rc<str>>) -> Value {
1143        Value(Repr::Str(text.into()))
1144    }
1145
1146    /// The range `start..end`, or `start..<end` when `inclusive_end` is
1147    /// false.
1148    ///
1149    /// Both bounds as source writes them, rather than the normalised
1150    /// half-open pair [`Value::range`] answers with: `1..3` and `1..<4` cover
1151    /// the same integers and are still two different values, since `==`
1152    /// compares the bounds a range was written with.
1153    ///
1154    /// The name is `range_of` and not `range` because the reader took
1155    /// `range`, and the readers are what issue #195 shipped.
1156    pub fn range_of(start: i64, end: i64, inclusive_end: bool) -> Value {
1157        Value(Repr::Range {
1158            start,
1159            end,
1160            inclusive_end,
1161        })
1162    }
1163
1164    /// A handle to a resource the host owns, such as a database connection.
1165    ///
1166    /// The companion of [`Value::resource`], and it takes the whole handle
1167    /// because ADR 0013 decides that a handle *is* a name and every field of
1168    /// it is part of that name. What it hides is the shared pointer, which is
1169    /// there so a handle can cross into a task when its schema allows it —
1170    /// pass either a [`ResourceHandle`] or the `Arc` that
1171    /// [`ResourceHandle::new`](crate::host::ResourceHandle::new) answers.
1172    ///
1173    /// The name is `from_resource` and not `resource` because the reader took
1174    /// `resource`.
1175    pub fn from_resource(handle: impl Into<Arc<ResourceHandle>>) -> Value {
1176        Value(Repr::Resource(handle.into()))
1177    }
1178
1179    /// A bound host operation, such as `console.println`.
1180    ///
1181    /// The companion of [`Value::host_op`]. Two names and not an
1182    /// implementation: what they name is found in the registry at the call.
1183    pub fn host_fn(module: impl Into<Rc<str>>, op: impl Into<Rc<str>>) -> Value {
1184        Value(Repr::HostFn(Rc::new(HostFnValue {
1185            module: module.into(),
1186            op: op.into(),
1187        })))
1188    }
1189
1190    /// A bound host module, such as `console`.
1191    pub fn host_module(name: impl Into<Rc<str>>) -> Value {
1192        Value(Repr::HostModule(name.into()))
1193    }
1194
1195    /// A type used as a value, such as `Vector` in `Vector.of(1, 2)`.
1196    ///
1197    /// The name is `type_value` and not `type_name` because
1198    /// [`Value::type_name`] answers the name of the type a value *is*, which
1199    /// is a different question asked of every value rather than of this one.
1200    pub fn type_value(name: impl Into<Rc<str>>) -> Value {
1201        Value(Repr::Type(name.into()))
1202    }
1203
1204    /// Whether this is an `Ok`, the success case of a `Result`.
1205    pub fn is_ok(&self) -> bool {
1206        self.builtin_case(&RESULT, &OK_CASE).is_some()
1207    }
1208
1209    /// Whether this is an `Err`.
1210    pub fn is_err(&self) -> bool {
1211        self.builtin_case(&RESULT, &ERR_CASE).is_some()
1212    }
1213
1214    /// Whether this is a `Some`.
1215    pub fn is_some(&self) -> bool {
1216        self.builtin_case(&OPTION, &SOME_CASE).is_some()
1217    }
1218
1219    /// What an `Ok` carries, when this is one.
1220    ///
1221    /// The payload is a slice rather than a value because what a caller does
1222    /// with an empty one differs: the `?` operator answers `()` and a
1223    /// diagnostic answers nothing at all. The schema says an `Ok` carries
1224    /// exactly one value, so an empty one is a host that broke its word.
1225    pub fn ok_payload(&self) -> Option<&[Value]> {
1226        self.builtin_case(&RESULT, &OK_CASE)
1227            .map(|case| case.payload.as_slice())
1228    }
1229
1230    /// What an `Err` carries, when this is one.
1231    pub fn err_payload(&self) -> Option<&[Value]> {
1232        self.builtin_case(&RESULT, &ERR_CASE)
1233            .map(|case| case.payload.as_slice())
1234    }
1235
1236    /// What a `Some` carries, when this is one.
1237    pub fn some_payload(&self) -> Option<&[Value]> {
1238        self.builtin_case(&OPTION, &SOME_CASE)
1239            .map(|case| case.payload.as_slice())
1240    }
1241
1242    /// The `message` a builtin `Error` carries, when this is one.
1243    pub fn error_message(&self) -> Option<&Value> {
1244        match self {
1245            Value(Repr::Struct(value)) if &*value.type_name == ERROR.name => {
1246                value.get(MESSAGE_FIELD.name)
1247            }
1248            _ => None,
1249        }
1250    }
1251
1252    /// This value as `case` of the builtin enum `schema`, when it is one.
1253    ///
1254    /// Both halves of the question are asked here: a user enum may declare a
1255    /// case called `Ok`, and it is not this one.
1256    fn builtin_case(&self, schema: &BuiltinSchema, case: &CaseSchema) -> Option<&EnumValue> {
1257        match self {
1258            Value(Repr::Enum(value))
1259                if &*value.type_name == schema.name && &*value.case == case.name =>
1260            {
1261                Some(value)
1262            }
1263            _ => None,
1264        }
1265    }
1266
1267    /// The name shown in diagnostics.
1268    /// Whether `other` is a value of the same type as this one, without
1269    /// naming either type.
1270    ///
1271    /// `==` has to refuse a comparison between two types before it compares
1272    /// two values, and it asked that question by building both type names and
1273    /// comparing the strings. Two allocations per comparison is a great deal
1274    /// to pay for an answer that is a discriminant check and, for the two
1275    /// declared kinds, one string comparison — and a parser compares
1276    /// characters constantly, so this was measurable (issue #104). The names
1277    /// are still built for the diagnostic, which happens once.
1278    pub fn same_type_as(&self, other: &Value) -> bool {
1279        match (self, other) {
1280            (Value(Repr::Struct(left)), Value(Repr::Struct(right))) => {
1281                left.type_name == right.type_name
1282            }
1283            (Value(Repr::Enum(left)), Value(Repr::Enum(right))) => {
1284                left.type_name == right.type_name
1285            }
1286            (Value(Repr::Dyn(left)), Value(Repr::Dyn(right))) => {
1287                left.trait_name == right.trait_name
1288            }
1289            (Value(Repr::Resource(left)), Value(Repr::Resource(right))) => {
1290                left.module == right.module && left.type_name == right.type_name
1291            }
1292            (Value(Repr::HostModule(left)), Value(Repr::HostModule(right))) => left == right,
1293            (Value(Repr::HostFn(left)), Value(Repr::HostFn(right))) => {
1294                left.module == right.module && left.op == right.op
1295            }
1296            (Value(Repr::Type(left)), Value(Repr::Type(right))) => left == right,
1297            // Everything else is one type per variant, so the discriminants
1298            // answering the same is the whole of the question.
1299            _ => std::mem::discriminant(&self.0) == std::mem::discriminant(&other.0),
1300        }
1301    }
1302
1303    /// The name of the declared type this value is of, for a struct or an
1304    /// enum, and `None` for everything else.
1305    ///
1306    /// A method declared in a package can only ever be found on one of those
1307    /// two, so this is what receiver dispatch asks rather than
1308    /// [`Value::type_name`]: no name is built at all for the receivers that
1309    /// have none, and a declared one hands back the name it already holds.
1310    ///
1311    /// **A `Some` here is not a declared type.** The builtin `Option` and
1312    /// `Result` are `Repr::Enum` as well, and answer their own bare names —
1313    /// `Option`, with no module in front. A caller asking "is this a
1314    /// declared type" has to look for the dot; a caller that read `is_some`
1315    /// as the answer got two builtins wrong.
1316    pub fn declared_type_name(&self) -> Option<&Rc<str>> {
1317        match self {
1318            Value(Repr::Struct(value)) => Some(&value.type_name),
1319            Value(Repr::Enum(value)) => Some(&value.type_name),
1320            _ => None,
1321        }
1322    }
1323
1324    pub fn type_name(&self) -> String {
1325        match self {
1326            Value(Repr::Unit) => "Unit".into(),
1327            Value(Repr::Bool(_)) => "Bool".into(),
1328            Value(Repr::Int(_)) => "Int".into(),
1329            Value(Repr::Float(_)) => "Float".into(),
1330            Value(Repr::Duration(_)) => "Duration".into(),
1331            Value(Repr::Str(_)) => "String".into(),
1332            Value(Repr::Array(_)) => "Array".into(),
1333            Value(Repr::Vector(_)) => "Vector".into(),
1334            Value(Repr::Map(_)) => "Map".into(),
1335            Value(Repr::Set(_)) => "Set".into(),
1336            Value(Repr::Struct(s)) => s.type_name.to_string(),
1337            Value(Repr::Enum(e)) => e.type_name.to_string(),
1338            Value(Repr::Closure(_)) => "fn".into(),
1339            Value(Repr::Dyn(d)) => format!("dyn {}", d.trait_name),
1340            Value(Repr::HostModule(m)) => format!("host module `{m}`"),
1341            Value(Repr::Resource(handle)) => handle.qualified_type(),
1342            Value(Repr::HostFn(host)) => {
1343                format!("host operation `{}.{}`", host.module, host.op)
1344            }
1345            Value(Repr::Type(t)) => format!("type `{t}`"),
1346            Value(Repr::Range { .. }) => "Range".into(),
1347            Value(Repr::TaskScope(_)) => "TaskScope".into(),
1348            Value(Repr::Task(_)) => "Task".into(),
1349            Value(Repr::Shared(_)) => "Shared".into(),
1350        }
1351    }
1352
1353    /// The value a trait object holds, or this value when it is not one.
1354    ///
1355    /// A `dyn Trait` wrapper records where a value was converted, and the
1356    /// checker decides where that is: a written type converts and a lambda's
1357    /// inferred result does not, though both have type `dyn Trait`. Nothing
1358    /// a program can ask should be able to tell those two apart, so
1359    /// everything that compares, renders, or keys a value looks through the
1360    /// wrapper first.
1361    pub fn erased(&self) -> &Value {
1362        match self {
1363            Value(Repr::Dyn(d)) => d.value.erased(),
1364            other => other,
1365        }
1366    }
1367
1368    /// Value equality. Identity, when available, is explicit and separate.
1369    pub fn eq_value(&self, other: &Value) -> bool {
1370        match (self.erased(), other.erased()) {
1371            (Value(Repr::Unit), Value(Repr::Unit)) => true,
1372            (Value(Repr::Bool(a)), Value(Repr::Bool(b))) => a == b,
1373            (Value(Repr::Int(a)), Value(Repr::Int(b))) => a == b,
1374            (Value(Repr::Float(a)), Value(Repr::Float(b))) => a == b,
1375            (Value(Repr::Duration(a)), Value(Repr::Duration(b))) => a == b,
1376            (Value(Repr::Str(a)), Value(Repr::Str(b))) => a == b,
1377            (Value(Repr::Array(a)), Value(Repr::Array(b))) => {
1378                a.len() == b.len() && a.iter().zip(b.iter()).all(|(x, y)| x.eq_value(y))
1379            }
1380            // Both sides are `BTreeMap`s keyed the same way, so two maps with
1381            // the same keys line up entry-for-entry once both are in their
1382            // one true ascending order.
1383            (Value(Repr::Map(a)), Value(Repr::Map(b))) => {
1384                a.len() == b.len()
1385                    && a.iter()
1386                        .zip(b.iter())
1387                        .all(|((ka, va), (kb, vb))| ka == kb && va.eq_value(vb))
1388            }
1389            // `BTreeSet<MapKey>` already compares as a set of keys.
1390            (Value(Repr::Set(a)), Value(Repr::Set(b))) => a == b,
1391            (Value(Repr::Struct(a)), Value(Repr::Struct(b))) => {
1392                a.type_name == b.type_name
1393                    && a.fields.len() == b.fields.len()
1394                    && a.fields
1395                        .iter()
1396                        .zip(b.fields.iter())
1397                        .all(|((_, x), (_, y))| x.eq_value(y))
1398            }
1399            (Value(Repr::Enum(a)), Value(Repr::Enum(b))) => {
1400                a.type_name == b.type_name
1401                    && a.case == b.case
1402                    && a.payload.len() == b.payload.len()
1403                    && a.payload
1404                        .iter()
1405                        .zip(b.payload.iter())
1406                        .all(|(x, y)| x.eq_value(y))
1407            }
1408            // Ranges compare by the bounds they were written with, so `0..<3`
1409            // and `0..2` are distinct values even though they yield the same
1410            // integers.
1411            (
1412                Value(Repr::Range {
1413                    start: a,
1414                    end: b,
1415                    inclusive_end: a_inclusive,
1416                }),
1417                Value(Repr::Range {
1418                    start: c,
1419                    end: d,
1420                    inclusive_end: b_inclusive,
1421                }),
1422            ) => a == c && b == d && a_inclusive == b_inclusive,
1423            // Two handles are equal when they name the same resource. A
1424            // handle has no contents to compare, so naming the same thing is
1425            // the whole of being the same value.
1426            (Value(Repr::Resource(a)), Value(Repr::Resource(b))) => a.names_same(b),
1427            // `==` means value equality regardless of mutability, so `Vector`
1428            // compares its current elements structurally, exactly like
1429            // `Array`. Storage identity — whether two handles are the same
1430            // growable buffer — is the separate question `is` answers.
1431            (Value(Repr::Vector(a)), Value(Repr::Vector(b))) => {
1432                let a = a.elements.borrow();
1433                let b = b.elements.borrow();
1434                a.len() == b.len() && a.iter().zip(b.iter()).all(|(x, y)| x.eq_value(y))
1435            }
1436            _ => false,
1437        }
1438    }
1439}
1440
1441/// Reading a value without naming its representation.
1442///
1443/// The constructors above — [`Value::structure`], [`Value::enumeration`],
1444/// [`Value::array`], [`Value::set`], [`Value::map`], and the builtin four —
1445/// let a host *build* every shape that crosses the boundary without writing
1446/// an `Rc`, a `Box`, a field vector or the `opaque` flag. These are the other
1447/// half: they let a host *read* the same shapes the same way.
1448///
1449/// Only one half existed, and the missing half cost something every time the
1450/// representation moved. Issue #104 made `Value::Struct` an
1451/// `Rc<StructValue>`; issue #109 put `Value::HostFn`'s two names behind one
1452/// pointer and took every value in the program from forty bytes to
1453/// twenty-four; issue #121 replaced a closure's parameter list with an arity;
1454/// issue #183 replaced an enum payload's `Vec<Value>` with [`Payload`]. Every
1455/// one of those was invisible to a host that only built values and a source
1456/// break for one that read them, because reading meant matching on a variant
1457/// and a match on a variant is a match on the representation. Issue #186 is
1458/// where that was written down, and this is its answer.
1459///
1460/// **A reader borrows.** It hands back a reference into the value it was
1461/// asked about and the caller clones what it means to keep, which is what
1462/// [`Value::ok_payload`] and [`StructValue::get`] already did and what a host
1463/// wants: a conversion into the host's own types reads each part once and
1464/// keeps no `Value` at all. Borrowing is the half of this that constrains
1465/// what can still move, and it constrains it in one direction — every part a
1466/// reader answers with has to be *stored* as the thing it answers with. A
1467/// struct's fields can move behind a different pointer, a shared shape table,
1468/// or an inline arity the way [`Payload`] already did, and none of that is
1469/// visible here; they cannot become values that are *computed* — unpacked
1470/// from a tagged word, decoded lazily, or held under a lock — without these
1471/// signatures changing. A reader that cloned would forbid none of that, and
1472/// would charge every read for the possibility. A `Vector` is where
1473/// the line already falls, and it falls the same way for building: its
1474/// elements are behind a `RefCell` because the language lets an alias write
1475/// them, so there is no borrowing reader for one here and no constructor for
1476/// one above.
1477///
1478/// **A wrong shape answers `None`.** Asking an `Int` for its fields is the
1479/// host's mistake rather than the program's — no Cove code asked for it and
1480/// none can handle it — so it is not a
1481/// [`RuntimeError`](crate::error::RuntimeError); and it is not a panic
1482/// either, because a host converting a value it did not build wants to report
1483/// what arrived instead. [`Value::type_name`] is what names that in the
1484/// report. This is the convention the readers that already existed use:
1485/// [`Value::ok_payload`], [`Value::error_message`] and [`StructValue::get`]
1486/// all answer `None` to the question they were not the right value for.
1487///
1488/// **A reader looks through `dyn Trait`.** Each of these calls
1489/// [`Value::erased`] first, for the reason that method gives: the wrapper
1490/// records where a value was converted, nothing a program can ask should be
1491/// able to tell a written `dyn Trait` from a lambda's inferred one, and
1492/// [`fmt::Display`] already looks through it — "the wrapper is a
1493/// representation, not something the program put there". There is no reader
1494/// for the wrapper itself, which matches the constructors, none of which can
1495/// build one.
1496impl Value {
1497    /// The `Bool` this is.
1498    pub fn as_bool(&self) -> Option<bool> {
1499        match self.erased() {
1500            Value(Repr::Bool(b)) => Some(*b),
1501            _ => None,
1502        }
1503    }
1504
1505    /// The `Int` this is.
1506    ///
1507    /// A full sixty-four bits, because an `Int` is one and overflow is a
1508    /// broken invariant rather than a wrap.
1509    pub fn as_int(&self) -> Option<i64> {
1510        match self.erased() {
1511            Value(Repr::Int(n)) => Some(*n),
1512            _ => None,
1513        }
1514    }
1515
1516    /// The `Float` this is.
1517    pub fn as_float(&self) -> Option<f64> {
1518        match self.erased() {
1519            Value(Repr::Float(x)) => Some(*x),
1520            _ => None,
1521        }
1522    }
1523
1524    /// The `Duration` this is, in nanoseconds.
1525    ///
1526    /// Nanoseconds rather than a [`std::time::Duration`], because a Cove
1527    /// duration is a signed count of them: `-1s` is an ordinary value and
1528    /// `std::time::Duration` cannot hold it.
1529    pub fn as_duration_nanos(&self) -> Option<i64> {
1530        match self.erased() {
1531            Value(Repr::Duration(ns)) => Some(*ns),
1532            _ => None,
1533        }
1534    }
1535
1536    /// The `String` this is.
1537    pub fn as_str(&self) -> Option<&str> {
1538        match self.erased() {
1539            Value(Repr::Str(text)) => Some(text),
1540            _ => None,
1541        }
1542    }
1543
1544    /// Whether this is `()`.
1545    pub fn is_unit(&self) -> bool {
1546        matches!(self.erased(), Value(Repr::Unit))
1547    }
1548
1549    /// The declared type this value is of — `rules.policy.Decision`, or
1550    /// `Option` for a builtin — for a struct or an enum, and `None` for
1551    /// everything else.
1552    ///
1553    /// The qualified name [`Value::structure`] and [`Value::enumeration`]
1554    /// take, which is what a host checks an answer against before reading it
1555    /// apart. [`Value::declared_type_name`] answers the same question with
1556    /// the shared handle itself, because the two backends clone it to
1557    /// dispatch a method; this is the reader, and it does not say what the
1558    /// handle is made of.
1559    pub fn declared_type(&self) -> Option<&str> {
1560        self.erased().declared_type_name().map(|name| &**name)
1561    }
1562
1563    /// The field `name` of a struct value.
1564    ///
1565    /// `None` both when this is not a struct and when the struct declares no
1566    /// such field, because a host has the same thing to say about either and
1567    /// [`Value::type_name`] is what says it: "`Int` carries no field
1568    /// `policy`" and "`rules.policy.Decision` carries no field `polciy`" are
1569    /// the same sentence with the name filled in.
1570    pub fn field(&self, name: &str) -> Option<&Value> {
1571        match self.erased() {
1572            Value(Repr::Struct(value)) => value.get(name),
1573            _ => None,
1574        }
1575    }
1576
1577    /// A struct value's fields, in declaration order, and `None` when this is
1578    /// not a struct — which is also how a host asks whether it is one.
1579    ///
1580    /// Declaration order rather than the order anything asked for: it is the
1581    /// order [`Value::structure`] was handed and the order the declaration
1582    /// states, so a host reading a struct positionally reads what a host
1583    /// building one wrote.
1584    ///
1585    /// An `export opaque struct` (ADR 0014) answers here like any other. The
1586    /// flag governs *rendering*, because a `Display` has no idea which module
1587    /// is watching; a host holding the value has already been handed it, and
1588    /// hiding the fields from it would hide them from the very code the
1589    /// module exported the value to.
1590    pub fn fields(&self) -> Option<impl Iterator<Item = (&str, &Value)> + '_> {
1591        match self.erased() {
1592            Value(Repr::Struct(value)) => Some(value.fields.iter().map(|(name, v)| (&**name, v))),
1593            _ => None,
1594        }
1595    }
1596
1597    /// The case of an enum value, such as `Some`, `Err`, or `Require`.
1598    ///
1599    /// The case alone, unqualified, exactly as [`Value::enumeration`] takes
1600    /// it; [`Value::declared_type`] is the other half of the name.
1601    pub fn case(&self) -> Option<&str> {
1602        match self.erased() {
1603            Value(Repr::Enum(value)) => Some(&value.case),
1604            _ => None,
1605        }
1606    }
1607
1608    /// What an enum value's case carries, in the order the case declares it.
1609    ///
1610    /// A slice, and an empty one for a case that carries nothing, for the
1611    /// reason [`Value::ok_payload`] gives: what a caller does with an empty
1612    /// payload differs and only the caller knows which. Those four ask a
1613    /// builtin question — "is this an `Ok`?" — and answer the payload as a
1614    /// consequence; this one is asked of a value whose case the caller reads
1615    /// for itself with [`Value::case`], which is what a package's own enum
1616    /// needs.
1617    pub fn payload(&self) -> Option<&[Value]> {
1618        match self.erased() {
1619            Value(Repr::Enum(value)) => Some(value.payload.as_slice()),
1620            _ => None,
1621        }
1622    }
1623
1624    /// An `Array`'s elements, in order.
1625    ///
1626    /// The companion of [`Value::array`]. A `Vector` answers `None` and that
1627    /// is not an oversight: its elements are behind a `RefCell` because an
1628    /// alias may write them, so nothing can hand out a plain slice of them,
1629    /// and there is no constructor for one either.
1630    /// [`Value::vector_elements`] is how a vector is read — a guard rather
1631    /// than a slice, which is what a part behind a cell can answer with.
1632    pub fn items(&self) -> Option<&[Value]> {
1633        match self.erased() {
1634            Value(Repr::Array(items)) => Some(items),
1635            _ => None,
1636        }
1637    }
1638
1639    /// A `Set`'s elements, in ascending key order.
1640    ///
1641    /// [`MapKey`]s and not [`Value`]s, for the reason [`Value::set`] gives on
1642    /// the way in: the restriction is real, and showing it is better than a
1643    /// reader that pretends a set holds anything. [`MapKey::to_value`]
1644    /// converts one back.
1645    ///
1646    /// Ascending key order whatever order they were inserted in, which is the
1647    /// order a Cove program iterating the same set sees.
1648    pub fn elements(&self) -> Option<impl Iterator<Item = &MapKey> + '_> {
1649        match self.erased() {
1650            Value(Repr::Set(items)) => Some(items.iter()),
1651            _ => None,
1652        }
1653    }
1654
1655    /// A `Map`'s entries, in ascending key order.
1656    ///
1657    /// The companion of [`Value::map`], with the same split: only the key
1658    /// carries the [`MapKey`] restriction, so the value half is an ordinary
1659    /// [`Value`].
1660    pub fn entries(&self) -> Option<impl Iterator<Item = (&MapKey, &Value)> + '_> {
1661        match self.erased() {
1662            Value(Repr::Map(entries)) => Some(entries.iter()),
1663            _ => None,
1664        }
1665    }
1666
1667    /// A `Range`'s bounds, half-open.
1668    ///
1669    /// [`RangeBounds`] rather than the three fields the variant holds,
1670    /// because `..` and `..<` are two ways of writing one range: `1..3` and
1671    /// `1..<4` cover the same integers, and a host asking what a range covers
1672    /// should not have to normalise them itself. The bounds are `i128` so
1673    /// that an inclusive `i64::MAX` end cannot overflow.
1674    pub fn range(&self) -> Option<RangeBounds> {
1675        match *self.erased() {
1676            Value(Repr::Range {
1677                start,
1678                end,
1679                inclusive_end,
1680            }) => Some(RangeBounds::of(start, end, inclusive_end)),
1681            _ => None,
1682        }
1683    }
1684
1685    /// The resource handle this is.
1686    ///
1687    /// [`ResourceHandle`] is the answer rather than something this hides,
1688    /// because ADR 0013 decides that a handle *is* a name: "every field of it
1689    /// is part of the name", and there is no field for state because the
1690    /// state is the host's. What this hides is the `Arc`, which is there so
1691    /// that a handle can cross into a task when its schema allows it.
1692    pub fn resource(&self) -> Option<&ResourceHandle> {
1693        match self.erased() {
1694            Value(Repr::Resource(handle)) => Some(handle),
1695            _ => None,
1696        }
1697    }
1698
1699    /// The module and operation a bound host operation names, such as
1700    /// `("console", "println")`.
1701    ///
1702    /// Two names and not an implementation: a bound host operation is a name
1703    /// the way [`ValueView::HostModule`] is, and what it names is found in the
1704    /// registry at the call. This is the reader for the variant issue #109
1705    /// boxed to buy the sixteen bytes — a host that matched `Value::HostFn {
1706    /// module, op }` had to be rewritten, and one that had called this would
1707    /// not have noticed.
1708    pub fn host_op(&self) -> Option<(&str, &str)> {
1709        match self.erased() {
1710            Value(Repr::HostFn(host)) => Some((&host.module, &host.op)),
1711            _ => None,
1712        }
1713    }
1714
1715    /// How many parameters a closure value declares.
1716    ///
1717    /// Parameters and not arguments a call must supply: a defaulted or a
1718    /// variadic parameter counts like any other. A host that was handed a
1719    /// callback asks this to refuse one of the wrong shape before calling it
1720    /// back through [`Reentry`](crate::host::Reentry), which is the only way
1721    /// to call one, since the body belongs to the backend that made it. This
1722    /// is the reader for the field issue #121 replaced with a count, and it
1723    /// is the whole of a closure a host has any business reading.
1724    pub fn arity(&self) -> Option<usize> {
1725        match self.erased() {
1726            Value(Repr::Closure(closure)) => Some(closure.arity),
1727            _ => None,
1728        }
1729    }
1730
1731    /// A `Vector`'s elements, in order, for as long as the guard is held.
1732    ///
1733    /// The companion of [`Value::items`], which answers `None` for a
1734    /// `Vector` because its elements sit behind a cell — an alias may write
1735    /// them, so nothing can hand out a plain `&[Value]` of them. Issue #196
1736    /// records that as "the one place the borrow-based reader design cannot
1737    /// reach"; ADR 0028 decision 7 is where it is reached, and this is the
1738    /// shape of the answer: a part whose storage will not sit still is handed
1739    /// out as an opaque guard, and the guard is public API.
1740    ///
1741    /// [`Elements`] derefs to `[Value]`, so a host reads a vector the way it
1742    /// reads an array. Holding one *borrows* the vector: drop it before
1743    /// calling back into Cove through
1744    /// [`Reentry`](crate::host::Reentry), because Cove code that writes the
1745    /// same vector while the guard is alive is a panic rather than a data
1746    /// race.
1747    pub fn vector_elements(&self) -> Option<Elements<'_>> {
1748        match self.erased() {
1749            Value(Repr::Vector(storage)) => Some(Elements(storage.elements.borrow())),
1750            _ => None,
1751        }
1752    }
1753
1754    /// The trait a `dyn Trait` value was used at, such as `render.Display`.
1755    ///
1756    /// The one reader that does *not* look through the wrapper, because it is
1757    /// the reader for the wrapper. Every other reader and
1758    /// [`Value::view`] call [`Value::erased`] first, for the reason that
1759    /// method gives — the wrapper is a representation, not something the
1760    /// program put there — so this is how a host that genuinely wants to name
1761    /// the trait in a diagnostic asks for it.
1762    pub fn dyn_trait(&self) -> Option<&str> {
1763        match self {
1764            Value(Repr::Dyn(d)) => Some(&d.trait_name),
1765            _ => None,
1766        }
1767    }
1768
1769    /// Classify this value: what *kind* of Cove value it is, and its parts.
1770    ///
1771    /// O(1), allocates nothing, and borrows from `self`. It looks through
1772    /// `dyn Trait` exactly as every reader beside it does, which is why
1773    /// [`ValueView`] has no `Dyn` variant; [`Value::dyn_trait`] is how a host
1774    /// asks about the wrapper.
1775    ///
1776    /// This is the exhaustive match that sealing takes away, given back
1777    /// deliberately. See [`ValueView`] for what it promises and when it
1778    /// breaks.
1779    ///
1780    /// A `Vector` borrows its elements for as long as the view is held, for
1781    /// the reason [`Value::vector_elements`] gives.
1782    pub fn view(&self) -> ValueView<'_> {
1783        match self.erased() {
1784            Value(Repr::Unit) => ValueView::Unit,
1785            Value(Repr::Bool(b)) => ValueView::Bool(*b),
1786            Value(Repr::Int(n)) => ValueView::Int(*n),
1787            Value(Repr::Float(x)) => ValueView::Float(*x),
1788            Value(Repr::Duration(ns)) => ValueView::Duration(*ns),
1789            Value(Repr::Str(text)) => ValueView::Str(text),
1790            Value(Repr::Array(items)) => ValueView::Array(items),
1791            Value(Repr::Vector(storage)) => ValueView::Vector(Elements(storage.elements.borrow())),
1792            Value(Repr::Map(entries)) => ValueView::Map(Entries(entries)),
1793            Value(Repr::Set(members)) => ValueView::Set(Members(members)),
1794            Value(Repr::Struct(value)) => ValueView::Struct(StructView(value)),
1795            Value(Repr::Enum(value)) => ValueView::Enum(EnumView(value)),
1796            Value(Repr::Closure(closure)) => ValueView::Closure(ClosureView(closure)),
1797            Value(Repr::HostModule(name)) => ValueView::HostModule(name),
1798            Value(Repr::HostFn(host)) => ValueView::HostFn {
1799                module: &host.module,
1800                op: &host.op,
1801            },
1802            Value(Repr::Resource(handle)) => ValueView::Resource(handle),
1803            Value(Repr::Type(name)) => ValueView::Type(name),
1804            Value(Repr::Range {
1805                start,
1806                end,
1807                inclusive_end,
1808            }) => ValueView::Range(RangeBounds::of(*start, *end, *inclusive_end)),
1809            Value(Repr::Task(task)) => ValueView::Task(TaskView(task)),
1810            Value(Repr::TaskScope(scope)) => ValueView::TaskScope(TaskScopeView(scope)),
1811            Value(Repr::Shared(_)) => ValueView::Shared(SharedView(std::marker::PhantomData)),
1812            // `erased` looks through every wrapper, including a wrapper
1813            // holding a wrapper, so control never arrives here.
1814            Value(Repr::Dyn(_)) => unreachable!("`Value::erased` answers no `dyn` wrapper"),
1815        }
1816    }
1817}
1818
1819/// What kind of Cove value this is: the stable public classification, and the
1820/// exhaustive match a host is allowed to write.
1821///
1822/// # Why this exists
1823///
1824/// [`Value`]'s variants are sealed (ADR 0028 decision 6), which takes away a
1825/// real safety property: a host that matched every variant got a compile
1826/// error when a new one arrived. Issue #196 raises exactly that objection.
1827/// This is the answer, and it is a better answer than the thing it replaces,
1828/// because today one enum carries two unrelated kinds of change and a host
1829/// cannot tell them apart. Moving a struct from a `Box` to an `Rc` (issue
1830/// #104) and "Cove has a new kind of value" arrive at a host as the same
1831/// compile error.
1832///
1833/// After this they are different events:
1834///
1835/// - a **representation** change is invisible — nothing here names an `Rc`, a
1836///   `Box`, a slot, a heap object or a tag, so how the runtime holds a value
1837///   may move without a host noticing;
1838/// - a **language** change is a compile error at every `match` — a new kind
1839///   of Cove value is a new variant here, and that is the right way round.
1840///
1841/// # It is exhaustive on purpose
1842///
1843/// This is deliberately **not** `#[non_exhaustive]`, and that is the whole
1844/// point. A `#[non_exhaustive]` view would give back the syntax of an
1845/// exhaustive match and none of its value: every host would carry a `_` arm,
1846/// and the compile error that a new kind of value *should* cause would never
1847/// happen anywhere.
1848///
1849/// The cost is real and is accepted: this is a second place every new kind of
1850/// Cove value must be added, and adding one is a breaking change for every
1851/// embedder. Forgetting is a compile error inside this crate, at
1852/// [`Value::view`], which is the good case.
1853///
1854/// # What it promises
1855///
1856/// Each payload borrows from the value or copies out of it, and building one
1857/// allocates nothing — so every part named here must still be *stored* as the
1858/// thing it answers with. That is a promise about a materialized boundary
1859/// value and not about how the linear-memory backend holds one: ADR 0028
1860/// separates the two, and the parts that will actually move — slots, heap
1861/// objects, dynamic values — are not [`Value`] and never reach here.
1862///
1863/// A part whose storage sits behind a cell is answered as an opaque guard
1864/// rather than a borrow: [`Elements`] is the one that exists, and it is what
1865/// lets `Vector` be viewed at all.
1866///
1867/// There is no `Dyn` variant, because [`Value::view`] looks through the
1868/// wrapper like every reader beside it. [`Value::dyn_trait`] answers the
1869/// trait name for a host that wants it.
1870#[derive(Clone, Debug)]
1871pub enum ValueView<'a> {
1872    /// `()`
1873    Unit,
1874    Bool(bool),
1875    Int(i64),
1876    Float(f64),
1877    /// A duration in nanoseconds, signed, exactly as
1878    /// [`Value::as_duration_nanos`] answers it.
1879    Duration(i64),
1880    Str(&'a str),
1881    /// A fixed-length immutable sequence.
1882    Array(&'a [Value]),
1883    /// A growable sequence, borrowed for as long as the view is held.
1884    Vector(Elements<'a>),
1885    Map(Entries<'a>),
1886    Set(Members<'a>),
1887    Struct(StructView<'a>),
1888    /// An enum value, including `Option` and `Result`.
1889    Enum(EnumView<'a>),
1890    /// A callback. A host calls one back through
1891    /// [`Reentry`](crate::host::Reentry) and never directly, since the body
1892    /// belongs to the backend that made it.
1893    Closure(ClosureView<'a>),
1894    /// A bound host module such as `console`.
1895    HostModule(&'a str),
1896    /// A bound host operation such as `console.println`.
1897    HostFn {
1898        /// The host module, such as `console`.
1899        module: &'a str,
1900        /// The operation's own name, such as `println`.
1901        op: &'a str,
1902    },
1903    /// A handle to a resource the host owns. ADR 0013 decides that the handle
1904    /// is a name and that every field of it is part of that name, which is
1905    /// why the whole of it is the answer.
1906    Resource(&'a ResourceHandle),
1907    /// A type used as a value, such as `Vector` in `Vector.of(1, 2)`.
1908    Type(&'a str),
1909    /// An integer range, normalised to half-open bounds.
1910    Range(RangeBounds),
1911    /// A handle to a spawned task. Its value is reachable only through
1912    /// `await` or through the scope settling it.
1913    Task(TaskView<'a>),
1914    /// The scope `scope tasks { ... }` binds.
1915    TaskScope(TaskScopeView<'a>),
1916    /// Mutable state more than one task may reach. Its contents are reachable
1917    /// only through `lock`, so there is nothing here to read.
1918    Shared(SharedView<'a>),
1919}
1920
1921/// A `Vector`'s elements, borrowed.
1922///
1923/// Reads as `[Value]`, so a host reads a vector the way it reads an array:
1924/// `elements.len()`, `elements[0]`, `for value in &elements`.
1925///
1926/// It is a guard and not a slice because the elements sit behind a cell — the
1927/// language lets an alias write them — and a guard is ADR 0028's general
1928/// answer for a part whose storage will not sit still. Holding one borrows
1929/// the vector, so drop it before letting Cove code write the same vector.
1930pub struct Elements<'a>(std::cell::Ref<'a, Vec<Value>>);
1931
1932impl Clone for Elements<'_> {
1933    /// Another guard onto the same elements, which is a second shared borrow
1934    /// and never a copy of them.
1935    fn clone(&self) -> Self {
1936        Elements(std::cell::Ref::clone(&self.0))
1937    }
1938}
1939
1940impl std::ops::Deref for Elements<'_> {
1941    type Target = [Value];
1942
1943    fn deref(&self) -> &[Value] {
1944        &self.0
1945    }
1946}
1947
1948impl fmt::Debug for Elements<'_> {
1949    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1950        fmt::Debug::fmt(&*self.0, f)
1951    }
1952}
1953
1954impl<'a, 'b> IntoIterator for &'b Elements<'a> {
1955    type Item = &'b Value;
1956    type IntoIter = std::slice::Iter<'b, Value>;
1957
1958    fn into_iter(self) -> Self::IntoIter {
1959        self.iter()
1960    }
1961}
1962
1963/// A `Map`'s entries, in ascending key order.
1964///
1965/// Opaque so that the key-ordered storage behind it stays the runtime's
1966/// business; what it promises is the order, which is the order a Cove program
1967/// iterating the same map sees.
1968#[derive(Clone, Copy, Debug)]
1969pub struct Entries<'a>(&'a BTreeMap<MapKey, Value>);
1970
1971impl<'a> Entries<'a> {
1972    /// How many entries the map holds.
1973    pub fn len(self) -> usize {
1974        self.0.len()
1975    }
1976
1977    /// Whether the map holds none.
1978    pub fn is_empty(self) -> bool {
1979        self.0.is_empty()
1980    }
1981
1982    /// What `key` maps to, if anything.
1983    pub fn get(self, key: &MapKey) -> Option<&'a Value> {
1984        self.0.get(key)
1985    }
1986
1987    /// The entries, in ascending key order.
1988    pub fn iter(self) -> impl Iterator<Item = (&'a MapKey, &'a Value)> {
1989        self.0.iter()
1990    }
1991}
1992
1993impl<'a> IntoIterator for Entries<'a> {
1994    type Item = (&'a MapKey, &'a Value);
1995    type IntoIter = std::collections::btree_map::Iter<'a, MapKey, Value>;
1996
1997    fn into_iter(self) -> Self::IntoIter {
1998        self.0.iter()
1999    }
2000}
2001
2002/// A `Set`'s elements, in ascending key order.
2003///
2004/// [`MapKey`]s and not [`Value`]s, for the reason [`Value::set`] gives on the
2005/// way in: the restriction is real, and showing it is better than pretending
2006/// a set holds anything.
2007#[derive(Clone, Copy, Debug)]
2008pub struct Members<'a>(&'a BTreeSet<MapKey>);
2009
2010impl<'a> Members<'a> {
2011    /// How many elements the set holds.
2012    pub fn len(self) -> usize {
2013        self.0.len()
2014    }
2015
2016    /// Whether the set holds none.
2017    pub fn is_empty(self) -> bool {
2018        self.0.is_empty()
2019    }
2020
2021    /// Whether `member` is one of them.
2022    pub fn contains(self, member: &MapKey) -> bool {
2023        self.0.contains(member)
2024    }
2025
2026    /// The elements, in ascending key order.
2027    pub fn iter(self) -> impl Iterator<Item = &'a MapKey> {
2028        self.0.iter()
2029    }
2030}
2031
2032impl<'a> IntoIterator for Members<'a> {
2033    type Item = &'a MapKey;
2034    type IntoIter = std::collections::btree_set::Iter<'a, MapKey>;
2035
2036    fn into_iter(self) -> Self::IntoIter {
2037        self.0.iter()
2038    }
2039}
2040
2041/// A struct value's name and fields.
2042#[derive(Clone, Copy, Debug)]
2043pub struct StructView<'a>(&'a StructValue);
2044
2045impl<'a> StructView<'a> {
2046    /// The qualified name of the declared type, such as
2047    /// `rules.policy.PullRequest` — the name [`Value::structure`] takes.
2048    pub fn type_name(self) -> &'a str {
2049        &self.0.type_name
2050    }
2051
2052    /// The field `name`, or `None` when the struct declares no such field.
2053    pub fn field(self, name: &str) -> Option<&'a Value> {
2054        self.0.get(name)
2055    }
2056
2057    /// The fields, in declaration order.
2058    pub fn fields(self) -> impl Iterator<Item = (&'a str, &'a Value)> {
2059        self.0.fields.iter().map(|(name, value)| (&**name, value))
2060    }
2061
2062    /// How many fields the struct declares.
2063    pub fn len(self) -> usize {
2064        self.0.fields.len()
2065    }
2066
2067    /// Whether the struct declares no fields at all.
2068    pub fn is_empty(self) -> bool {
2069        self.0.fields.is_empty()
2070    }
2071
2072    /// Whether the declaration said `export opaque struct` (ADR 0014), which
2073    /// governs how the value *renders* and nothing else.
2074    ///
2075    /// The fields are readable here whatever this answers, for the reason
2076    /// [`Value::fields`] gives: a host holding the value has already been
2077    /// handed it.
2078    pub fn is_opaque(self) -> bool {
2079        self.0.opaque
2080    }
2081}
2082
2083/// An enum value's name, case, and payload.
2084#[derive(Clone, Copy, Debug)]
2085pub struct EnumView<'a>(&'a EnumValue);
2086
2087impl<'a> EnumView<'a> {
2088    /// The qualified name of the declared type, or `Option` / `Result` for
2089    /// the builtins.
2090    pub fn type_name(self) -> &'a str {
2091        &self.0.type_name
2092    }
2093
2094    /// The case, unqualified: `Some`, `Err`, `Require`.
2095    pub fn case(self) -> &'a str {
2096        &self.0.case
2097    }
2098
2099    /// What the case carries, in the order the case declares it, and an empty
2100    /// slice for a case that carries nothing.
2101    pub fn payload(self) -> &'a [Value] {
2102        self.0.payload.as_slice()
2103    }
2104}
2105
2106/// What a host may read of a callback.
2107///
2108/// The body is not here and cannot be: the interpreter walks a tree and the
2109/// VM runs a lowered function, and calling one is
2110/// [`Reentry`](crate::host::Reentry)'s job because only the backend that made
2111/// a closure can run it.
2112#[derive(Clone, Copy, Debug)]
2113pub struct ClosureView<'a>(&'a Closure);
2114
2115impl ClosureView<'_> {
2116    /// How many parameters the closure declares — parameters, not arguments a
2117    /// call must supply, so a defaulted or a variadic one counts like any
2118    /// other.
2119    pub fn arity(self) -> usize {
2120        self.0.arity
2121    }
2122
2123    /// Whether it was declared `async`.
2124    pub fn is_async(self) -> bool {
2125        self.0.is_async
2126    }
2127}
2128
2129/// What a host may read of a task handle.
2130#[derive(Clone, Copy, Debug)]
2131pub struct TaskView<'a>(&'a Task);
2132
2133impl<'a> TaskView<'a> {
2134    /// Trace identity, unique across the run.
2135    pub fn id(self) -> u64 {
2136        self.0.id
2137    }
2138
2139    /// The name of the scope that owns the task.
2140    pub fn scope(self) -> &'a str {
2141        &self.0.scope
2142    }
2143
2144    /// Position in spawn order within that scope, counting from one.
2145    pub fn position(self) -> usize {
2146        self.0.position
2147    }
2148}
2149
2150/// What a host may read of a task scope.
2151#[derive(Clone, Copy, Debug)]
2152pub struct TaskScopeView<'a>(&'a TaskScope);
2153
2154impl<'a> TaskScopeView<'a> {
2155    /// The name the scope is bound to.
2156    pub fn name(self) -> &'a str {
2157        &self.0.name
2158    }
2159}
2160
2161/// A `Shared` cell, which has nothing readable on it.
2162///
2163/// Its contents are reachable only through `lock`, and showing them here
2164/// would be a read outside one — the single thing the type exists to prevent.
2165/// The variant is in [`ValueView`] so that a host can *tell* a `Shared` from
2166/// everything else, which is all a host can do with one.
2167///
2168/// It carries the borrow and no accessor, so the cell it was made from is not
2169/// reachable through it — deliberately, since reaching it is what `lock` is
2170/// for.
2171#[derive(Clone, Copy, Debug)]
2172pub struct SharedView<'a>(std::marker::PhantomData<&'a SharedCell>);
2173
2174/// How a value appears inside string interpolation and `console.println`.
2175impl fmt::Display for Value {
2176    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2177        match self {
2178            Value(Repr::Unit) => f.write_str("()"),
2179            Value(Repr::Bool(b)) => write!(f, "{b}"),
2180            Value(Repr::Int(i)) => write!(f, "{i}"),
2181            Value(Repr::Float(x)) => write_float(f, *x),
2182            Value(Repr::Duration(ns)) => write_duration(f, *ns),
2183            Value(Repr::Str(s)) => f.write_str(s),
2184            Value(Repr::Array(items)) => {
2185                f.write_str("[")?;
2186                for (i, item) in items.iter().enumerate() {
2187                    if i > 0 {
2188                        f.write_str(", ")?;
2189                    }
2190                    write!(f, "{item}")?;
2191                }
2192                f.write_str("]")
2193            }
2194            Value(Repr::Vector(storage)) => {
2195                f.write_str("[")?;
2196                for (i, item) in storage.elements.borrow().iter().enumerate() {
2197                    if i > 0 {
2198                        f.write_str(", ")?;
2199                    }
2200                    write!(f, "{item}")?;
2201                }
2202                f.write_str("]")
2203            }
2204            Value(Repr::Map(entries)) => {
2205                f.write_str("{")?;
2206                for (i, (k, v)) in entries.iter().enumerate() {
2207                    if i > 0 {
2208                        f.write_str(", ")?;
2209                    }
2210                    write!(f, "{k}: {v}")?;
2211                }
2212                f.write_str("}")
2213            }
2214            Value(Repr::Set(items)) => {
2215                f.write_str("{")?;
2216                for (i, item) in items.iter().enumerate() {
2217                    if i > 0 {
2218                        f.write_str(", ")?;
2219                    }
2220                    write!(f, "{item}")?;
2221                }
2222                f.write_str("}")
2223            }
2224            Value(Repr::Struct(s)) => {
2225                if &*s.type_name == ERROR.name {
2226                    return match s.get(MESSAGE_FIELD.name) {
2227                        Some(Value(Repr::Str(m))) => f.write_str(m),
2228                        _ => f.write_str(ERROR.name),
2229                    };
2230                }
2231                let short = s.type_name.rsplit('.').next().unwrap_or(&s.type_name);
2232                // An opaque type renders as its name and nothing else. Its
2233                // fields are the module's own business, and a rendering is
2234                // read by whoever the string reaches, so showing them here
2235                // would publish through `println` what the checker refuses
2236                // to publish through a field access.
2237                if s.opaque {
2238                    return f.write_str(short);
2239                }
2240                write!(f, "{short}(")?;
2241                for (i, (name, value)) in s.fields.iter().enumerate() {
2242                    if i > 0 {
2243                        f.write_str(", ")?;
2244                    }
2245                    write!(f, "{name}: {value}")?;
2246                }
2247                f.write_str(")")
2248            }
2249            Value(Repr::Enum(e)) => {
2250                f.write_str(&e.case)?;
2251                if !e.payload.is_empty() {
2252                    f.write_str("(")?;
2253                    for (i, value) in e.payload.iter().enumerate() {
2254                        if i > 0 {
2255                            f.write_str(", ")?;
2256                        }
2257                        write!(f, "{value}")?;
2258                    }
2259                    f.write_str(")")?;
2260                }
2261                Ok(())
2262            }
2263            // A trait object shows the value it holds: the wrapper is a
2264            // representation, not something the program put there.
2265            Value(Repr::Dyn(d)) => write!(f, "{}", d.value),
2266            Value(Repr::Closure(_)) => f.write_str("<fn>"),
2267            Value(Repr::HostModule(m)) => write!(f, "<host module {m}>"),
2268            // A handle prints as what it names, identity included: two
2269            // connections are told apart by the number the host issued and
2270            // by nothing else.
2271            Value(Repr::Resource(handle)) => write!(f, "<{}>", handle),
2272            Value(Repr::HostFn(host)) => write!(f, "<host fn {}.{}>", host.module, host.op),
2273            Value(Repr::Type(t)) => write!(f, "<type {t}>"),
2274            Value(Repr::Range {
2275                start,
2276                end,
2277                inclusive_end,
2278            }) => {
2279                let operator = if *inclusive_end { ".." } else { "..<" };
2280                write!(f, "{start}{operator}{end}")
2281            }
2282            Value(Repr::TaskScope(scope)) => write!(f, "<task scope {}>", scope.name),
2283            // A task prints as a handle, never as the value it will produce:
2284            // that value is observable only through `await` or scope exit.
2285            Value(Repr::Task(_)) => f.write_str("<task>"),
2286            // A `Shared` prints as the handle it is. Showing what it holds
2287            // would be a read outside a `lock`, which is the one thing the
2288            // type exists to prevent.
2289            Value(Repr::Shared(_)) => f.write_str("<shared>"),
2290        }
2291    }
2292}
2293
2294/// Renders a `Float` so that it is never mistaken for an `Int`.
2295///
2296/// Cove performs no implicit numeric conversions, so a float with no
2297/// fractional part still shows its point: `4.0`, not `4`. Negative zero keeps
2298/// its sign, and the non-finite values print as `NaN`, `inf`, and `-inf`.
2299fn write_float(f: &mut fmt::Formatter<'_>, x: f64) -> fmt::Result {
2300    if x.is_nan() {
2301        return f.write_str("NaN");
2302    }
2303    if x.is_infinite() {
2304        return f.write_str(if x.is_sign_negative() { "-inf" } else { "inf" });
2305    }
2306    if x.fract() == 0.0 {
2307        write!(f, "{x:.1}")
2308    } else {
2309        write!(f, "{x}")
2310    }
2311}
2312
2313/// Nanoseconds per duration unit, largest first, using the suffixes the lexer
2314/// accepts.
2315const DURATION_UNITS: [(i64, &str); 6] = [
2316    (3_600_000_000_000, "h"),
2317    (60_000_000_000, "m"),
2318    (1_000_000_000, "s"),
2319    (1_000_000, "ms"),
2320    (1_000, "us"),
2321    (1, "ns"),
2322];
2323
2324/// Renders a `Duration` in the largest unit that divides it exactly.
2325///
2326/// A duration no larger unit divides exactly stays in nanoseconds, and a
2327/// negative duration keeps its sign. Zero has no largest unit, so it prints as
2328/// `0ns`.
2329fn write_duration(f: &mut fmt::Formatter<'_>, ns: i64) -> fmt::Result {
2330    if ns == 0 {
2331        return f.write_str("0ns");
2332    }
2333    for (factor, suffix) in DURATION_UNITS {
2334        if ns % factor == 0 {
2335            return write!(f, "{}{suffix}", ns / factor);
2336        }
2337    }
2338    unreachable!("every duration is divisible by one nanosecond")
2339}
2340
2341#[cfg(test)]
2342mod tests {
2343    use super::*;
2344
2345    /// Inlining the common arities cost an `EnumValue` nothing at all.
2346    ///
2347    /// A `Payload` is three variants, one of them a whole [`Value`], and it
2348    /// is still twenty-four bytes — the width of the `Vec` it replaced —
2349    /// because `Value`'s discriminant lives in a `bool` niche with room to
2350    /// spare and `Payload`'s fits beside it. So `Some(x)` lost an allocation
2351    /// and gained no width, and `Marker::visit`'s
2352    /// `size_of::<EnumValue>()` charge means what it meant.
2353    ///
2354    /// Asserted rather than remembered because it is not obvious and because
2355    /// a future variant of either enum could take it away silently: a
2356    /// `Payload` wider than a `Vec` makes every enum value's box bigger, and
2357    /// this is the only place that would say so.
2358    #[test]
2359    fn a_payload_is_no_wider_than_the_vector_it_replaced() {
2360        assert_eq!(size_of::<Payload>(), size_of::<Vec<Value>>());
2361        assert_eq!(size_of::<Payload>(), 24);
2362        assert_eq!(size_of::<EnumValue>(), 56);
2363    }
2364
2365    fn shown(value: Value) -> String {
2366        value.to_string()
2367    }
2368
2369    #[test]
2370    fn a_float_is_never_shown_as_an_int() {
2371        assert_eq!(shown(Value(Repr::Float(4.0))), "4.0");
2372        assert_eq!(shown(Value(Repr::Float(-4.0))), "-4.0");
2373        assert_eq!(shown(Value(Repr::Float(1500.0))), "1500.0");
2374        assert_eq!(shown(Value(Repr::Float(1.5))), "1.5");
2375        assert_eq!(shown(Value(Repr::Float(0.25))), "0.25");
2376        assert_eq!(shown(Value(Repr::Float(-0.75))), "-0.75");
2377        assert_eq!(shown(Value(Repr::Float(0.02))), "0.02");
2378    }
2379
2380    #[test]
2381    fn float_edge_cases_are_explicit() {
2382        assert_eq!(shown(Value(Repr::Float(0.0))), "0.0");
2383        assert_eq!(shown(Value(Repr::Float(-0.0))), "-0.0");
2384        assert_eq!(shown(Value(Repr::Float(f64::INFINITY))), "inf");
2385        assert_eq!(shown(Value(Repr::Float(f64::NEG_INFINITY))), "-inf");
2386        assert_eq!(shown(Value(Repr::Float(f64::NAN))), "NaN");
2387    }
2388
2389    #[test]
2390    fn a_duration_uses_the_largest_unit_that_divides_it() {
2391        assert_eq!(shown(Value(Repr::Duration(0))), "0ns");
2392        assert_eq!(shown(Value(Repr::Duration(1))), "1ns");
2393        assert_eq!(shown(Value(Repr::Duration(1_000))), "1us");
2394        assert_eq!(shown(Value(Repr::Duration(1_000_000))), "1ms");
2395        assert_eq!(shown(Value(Repr::Duration(1_000_000_000))), "1s");
2396        assert_eq!(shown(Value(Repr::Duration(60_000_000_000))), "1m");
2397        assert_eq!(shown(Value(Repr::Duration(3_600_000_000_000))), "1h");
2398        assert_eq!(shown(Value(Repr::Duration(500_000_000))), "500ms");
2399        assert_eq!(shown(Value(Repr::Duration(1_500_000_000))), "1500ms");
2400        assert_eq!(shown(Value(Repr::Duration(90_000_000_000))), "90s");
2401    }
2402
2403    #[test]
2404    fn a_duration_no_larger_unit_divides_stays_in_nanoseconds() {
2405        assert_eq!(shown(Value(Repr::Duration(1_001))), "1001ns");
2406        assert_eq!(
2407            shown(Value(Repr::Duration(i64::MAX))),
2408            format!("{}ns", i64::MAX)
2409        );
2410    }
2411
2412    #[test]
2413    fn a_negative_duration_keeps_its_sign() {
2414        assert_eq!(shown(Value(Repr::Duration(-3_600_000_000_000))), "-1h");
2415        assert_eq!(shown(Value(Repr::Duration(-500_000_000))), "-500ms");
2416        assert_eq!(shown(Value(Repr::Duration(-1))), "-1ns");
2417    }
2418
2419    fn range(start: i64, end: i64, inclusive_end: bool) -> Value {
2420        Value(Repr::Range {
2421            start,
2422            end,
2423            inclusive_end,
2424        })
2425    }
2426
2427    #[test]
2428    fn a_range_shows_the_operator_it_was_written_with() {
2429        assert_eq!(shown(range(0, 3, false)), "0..<3");
2430        assert_eq!(shown(range(0, 3, true)), "0..3");
2431        assert_eq!(shown(range(-2, -1, false)), "-2..<-1");
2432    }
2433
2434    #[test]
2435    fn ranges_compare_by_value() {
2436        assert!(range(0, 3, false).eq_value(&range(0, 3, false)));
2437        assert!(!range(0, 3, false).eq_value(&range(0, 3, true)));
2438        assert!(!range(0, 3, false).eq_value(&range(1, 3, false)));
2439        assert!(!range(0, 3, false).eq_value(&Value(Repr::Int(0))));
2440    }
2441
2442    #[test]
2443    fn range_bounds_measure_and_test_membership() {
2444        let exclusive = RangeBounds::of(0, 3, false);
2445        assert_eq!(exclusive.len(), 3);
2446        assert!(!exclusive.is_empty());
2447        assert!(exclusive.contains(0));
2448        assert!(exclusive.contains(2));
2449        assert!(!exclusive.contains(3));
2450        assert!(!exclusive.contains(-1));
2451
2452        let inclusive = RangeBounds::of(0, 3, true);
2453        assert_eq!(inclusive.len(), 4);
2454        assert!(inclusive.contains(3));
2455    }
2456
2457    #[test]
2458    fn a_reversed_or_empty_range_is_empty() {
2459        for bounds in [
2460            RangeBounds::of(3, 0, false),
2461            RangeBounds::of(3, 0, true),
2462            RangeBounds::of(0, 0, false),
2463        ] {
2464            assert_eq!(bounds.len(), 0);
2465            assert!(bounds.is_empty());
2466            assert!(bounds.items().is_empty());
2467            assert!(!bounds.contains(0));
2468        }
2469    }
2470
2471    #[test]
2472    fn an_inclusive_range_that_ends_at_the_largest_int_does_not_overflow() {
2473        let bounds = RangeBounds::of(i64::MAX, i64::MAX, true);
2474        assert_eq!(bounds.len(), 1);
2475        assert!(bounds.contains(i64::MAX));
2476    }
2477
2478    fn payload_free_case(type_name: &str, case: &str) -> Value {
2479        Value(Repr::Enum(Box::new(EnumValue {
2480            type_name: type_name.into(),
2481            case: case.into(),
2482            payload: Payload::Empty,
2483        })))
2484    }
2485
2486    fn point(x: i64, y: i64) -> Value {
2487        Value(Repr::Struct(Rc::new(StructValue {
2488            type_name: "test.Point".into(),
2489            fields: vec![
2490                ("x".into(), Value(Repr::Int(x))),
2491                ("y".into(), Value(Repr::Int(y))),
2492            ],
2493            opaque: false,
2494        })))
2495    }
2496
2497    #[test]
2498    fn map_keys_accept_the_primitive_shapes() {
2499        assert_eq!(MapKey::from_value(&Value(Repr::Unit)), Ok(MapKey::Unit));
2500        assert_eq!(
2501            MapKey::from_value(&Value(Repr::Bool(true))),
2502            Ok(MapKey::Bool(true))
2503        );
2504        assert_eq!(MapKey::from_value(&Value(Repr::Int(7))), Ok(MapKey::Int(7)));
2505        assert_eq!(
2506            MapKey::from_value(&Value(Repr::Duration(500))),
2507            Ok(MapKey::Duration(500))
2508        );
2509        assert_eq!(
2510            MapKey::from_value(&Value(Repr::Str("a".into()))),
2511            Ok(MapKey::Str("a".to_string()))
2512        );
2513        assert_eq!(
2514            MapKey::from_value(&payload_free_case("Color", "Red")),
2515            Ok(MapKey::EnumCase(
2516                "Color".to_string(),
2517                "Red".to_string(),
2518                Vec::new()
2519            ))
2520        );
2521    }
2522
2523    /// A `Range` is immutable with a stable `eq_value`, so it qualifies as a
2524    /// map key or set element under the same rule as every other value here.
2525    #[test]
2526    fn a_range_is_a_valid_map_key() {
2527        assert_eq!(
2528            MapKey::from_value(&Value(Repr::Range {
2529                start: 0,
2530                end: 3,
2531                inclusive_end: false,
2532            })),
2533            Ok(MapKey::Range {
2534                start: 0,
2535                end: 3,
2536                inclusive_end: false,
2537            })
2538        );
2539        // `0..<3` and `0..2` are distinct keys, exactly as they are distinct
2540        // values: `eq_value` compares the bounds a range was written with.
2541        assert_ne!(
2542            MapKey::from_value(&Value(Repr::Range {
2543                start: 0,
2544                end: 3,
2545                inclusive_end: false,
2546            })),
2547            MapKey::from_value(&Value(Repr::Range {
2548                start: 0,
2549                end: 2,
2550                inclusive_end: true,
2551            }))
2552        );
2553    }
2554
2555    #[test]
2556    fn a_struct_built_only_from_admissible_fields_is_a_valid_key() {
2557        let key = MapKey::from_value(&point(1, 2)).expect("a struct of Ints is a valid key");
2558        assert_eq!(
2559            key,
2560            MapKey::Struct(
2561                "test.Point".to_string(),
2562                vec![
2563                    ("x".to_string(), MapKey::Int(1)),
2564                    ("y".to_string(), MapKey::Int(2)),
2565                ],
2566                false
2567            )
2568        );
2569    }
2570
2571    #[test]
2572    fn a_struct_nested_inside_a_struct_is_a_valid_key_when_every_field_is() {
2573        let line = Value(Repr::Struct(Rc::new(StructValue {
2574            type_name: "test.Line".into(),
2575            fields: vec![("from".into(), point(0, 0)), ("to".into(), point(1, 1))],
2576            opaque: false,
2577        })));
2578        let key = MapKey::from_value(&line).expect("nested structs of Ints are a valid key");
2579        assert_eq!(
2580            key,
2581            MapKey::Struct(
2582                "test.Line".to_string(),
2583                vec![
2584                    (
2585                        "from".to_string(),
2586                        MapKey::Struct(
2587                            "test.Point".to_string(),
2588                            vec![
2589                                ("x".to_string(), MapKey::Int(0)),
2590                                ("y".to_string(), MapKey::Int(0)),
2591                            ],
2592                            false
2593                        )
2594                    ),
2595                    (
2596                        "to".to_string(),
2597                        MapKey::Struct(
2598                            "test.Point".to_string(),
2599                            vec![
2600                                ("x".to_string(), MapKey::Int(1)),
2601                                ("y".to_string(), MapKey::Int(1)),
2602                            ],
2603                            false
2604                        )
2605                    ),
2606                ],
2607                false
2608            )
2609        );
2610    }
2611
2612    #[test]
2613    fn an_enum_case_with_an_admissible_payload_is_a_valid_key() {
2614        let value = Value(Repr::Enum(Box::new(EnumValue {
2615            type_name: "test.Colour".into(),
2616            case: "Named".into(),
2617            payload: Payload::One(Value(Repr::Str("teal".into()))),
2618        })));
2619        assert_eq!(
2620            MapKey::from_value(&value),
2621            Ok(MapKey::EnumCase(
2622                "test.Colour".to_string(),
2623                "Named".to_string(),
2624                vec![MapKey::Str("teal".to_string())]
2625            ))
2626        );
2627    }
2628
2629    #[test]
2630    fn an_array_built_only_from_admissible_elements_is_a_valid_key() {
2631        let value = Value(Repr::Array(
2632            vec![Value(Repr::Int(1)), Value(Repr::Int(2))].into(),
2633        ));
2634        assert_eq!(
2635            MapKey::from_value(&value),
2636            Ok(MapKey::Array(vec![MapKey::Int(1), MapKey::Int(2)]))
2637        );
2638    }
2639
2640    #[test]
2641    fn map_keys_reject_a_float_for_a_reason_distinct_from_mutability() {
2642        let invalid = MapKey::from_value(&Value(Repr::Float(1.0))).unwrap_err();
2643        assert_eq!(invalid.type_name, "Float");
2644        assert!(invalid.path.is_empty());
2645        assert!(
2646            invalid.rule().contains("NaN"),
2647            "a Float's rejection must cite the broken order, not mutability: {}",
2648            invalid.rule()
2649        );
2650    }
2651
2652    #[test]
2653    fn map_keys_reject_a_vector_naming_it_directly_at_the_root() {
2654        let invalid =
2655            MapKey::from_value(&Value(Repr::Vector(VectorStorage::new(Vec::new())))).unwrap_err();
2656        assert_eq!(invalid.type_name, "Vector");
2657        assert!(invalid.path.is_empty());
2658        assert!(
2659            invalid.rule().contains("Mutable handles"),
2660            "{}",
2661            invalid.rule()
2662        );
2663    }
2664
2665    #[test]
2666    fn a_struct_containing_a_vector_is_rejected_naming_the_nested_field() {
2667        let value = Value(Repr::Struct(Rc::new(StructValue {
2668            type_name: "test.Point".into(),
2669            fields: vec![(
2670                "tags".into(),
2671                Value(Repr::Vector(VectorStorage::new(Vec::new()))),
2672            )],
2673            opaque: false,
2674        })));
2675        let invalid = MapKey::from_value(&value).unwrap_err();
2676        assert_eq!(invalid.type_name, "Vector");
2677        assert_eq!(invalid.path, "Point.tags");
2678    }
2679
2680    #[test]
2681    fn a_map_key_round_trips_through_to_value() {
2682        for key in [
2683            MapKey::Unit,
2684            MapKey::Bool(false),
2685            MapKey::Int(42),
2686            MapKey::Duration(500),
2687            MapKey::Str("hi".to_string()),
2688            MapKey::EnumCase("Color".to_string(), "Red".to_string(), Vec::new()),
2689            MapKey::Array(vec![MapKey::Int(1), MapKey::Int(2)]),
2690            MapKey::Range {
2691                start: 0,
2692                end: 3,
2693                inclusive_end: false,
2694            },
2695            MapKey::Struct(
2696                "test.Point".to_string(),
2697                vec![
2698                    ("x".to_string(), MapKey::Int(1)),
2699                    ("y".to_string(), MapKey::Int(2)),
2700                ],
2701                false,
2702            ),
2703        ] {
2704            let value = key.to_value();
2705            assert_eq!(MapKey::from_value(&value), Ok(key));
2706        }
2707    }
2708
2709    #[test]
2710    fn a_set_is_a_valid_key_because_its_elements_are_already_map_keys() {
2711        let inner = Value(Repr::Set(Rc::new(BTreeSet::from([
2712            MapKey::Int(1),
2713            MapKey::Int(2),
2714        ]))));
2715        assert_eq!(
2716            MapKey::from_value(&inner),
2717            Ok(MapKey::Set(BTreeSet::from([
2718                MapKey::Int(1),
2719                MapKey::Int(2)
2720            ])))
2721        );
2722    }
2723
2724    #[test]
2725    fn a_map_is_a_valid_key_when_every_value_is_admissible() {
2726        let inner = Value(Repr::Map(Rc::new(BTreeMap::from([(
2727            MapKey::Str("a".to_string()),
2728            Value(Repr::Int(1)),
2729        )]))));
2730        assert_eq!(
2731            MapKey::from_value(&inner),
2732            Ok(MapKey::Map(BTreeMap::from([(
2733                MapKey::Str("a".to_string()),
2734                MapKey::Int(1)
2735            )])))
2736        );
2737    }
2738
2739    #[test]
2740    fn a_map_containing_an_inadmissible_value_is_rejected_naming_the_entry() {
2741        let inner = Value(Repr::Map(Rc::new(BTreeMap::from([(
2742            MapKey::Str("a".to_string()),
2743            Value(Repr::Vector(VectorStorage::new(Vec::new()))),
2744        )]))));
2745        let invalid = MapKey::from_value(&inner).unwrap_err();
2746        assert_eq!(invalid.type_name, "Vector");
2747        assert_eq!(invalid.path, "[a]");
2748    }
2749
2750    fn map_of(pairs: Vec<(MapKey, Value)>) -> Value {
2751        Value(Repr::Map(Rc::new(pairs.into_iter().collect())))
2752    }
2753
2754    fn set_of(keys: Vec<MapKey>) -> Value {
2755        Value(Repr::Set(Rc::new(keys.into_iter().collect())))
2756    }
2757
2758    #[test]
2759    fn maps_compare_structurally() {
2760        let a = map_of(vec![(MapKey::Str("x".to_string()), Value(Repr::Int(1)))]);
2761        let b = map_of(vec![(MapKey::Str("x".to_string()), Value(Repr::Int(1)))]);
2762        let c = map_of(vec![(MapKey::Str("x".to_string()), Value(Repr::Int(2)))]);
2763        assert!(a.eq_value(&b));
2764        assert!(!a.eq_value(&c));
2765    }
2766
2767    #[test]
2768    fn sets_compare_structurally() {
2769        let a = set_of(vec![MapKey::Int(1), MapKey::Int(2)]);
2770        let b = set_of(vec![MapKey::Int(2), MapKey::Int(1)]);
2771        let c = set_of(vec![MapKey::Int(1)]);
2772        assert!(a.eq_value(&b));
2773        assert!(!a.eq_value(&c));
2774    }
2775
2776    /// `==` means value equality regardless of mutability, so two separately
2777    /// built `Vector`s with the same elements are equal; a vector with
2778    /// different elements, or a different length, is not. Storage identity
2779    /// is the separate question `is` answers, not `eq_value`.
2780    #[test]
2781    fn vectors_compare_structurally() {
2782        let a = Value(Repr::Vector(VectorStorage::new(vec![
2783            Value(Repr::Int(1)),
2784            Value(Repr::Int(2)),
2785        ])));
2786        let b = Value(Repr::Vector(VectorStorage::new(vec![
2787            Value(Repr::Int(1)),
2788            Value(Repr::Int(2)),
2789        ])));
2790        let c = Value(Repr::Vector(VectorStorage::new(vec![
2791            Value(Repr::Int(1)),
2792            Value(Repr::Int(3)),
2793        ])));
2794        let d = Value(Repr::Vector(VectorStorage::new(vec![Value(Repr::Int(1))])));
2795        assert!(a.eq_value(&b));
2796        assert!(!a.eq_value(&c));
2797        assert!(!a.eq_value(&d));
2798    }
2799
2800    /// A vector equals itself under `==` too, even though it is a mutable
2801    /// handle: `==` never asks the identity question.
2802    #[test]
2803    fn a_vector_equals_itself_structurally() {
2804        let a = Value(Repr::Vector(VectorStorage::new(vec![Value(Repr::Int(1))])));
2805        assert!(a.eq_value(&a.clone()));
2806    }
2807
2808    #[test]
2809    fn a_map_shows_entries_in_ascending_key_order() {
2810        let value = map_of(vec![
2811            (MapKey::Int(2), Value(Repr::Str("b".into()))),
2812            (MapKey::Int(1), Value(Repr::Str("a".into()))),
2813        ]);
2814        assert_eq!(shown(value), "{1: a, 2: b}");
2815    }
2816
2817    #[test]
2818    fn a_set_shows_elements_in_ascending_order() {
2819        let value = set_of(vec![MapKey::Int(3), MapKey::Int(1), MapKey::Int(2)]);
2820        assert_eq!(shown(value), "{1, 2, 3}");
2821    }
2822
2823    /// Every shape a constructor builds, read back through a reader, with no
2824    /// variant named on either side.
2825    ///
2826    /// This is the round trip issue #186 asked for: the constructors were the
2827    /// only half that existed, so a host could build a boundary value without
2828    /// naming `Rc<StructValue>` and could not read one back the same way.
2829    #[test]
2830    fn every_shape_a_constructor_builds_reads_back_through_a_reader() {
2831        let structure = Value::structure(
2832            "rules.policy.Decision",
2833            [
2834                ("policy", Value(Repr::Int(1))),
2835                ("findings", Value::array([])),
2836            ],
2837        );
2838        assert_eq!(structure.declared_type(), Some("rules.policy.Decision"));
2839        assert_eq!(structure.field("policy").and_then(Value::as_int), Some(1));
2840        assert!(structure.field("absent").is_none());
2841        assert_eq!(
2842            structure
2843                .fields()
2844                .expect("a struct has fields")
2845                .map(|(name, _)| name)
2846                .collect::<Vec<_>>(),
2847            ["policy", "findings"],
2848            "declaration order, which is the order the constructor was handed"
2849        );
2850
2851        let enumeration = Value::enumeration(
2852            "rules.policy.ReviewPolicy",
2853            "Require",
2854            [Value(Repr::Int(2)), Value(Repr::Str("large change".into()))],
2855        );
2856        assert_eq!(
2857            enumeration.declared_type(),
2858            Some("rules.policy.ReviewPolicy")
2859        );
2860        assert_eq!(enumeration.case(), Some("Require"));
2861        assert_eq!(enumeration.payload().map(<[Value]>::len), Some(2));
2862
2863        let array = Value::array([Value(Repr::Int(1)), Value(Repr::Int(2))]);
2864        assert_eq!(
2865            array.items().map(|items| items.len()),
2866            Some(2),
2867            "an `Array` reads as the slice it is"
2868        );
2869
2870        let set = Value::set([MapKey::Int(2), MapKey::Int(1), MapKey::Int(2)]);
2871        assert_eq!(
2872            set.elements()
2873                .expect("a set has elements")
2874                .collect::<Vec<_>>(),
2875            [&MapKey::Int(1), &MapKey::Int(2)],
2876            "ascending key order, and a duplicate collapsed"
2877        );
2878
2879        let map = Value::map([
2880            (MapKey::Int(2), Value(Repr::Str("b".into()))),
2881            (MapKey::Int(1), Value(Repr::Str("a".into()))),
2882        ]);
2883        assert_eq!(
2884            map.entries()
2885                .expect("a map has entries")
2886                .map(|(key, value)| (key.clone(), value.to_string()))
2887                .collect::<Vec<_>>(),
2888            [
2889                (MapKey::Int(1), "a".to_string()),
2890                (MapKey::Int(2), "b".to_string()),
2891            ],
2892            "ascending key order, which is what a Cove program iterating sees"
2893        );
2894
2895        assert_eq!(
2896            Value::ok(Value(Repr::Int(1))).payload().map(<[Value]>::len),
2897            Some(1),
2898            "a builtin enum reads through the general reader as well as the four"
2899        );
2900        assert_eq!(
2901            Value::none().payload().map(<[Value]>::len),
2902            Some(0),
2903            "a case that carries nothing reads as an empty slice"
2904        );
2905        assert_eq!(
2906            Value::error("broken")
2907                .error_message()
2908                .and_then(Value::as_str),
2909            Some("broken")
2910        );
2911    }
2912
2913    /// Every scalar reads back as the Rust value it was built from.
2914    #[test]
2915    fn a_scalar_reads_back_as_itself() {
2916        assert_eq!(Value(Repr::Bool(true)).as_bool(), Some(true));
2917        assert_eq!(Value(Repr::Int(-7)).as_int(), Some(-7));
2918        assert_eq!(Value(Repr::Float(1.5)).as_float(), Some(1.5));
2919        assert_eq!(
2920            Value(Repr::Duration(-1_000)).as_duration_nanos(),
2921            Some(-1_000)
2922        );
2923        assert_eq!(Value(Repr::Str("hello".into())).as_str(), Some("hello"));
2924        assert!(Value(Repr::Unit).is_unit());
2925        assert_eq!(
2926            Value(Repr::Range {
2927                start: 1,
2928                end: 3,
2929                inclusive_end: true,
2930            })
2931            .range()
2932            .map(|bounds| (bounds.start, bounds.end)),
2933            Some((1, 4)),
2934            "`..` and `..<` normalise to one half-open pair"
2935        );
2936    }
2937
2938    /// A wrong shape answers `None` rather than panicking, which is the
2939    /// convention `ok_payload` and `StructValue::get` already set.
2940    #[test]
2941    fn a_reader_asked_of_the_wrong_shape_answers_none() {
2942        let value = Value(Repr::Int(1));
2943        assert_eq!(value.as_str(), None);
2944        assert_eq!(value.as_bool(), None);
2945        assert_eq!(value.declared_type(), None);
2946        assert!(value.field("policy").is_none());
2947        assert!(value.fields().is_none());
2948        assert_eq!(value.case(), None);
2949        assert!(value.payload().is_none());
2950        assert!(value.items().is_none());
2951        assert!(value.elements().is_none());
2952        assert!(value.entries().is_none());
2953        assert!(value.range().is_none());
2954        assert!(value.resource().is_none());
2955        assert_eq!(value.host_op(), None);
2956        assert_eq!(value.arity(), None);
2957        assert!(!value.is_unit());
2958
2959        // A `Vector` is not an `Array` and says so, because its elements are
2960        // behind a `RefCell` and nothing can hand out a slice of them.
2961        let vector = Value(Repr::Vector(VectorStorage::new(vec![Value(Repr::Int(1))])));
2962        assert!(vector.items().is_none());
2963    }
2964
2965    /// A reader looks through a `dyn Trait` wrapper, exactly as `Display` and
2966    /// `eq_value` do: nothing a program can ask tells a written conversion
2967    /// from a lambda's inferred one.
2968    #[test]
2969    fn a_reader_looks_through_a_trait_object() {
2970        let wrapped = Value(Repr::Dyn(Rc::new(DynValue {
2971            trait_name: "render.Display".into(),
2972            value: Value::structure("app.Point", [("x", Value(Repr::Int(1)))]),
2973        })));
2974        assert_eq!(wrapped.declared_type(), Some("app.Point"));
2975        assert_eq!(wrapped.field("x").and_then(Value::as_int), Some(1));
2976
2977        let wrapped_scalar = Value(Repr::Dyn(Rc::new(DynValue {
2978            trait_name: "render.Display".into(),
2979            value: Value(Repr::Str("shown".into())),
2980        })));
2981        assert_eq!(wrapped_scalar.as_str(), Some("shown"));
2982    }
2983
2984    /// The three representation changes that were embedder source breaks, read
2985    /// through the API that would have hidden each of them.
2986    ///
2987    /// Not a test of behaviour so much as of what the signatures admit: every
2988    /// assertion below names a shape the *language* has and no type the
2989    /// runtime chose to hold it in. Issue #104 moved a struct from a `Box` to
2990    /// an `Rc`, issue #109 moved a bound host operation's two names behind one
2991    /// pointer, and issue #183 replaced an enum payload's `Vec<Value>` with
2992    /// [`Payload`] — a host written against these lines would have compiled
2993    /// unchanged across all three, and the point of writing them down is that
2994    /// the next such change has to keep them compiling.
2995    #[test]
2996    fn a_reader_hides_each_representation_change_that_was_a_source_break() {
2997        // #104: the struct behind an `Rc`, where a host once wrote
2998        // `let Value::Struct(s) = value` and bound a `&Box<StructValue>`.
2999        let decision = Value::structure("app.Decision", [("reviewers", Value(Repr::Int(2)))]);
3000        assert_eq!(decision.field("reviewers").and_then(Value::as_int), Some(2));
3001
3002        // #183: the payload at each of the three arities `Payload` holds, read
3003        // as one slice whichever it is.
3004        for (payload, len) in [
3005            (Vec::new(), 0),
3006            (vec![Value(Repr::Int(1))], 1),
3007            (vec![Value(Repr::Int(1)), Value(Repr::Int(2))], 2),
3008        ] {
3009            let value = Value::enumeration("app.Verdict", "Case", payload);
3010            assert_eq!(value.case(), Some("Case"));
3011            assert_eq!(value.payload().map(<[Value]>::len), Some(len));
3012        }
3013
3014        // #109: the two names of a bound host operation, which were inline
3015        // fields of the variant until they cost every value in the program
3016        // sixteen bytes.
3017        let bound = Value(Repr::HostFn(Rc::new(HostFnValue {
3018            module: "console".into(),
3019            op: "println".into(),
3020        })));
3021        assert_eq!(bound.host_op(), Some(("console", "println")));
3022
3023        // #121, the fourth of the same kind: a closure's parameter list became
3024        // a count, and a host only ever wanted the count.
3025        let closure = Value(Repr::Closure(Rc::new(Closure {
3026            is_async: false,
3027            arity: 2,
3028            body: ClosureBody::Tree {
3029                params: Vec::new(),
3030                block: Arc::new(cove_syntax::ast::Block {
3031                    statements: Vec::new(),
3032                    tail: None,
3033                    span: cove_diag::Span::new(cove_diag::FileId(0), 0, 0),
3034                }),
3035                decl: None,
3036            },
3037            module: "app".into(),
3038            captures: Vec::new(),
3039        })));
3040        assert_eq!(closure.arity(), Some(2));
3041    }
3042
3043    /// One value of every kind the language has, classified.
3044    ///
3045    /// The list is exhaustive on purpose: [`ValueView`] is not
3046    /// `#[non_exhaustive]`, so a new kind of Cove value is a compile error at
3047    /// `Value::view` first and here second, and this is where the count is
3048    /// checked. A `_` arm below would defeat both.
3049    #[test]
3050    fn a_view_names_every_kind_of_value() {
3051        let cell = SharedCell::new(crate::Transfer::Int(1));
3052        let scope = TaskScope::new("work".into());
3053        let task = Task::settled(Value::unit());
3054        let kinds = [
3055            Value::unit(),
3056            Value::bool(true),
3057            Value::int(1),
3058            Value::float(1.0),
3059            Value::duration(1),
3060            Value::string("hi"),
3061            Value::array([Value::int(1)]),
3062            Value(Repr::Vector(VectorStorage::new(vec![Value::int(1)]))),
3063            Value::map([(MapKey::Int(1), Value::int(2))]),
3064            Value::set([MapKey::Int(1)]),
3065            Value::structure("app.Point", [("x", Value::int(1))]),
3066            Value::some(Value::int(1)),
3067            Value(Repr::Closure(Rc::new(Closure {
3068                is_async: true,
3069                arity: 2,
3070                body: ClosureBody::Tree {
3071                    params: Vec::new(),
3072                    block: Arc::new(cove_syntax::ast::Block {
3073                        statements: Vec::new(),
3074                        tail: None,
3075                        span: cove_diag::Span::new(cove_diag::FileId(0), 0, 0),
3076                    }),
3077                    decl: None,
3078                },
3079                module: "app".into(),
3080                captures: Vec::new(),
3081            }))),
3082            Value::host_module("console"),
3083            Value::host_fn("console", "println"),
3084            Value::from_resource(ResourceHandle {
3085                module: "database".to_string(),
3086                type_name: "Connection".to_string(),
3087                id: 1,
3088                task_safe: true,
3089            }),
3090            Value::type_value("Vector"),
3091            Value::range_of(1, 3, false),
3092            Value(Repr::Task(task)),
3093            Value(Repr::TaskScope(scope)),
3094            Value(Repr::Shared(cell)),
3095        ];
3096        let mut seen = 0;
3097        for value in &kinds {
3098            seen += 1;
3099            match value.view() {
3100                ValueView::Unit => assert_eq!(seen, 1),
3101                ValueView::Bool(b) => assert!(b),
3102                ValueView::Int(n) => assert_eq!(n, 1),
3103                ValueView::Float(x) => assert_eq!(x, 1.0),
3104                ValueView::Duration(ns) => assert_eq!(ns, 1),
3105                ValueView::Str(text) => assert_eq!(text, "hi"),
3106                ValueView::Array(items) => assert_eq!(items.len(), 1),
3107                // The one part that answers a guard rather than a borrow,
3108                // and it reads as the slice it guards.
3109                ValueView::Vector(elements) => assert_eq!(elements[0].as_int(), Some(1)),
3110                ValueView::Map(entries) => {
3111                    assert_eq!(
3112                        entries.get(&MapKey::Int(1)).and_then(Value::as_int),
3113                        Some(2)
3114                    )
3115                }
3116                ValueView::Set(members) => assert!(members.contains(&MapKey::Int(1))),
3117                ValueView::Struct(value) => {
3118                    assert_eq!(value.type_name(), "app.Point");
3119                    assert!(!value.is_opaque());
3120                    assert_eq!(value.field("x").and_then(Value::as_int), Some(1));
3121                }
3122                ValueView::Enum(value) => {
3123                    assert_eq!((value.type_name(), value.case()), ("Option", "Some"));
3124                    assert_eq!(value.payload().len(), 1);
3125                }
3126                ValueView::Closure(closure) => {
3127                    assert!(closure.is_async());
3128                    assert_eq!(closure.arity(), 2);
3129                }
3130                ValueView::HostModule(name) => assert_eq!(name, "console"),
3131                ValueView::HostFn { module, op } => {
3132                    assert_eq!((module, op), ("console", "println"))
3133                }
3134                ValueView::Resource(handle) => assert_eq!(handle.id, 1),
3135                ValueView::Type(name) => assert_eq!(name, "Vector"),
3136                ValueView::Range(bounds) => assert_eq!((bounds.start, bounds.end), (1, 3)),
3137                ValueView::Task(task) => assert_eq!(task.scope(), "this call"),
3138                ValueView::TaskScope(scope) => assert_eq!(scope.name(), "work"),
3139                ValueView::Shared(_) => assert_eq!(seen, 21),
3140            }
3141        }
3142        assert_eq!(seen, kinds.len());
3143    }
3144
3145    /// The view looks through a `dyn Trait` wrapper, exactly as every reader
3146    /// beside it does — which is why there is no `Dyn` variant to match, and
3147    /// why the trait name is a reader instead.
3148    #[test]
3149    fn a_view_looks_through_a_trait_object() {
3150        let wrapped = Value(Repr::Dyn(Rc::new(DynValue {
3151            trait_name: "render.Display".into(),
3152            value: Value::structure("app.Point", [("x", Value::int(1))]),
3153        })));
3154        let ValueView::Struct(value) = wrapped.view() else {
3155            panic!("a wrapped struct views as a struct, not as a wrapper");
3156        };
3157        assert_eq!(value.type_name(), "app.Point");
3158        assert_eq!(wrapped.dyn_trait(), Some("render.Display"));
3159        assert_eq!(Value::int(1).dyn_trait(), None);
3160
3161        // Twice over: `erased` looks through a wrapper holding a wrapper, so
3162        // `view` never has one to answer.
3163        let twice = Value(Repr::Dyn(Rc::new(DynValue {
3164            trait_name: "render.Display".into(),
3165            value: wrapped,
3166        })));
3167        assert!(matches!(twice.view(), ValueView::Struct(_)));
3168    }
3169
3170    /// Viewing a value shares nothing new.
3171    ///
3172    /// ADR 0028 decision 8 separates three multiplicities and a view has to
3173    /// leave all three alone. It does, because it clones nothing: no `Rc`
3174    /// count changes, so the shortfall rule that makes a Rust local a root
3175    /// answers exactly what it answered before; no root storage location is
3176    /// yielded, so `Roots::walk` still reports each reference once; and the
3177    /// graph `Marker::visit` expands is the same graph, since a view adds no
3178    /// edge to it. A view that cloned an `Rc` would add a reference no walk
3179    /// can see and keep a dead object alive; one a walk could see twice would
3180    /// conceal the very shortfall the collector's soundness rests on. This is
3181    /// what says neither happens.
3182    ///
3183    /// The `Vector` guard holds a shared `RefCell` borrow rather than a
3184    /// reference, which is a different question and is answered the same way:
3185    /// `Marker::visit` borrows the elements shared, and the sweep clears them
3186    /// through `try_borrow_mut`, so an outstanding guard cannot make either
3187    /// panic.
3188    #[test]
3189    fn a_view_changes_no_reference_count() {
3190        let storage = VectorStorage::new(vec![Value::int(1)]);
3191        let vector = Value(Repr::Vector(storage.clone()));
3192        let fields = Rc::new(StructValue {
3193            type_name: "app.Point".into(),
3194            fields: vec![("x".into(), Value::int(1))],
3195            opaque: false,
3196        });
3197        let structure = Value(Repr::Struct(fields.clone()));
3198
3199        let before = (Rc::strong_count(&storage), Rc::strong_count(&fields));
3200        let views = (vector.view(), structure.view(), vector.vector_elements());
3201        assert_eq!(
3202            before,
3203            (Rc::strong_count(&storage), Rc::strong_count(&fields))
3204        );
3205        drop(views);
3206        assert_eq!(
3207            before,
3208            (Rc::strong_count(&storage), Rc::strong_count(&fields))
3209        );
3210    }
3211
3212    /// Every scalar a host can build, built without naming a variant and read
3213    /// back through the reader it mirrors.
3214    ///
3215    /// There was no way to build an `Int` at all until this: a host wrote
3216    /// `Value::Int(3)` because there was nothing else to write, which is why
3217    /// sealing the variants had to wait for the constructors. Each line pairs
3218    /// a constructor with the reader ADR 0028 calls its mirror, so a
3219    /// constructor that stopped agreeing with its reader fails here.
3220    #[test]
3221    fn every_scalar_has_a_constructor_that_mirrors_its_reader() {
3222        assert!(Value::unit().is_unit());
3223        assert_eq!(Value::bool(true).as_bool(), Some(true));
3224        assert_eq!(Value::int(i64::MIN).as_int(), Some(i64::MIN));
3225        assert_eq!(Value::float(-0.5).as_float(), Some(-0.5));
3226        assert_eq!(
3227            Value::duration(-1_000_000_000).as_duration_nanos(),
3228            Some(-1_000_000_000)
3229        );
3230        assert_eq!(Value::string("hi").as_str(), Some("hi"));
3231        assert_eq!(Value::string(String::from("hi")).as_str(), Some("hi"));
3232
3233        // `1..3` and `1..<4` cover the same integers and are still two
3234        // different values, so the constructor takes the bounds as written
3235        // and the reader answers the normalised pair.
3236        let bounds = Value::range_of(1, 3, true).range().expect("a range");
3237        assert_eq!((bounds.start, bounds.end), (1, 4));
3238
3239        assert_eq!(
3240            Value::host_fn("console", "println").host_op(),
3241            Some(("console", "println"))
3242        );
3243        assert_eq!(
3244            Value::host_module("console").type_name(),
3245            "host module `console`"
3246        );
3247        assert_eq!(Value::type_value("Vector").type_name(), "type `Vector`");
3248
3249        let handle = ResourceHandle {
3250            module: "database".to_string(),
3251            type_name: "Connection".to_string(),
3252            id: 7,
3253            task_safe: true,
3254        };
3255        let value = Value::from_resource(handle.clone());
3256        assert!(value.resource().expect("a resource").names_same(&handle));
3257        // The `Arc` a host already holds is accepted as it stands, so nothing
3258        // has to clone a handle to build a value out of one.
3259        assert!(Value::from_resource(Arc::new(handle)).resource().is_some());
3260    }
3261}