iter 22b.1.1: ClassDef/InstanceDef AST + downstream match arms
Adds Def::Class(ClassDef) and Def::Instance(InstanceDef) variants per Decision 11 §"Form-A schema". All optional fields (superclass, doc, default body) carry skip_serializing_if so canonical-JSON bytes of pre-22b fixtures stay bit-identical. Downstream match-on-Def sites are extended with explicit Class/Instance arms. Behaviour for 22b.1 is placeholder (skip in typecheck/codegen, one-line summary in pretty/manifest, placeholder marker in prose/print) with TODO comments naming the deferred sub-iters (22b.2 typecheck, 22b.3 codegen, 22b.4 prose-projection arms).
This commit is contained in:
@@ -57,9 +57,16 @@ pub struct Import {
|
||||
|
||||
/// A top-level definition — the unit that gets a content hash.
|
||||
///
|
||||
/// Discriminated by the JSON `kind` tag: `"fn"`, `"const"`, or
|
||||
/// `"type"`. Use [`def_name`] / [`def_kind`] (or the [`Def::name`]
|
||||
/// method) to inspect generically without matching every variant.
|
||||
/// Discriminated by the JSON `kind` tag: `"fn"`, `"const"`, `"type"`,
|
||||
/// `"class"`, or `"instance"`. Use [`def_name`] / [`def_kind`] (or the
|
||||
/// [`Def::name`] method) to inspect generically without matching every
|
||||
/// variant.
|
||||
///
|
||||
/// Iter 22b.1 (Decision 11): adds `Class` and `Instance`. Both are
|
||||
/// additive — pre-22b fixtures never produce these tags, so their
|
||||
/// canonical-JSON bytes (and therefore their content hashes) are
|
||||
/// unchanged. The `Def`-level match exhaustiveness in downstream
|
||||
/// crates is the only caller that has to acknowledge the variants.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(tag = "kind", rename_all = "lowercase")]
|
||||
pub enum Def {
|
||||
@@ -69,15 +76,26 @@ pub enum Def {
|
||||
Const(ConstDef),
|
||||
/// Type (ADT) definition; see [`TypeDef`].
|
||||
Type(TypeDef),
|
||||
/// Iter 22b.1: typeclass declaration; see [`ClassDef`].
|
||||
Class(ClassDef),
|
||||
/// Iter 22b.1: instance declaration; see [`InstanceDef`].
|
||||
Instance(InstanceDef),
|
||||
}
|
||||
|
||||
impl Def {
|
||||
/// Source-level name of the definition, regardless of kind.
|
||||
///
|
||||
/// For `Def::Instance` the "name" is the class being instantiated;
|
||||
/// instances are not separately named at the source level. The
|
||||
/// workspace registry keys instances by `(class, type-hash)`, so
|
||||
/// the class name alone is the closest analogue of a "name".
|
||||
pub fn name(&self) -> &str {
|
||||
match self {
|
||||
Def::Fn(f) => &f.name,
|
||||
Def::Const(c) => &c.name,
|
||||
Def::Type(t) => &t.name,
|
||||
Def::Class(c) => &c.name,
|
||||
Def::Instance(i) => &i.class,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,7 +110,7 @@ pub fn def_name(def: &Def) -> &str {
|
||||
}
|
||||
|
||||
/// External helper: discriminator tag of a definition (`"fn"`,
|
||||
/// `"const"`, `"type"`).
|
||||
/// `"const"`, `"type"`, `"class"`, `"instance"`).
|
||||
///
|
||||
/// Identical to the `kind` field in the JSON representation. Useful
|
||||
/// for tools that group or filter definitions by kind.
|
||||
@@ -101,6 +119,8 @@ pub fn def_kind(def: &Def) -> &'static str {
|
||||
Def::Fn(_) => "fn",
|
||||
Def::Const(_) => "const",
|
||||
Def::Type(_) => "type",
|
||||
Def::Class(_) => "class",
|
||||
Def::Instance(_) => "instance",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,6 +240,97 @@ pub struct Suppress {
|
||||
pub because: String,
|
||||
}
|
||||
|
||||
/// Iter 22b.1: a typeclass declaration (Decision 11).
|
||||
///
|
||||
/// Single-parameter, multi-method, optional-default, optional-superclass
|
||||
/// typeclass. The `param` is a single string — multi-param classes are
|
||||
/// rejected by Decision 11 axis 1, and the schema enforces it by shape
|
||||
/// (`param: String`, not `Vec<String>`).
|
||||
///
|
||||
/// `superclass`, when present, MUST have its `type` field equal to
|
||||
/// `param`. The check is enforced in 22b.2 via the
|
||||
/// `InvalidSuperclassParam` diagnostic; the schema does not encode it.
|
||||
///
|
||||
/// All optional fields are omitted from canonical JSON when absent /
|
||||
/// empty, so future schema evolution can land here without disturbing
|
||||
/// pre-22b hashes.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ClassDef {
|
||||
/// Class name (capitalised by convention).
|
||||
pub name: String,
|
||||
/// Single type-parameter name.
|
||||
pub param: String,
|
||||
/// Optional single-superclass relation.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub superclass: Option<SuperclassRef>,
|
||||
/// Methods of the class, in declaration order.
|
||||
pub methods: Vec<ClassMethod>,
|
||||
/// Optional source-level documentation string.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub doc: Option<String>,
|
||||
}
|
||||
|
||||
/// Iter 22b.1: reference to a superclass relation in [`ClassDef`].
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SuperclassRef {
|
||||
/// Superclass name.
|
||||
pub class: String,
|
||||
/// Type the superclass is applied to. MUST equal the parent
|
||||
/// `ClassDef.param` (validated in 22b.2 — schema does not enforce).
|
||||
#[serde(rename = "type")]
|
||||
pub type_: String,
|
||||
}
|
||||
|
||||
/// Iter 22b.1: one method declared in a [`ClassDef`].
|
||||
///
|
||||
/// `default` is `None` when the method is abstract-required (every
|
||||
/// instance must specify it); `Some(body)` when the method has a
|
||||
/// default body (instances may inherit or override).
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ClassMethod {
|
||||
/// Method name.
|
||||
pub name: String,
|
||||
/// Full method signature including any mode annotations. The
|
||||
/// class parameter appears as a [`Type::Var`] inside this signature.
|
||||
#[serde(rename = "type")]
|
||||
pub ty: Type,
|
||||
/// Default body. `None` ⇒ abstract-required; `Some(body)` ⇒
|
||||
/// default-with-fallback.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub default: Option<Term>,
|
||||
}
|
||||
|
||||
/// Iter 22b.1: an instance declaration (Decision 11).
|
||||
///
|
||||
/// `class` is the name of the class being instantiated. `type_` is the
|
||||
/// concrete type expression the class is applied to — never the class
|
||||
/// param. `methods` contains bodies for the required methods plus any
|
||||
/// overrides of default-bearing methods.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct InstanceDef {
|
||||
/// Class being instantiated.
|
||||
pub class: String,
|
||||
/// Concrete type the class is applied to.
|
||||
#[serde(rename = "type")]
|
||||
pub type_: Type,
|
||||
/// Method bodies in declaration order.
|
||||
pub methods: Vec<InstanceMethod>,
|
||||
/// Optional source-level documentation string.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub doc: Option<String>,
|
||||
}
|
||||
|
||||
/// Iter 22b.1: one method body in an [`InstanceDef`].
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct InstanceMethod {
|
||||
/// Method name (must match a method in the corresponding class).
|
||||
pub name: String,
|
||||
/// Method body. The class's declared method type with the class
|
||||
/// param substituted to the instance type is the body's expected
|
||||
/// type — checked in 22b.2.
|
||||
pub body: Term,
|
||||
}
|
||||
|
||||
/// A constant (top-level binding to a value).
|
||||
///
|
||||
/// Differs from a zero-arg [`FnDef`] in that it is evaluated once and
|
||||
|
||||
Reference in New Issue
Block a user