Skip to content
Merged

sg-4b #617

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,022 changes: 1,013 additions & 1,009 deletions src/v3/compiler/src/bootstrap_generated.rs

Large diffs are not rendered by default.

1,866 changes: 935 additions & 931 deletions src/v3/compiler/src/bootstrap_generated_without_runtime_mirrors.rs

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/v3/compiler/src/dag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1973,6 +1973,15 @@ impl Dag {
decl
}

/// Option-returning variant for the .dag substrate accessor
/// `declaration_by_id(d, id) -> Declaration?`. Same pattern as `node_opt`
/// / `port_opt`: permissive at the reflected-substrate boundary; C-8
/// fail-closed is enforced at the lens consumer that treats `None` as a
/// substrate-integrity violation (valid ids can't legitimately miss).
pub fn declaration_opt(&self, id: &DeclarationId) -> Option<&Declaration> {
self.declarations.get(id.index())
}

fn declaration_name_preference_rank(file: &str) -> usize {
if file.starts_with("src/v3/") {
2
Expand Down
12 changes: 10 additions & 2 deletions src/v3/compiler/src/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,10 @@ pub(crate) fn optional_match_variant_roles(
let mut payload_variant = None;
for variant in variants {
let shape = match variant_payload_shape(dag, &variant.ty) {
VariantPayloadShapeLookup::Missing => {
VariantPayloadShapeLookup::DeclarationMissing => {
return Err("optional branch variant references an absent declaration");
}
VariantPayloadShapeLookup::NotPayloadProduct => {
return Err("optional branch variants must lower to payload products");
}
VariantPayloadShapeLookup::Found { _0: shape } => shape,
Expand Down Expand Up @@ -2027,7 +2030,12 @@ impl<'a> Ctx<'a> {
binding_expr: &str,
) -> Result<Option<VariantPayloadBinding<String>>, EmitError> {
let shape = match variant_payload_shape(self.dag, &variant_id) {
VariantPayloadShapeLookup::Missing => {
VariantPayloadShapeLookup::DeclarationMissing => {
return Err(EmitError::UnsupportedBehavior(
"variant payload references an absent declaration".to_string(),
));
}
VariantPayloadShapeLookup::NotPayloadProduct => {
return Err(EmitError::UnsupportedBehavior(
"variant payload expected a product declaration".to_string(),
));
Expand Down
14 changes: 12 additions & 2 deletions src/v3/compiler/src/emit/python_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,12 @@ impl<'a> Ctx<'a> {
}
let variant_id = resolved_pattern_id(path)?;
let shape = match variant_payload_shape(self.dag, &variant_id) {
VariantPayloadShapeLookup::Missing => {
VariantPayloadShapeLookup::DeclarationMissing => {
return Err(EmitPythonError::Unsupported(
"variant payload references an absent declaration".to_string(),
));
}
VariantPayloadShapeLookup::NotPayloadProduct => {
return Ok(Some(VariantPayloadBinding::Direct("__match".to_string())));
}
VariantPayloadShapeLookup::Found { _0: shape } => shape,
Expand Down Expand Up @@ -1219,7 +1224,12 @@ impl<'a> Ctx<'a> {
return Ok(Some(format!("{runtime_name}()")));
}
let payload_shape = match variant_payload_shape(self.dag, &template) {
VariantPayloadShapeLookup::Missing => return Ok(None),
VariantPayloadShapeLookup::DeclarationMissing => {
return Err(EmitPythonError::Unsupported(
"variant constructor references an absent declaration".to_string(),
));
}
VariantPayloadShapeLookup::NotPayloadProduct => return Ok(None),
VariantPayloadShapeLookup::Found { _0: shape } => shape,
};
if matches!(payload_shape, VariantPayloadShape::PositionalSingle) {
Expand Down
14 changes: 12 additions & 2 deletions src/v3/compiler/src/emit/rust_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3563,7 +3563,12 @@ impl<'a> Ctx<'a> {
));
};
let payload_shape = match variant_payload_shape(self.dag, &resolved_id) {
VariantPayloadShapeLookup::Missing => {
VariantPayloadShapeLookup::DeclarationMissing => {
return Err(EmitError::UnsupportedBehavior(format!(
"matched variant `{variant_name}` references an absent declaration"
)));
}
VariantPayloadShapeLookup::NotPayloadProduct => {
return Err(EmitError::UnsupportedBehavior(format!(
"matched variant `{variant_name}` does not lower to a payload product"
)));
Expand Down Expand Up @@ -3712,7 +3717,12 @@ impl<'a> Ctx<'a> {
return Ok(None);
};
let shape = match variant_payload_shape(self.dag, variant_id) {
VariantPayloadShapeLookup::Missing => return Ok(None),
VariantPayloadShapeLookup::DeclarationMissing => {
return Err(EmitError::UnsupportedBehavior(
"variant payload binding references an absent declaration".to_string(),
));
}
VariantPayloadShapeLookup::NotPayloadProduct => return Ok(None),
VariantPayloadShapeLookup::Found { _0: shape } => shape,
};
let payload_binding_name = self.render_payload_binding_name(path, binding);
Expand Down
38 changes: 10 additions & 28 deletions src/v3/compiler/src/variant_payload_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,10 @@ pub enum VariantPayloadShape {
}
#[derive(Clone, Debug)]
pub enum VariantPayloadShapeLookup {
Missing,
DeclarationMissing,
NotPayloadProduct,
Found { _0: VariantPayloadShape },
}
#[derive(Clone, Debug)]
pub enum DeclarationLookup {
LookupMissing,
LookupFound { _0: Declaration },
}
pub fn find_declaration(p0: &[Declaration], p1: &DeclarationId) -> DeclarationLookup {
match p0 {
[] => DeclarationLookup::LookupMissing,
[__list_head, __list_tail @ ..] => {
if ((__list_head).id == (*(p1))) {
DeclarationLookup::LookupFound {
_0: (__list_head).clone(),
}
} else {
find_declaration(__list_tail, p1)
}
}
}
}
pub fn conj_field_label(p0: &Field) -> String {
((p0).label).clone()
}
Expand Down Expand Up @@ -61,27 +43,27 @@ pub fn conj_payload_shape(p0: &[Field]) -> VariantPayloadShape {
}
}
pub fn variant_payload_shape(p0: &Dag, p1: &DeclarationId) -> VariantPayloadShapeLookup {
match &(find_declaration((p0).declarations(), p1)) {
DeclarationLookup::LookupMissing => VariantPayloadShapeLookup::Missing,
DeclarationLookup::LookupFound { _0: decl } => match &((decl).connective) {
match &((p0).declaration_opt(p1).cloned()) {
None => VariantPayloadShapeLookup::DeclarationMissing,
Some(decl) => match &((decl).connective) {
TypeConnective::Conj { children: c } => VariantPayloadShapeLookup::Found {
_0: conj_payload_shape(c),
},
TypeConnective::Atom(_) => VariantPayloadShapeLookup::Missing,
TypeConnective::Disj { variants: _ } => VariantPayloadShapeLookup::Missing,
TypeConnective::Atom(_) => VariantPayloadShapeLookup::NotPayloadProduct,
TypeConnective::Disj { variants: _ } => VariantPayloadShapeLookup::NotPayloadProduct,
TypeConnective::Arrow {
inputs: _,
output: _,
body: _,
} => VariantPayloadShapeLookup::Missing,
} => VariantPayloadShapeLookup::NotPayloadProduct,
TypeConnective::Cardinality {
element: _,
bound: _,
} => VariantPayloadShapeLookup::Missing,
} => VariantPayloadShapeLookup::NotPayloadProduct,
TypeConnective::Instantiation {
template: _,
arguments: _,
} => VariantPayloadShapeLookup::Missing,
} => VariantPayloadShapeLookup::NotPayloadProduct,
},
}
}
4 changes: 2 additions & 2 deletions src/v3/compiler/tests/integration/m1_substrate_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2902,8 +2902,8 @@ fn substrate_accessor_rust_binding_invariants() {
checked += 1;
}
assert_eq!(
checked, 4,
"expected 4 substrate accessor bindings (port, node, resolve_producer, lane2_workflow)"
checked, 5,
"expected 5 substrate accessor bindings (port, node, resolve_producer, lane2_workflow, declaration_by_id)"
);
let missing: Vec<_> = universe.difference(&rust_covered).copied().collect();
assert!(
Expand Down
4 changes: 2 additions & 2 deletions src/v3/compiler/tests/integration/parse_corpus_manifest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ src/v3/compiler/tests/four_fixture_pressure/wrap.v3 4 5189 ac633b042c944480
src/v3/compiler/tokenize.dag 33 95264 0c164cce59b2cca9
src/v3/spec/go.dag 115 1042140 b9eab31358ae0a6f
src/v3/spec/python.dag 77 500558 1dddcfad58242e31
src/v3/spec/rust.dag 127 1099000 2413cc8741e0b21f
src/v3/spec/rust.dag 129 1104171 9d03eede663f4b01
src/v3/spec/v3_l1.dag 8 2238 1f55d782265c3bfe
src/v3/std/algebra.dag 33 281891 2a41cbb4d340fe43
src/v3/std/clean_emission.dag 15 23643 f0743c9828ee4a8e
Expand All @@ -31,7 +31,7 @@ src/v3/std/effects.dag 53 97508 011a56b9be40fb67
src/v3/std/emit_model.dag 31 60719 7f63d532f431fcc5
src/v3/std/list.dag 19 40241 721142de8452531f
src/v3/std/resources.dag 5 3632 5303e31e96b01ee5
src/v3/std/substrate.dag 46 104398 5181520784e9a58a
src/v3/std/substrate.dag 47 106283 fdc2120568de2036
src/v3/std/substrate_minimal.dag 8 5372 feeb314c735f4672
src/v3/std/verification.dag 16 28038 b5e6b3e17190069b
src/v3/std/workflows.dag 4 3135 bb6f9b042a02e8d6
42 changes: 20 additions & 22 deletions src/v3/lenses/variant_payload.dag
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,28 @@ module lenses.variant_payload

import std.list { List, empty, cons, map }
import std.substrate {
Dag, Declaration, DeclarationId, TypeConnective, ConjField
Dag, DeclarationId, TypeConnective, ConjField, declaration_by_id
}

type VariantPayloadShape
= Empty
| PositionalSingle
| NamedFields(List<String>)

// `DeclarationMissing` carries the substrate-integrity violation
// (`declaration_by_id` returned `None`): id-carriers can't legitimately
// reference an absent declaration, so consumers must fail closed.
// `NotPayloadProduct` is the ordinary outcome for declarations whose
// connective is not `Conj` (atoms, arrows, cardinalities, …) — callers
// that only care about product-shaped variants legitimately ignore it.
// Keeping the two distinct prevents a C-8 fail-open where a caller's
// `not-a-product` fallback would otherwise swallow a substrate-integrity
// miss.
type VariantPayloadShapeLookup
= Missing
= DeclarationMissing
| NotPayloadProduct
| Found(VariantPayloadShape)

type DeclarationLookup
= LookupMissing
| LookupFound(Declaration)

fn find_declaration(decls: List<Declaration>, target: DeclarationId) -> DeclarationLookup =
match decls {
Empty => LookupMissing
Cons(payload) =>
if payload.head.id == target then LookupFound(payload.head)
else find_declaration(payload.tail, target)
}

fn conj_field_label(f: ConjField) -> String =
f.label

Expand All @@ -51,15 +49,15 @@ fn conj_payload_shape(children: List<ConjField>) -> VariantPayloadShape =
}

fn variant_payload_shape(d: Dag, variant_id: DeclarationId) -> VariantPayloadShapeLookup =

This comment was marked as resolved.

match find_declaration(d.declarations, variant_id) {
LookupMissing => Missing
LookupFound(decl) =>
match declaration_by_id(d, variant_id) {
None => DeclarationMissing
Some(decl) =>
match decl.connective {
Conj(c) => Found(conj_payload_shape(c.children))
Atom(_) => Missing
Disj(_) => Missing
Arrow(_) => Missing
Cardinality(_) => Missing
Instantiation(_) => Missing
Atom(_) => NotPayloadProduct
Disj(_) => NotPayloadProduct
Arrow(_) => NotPayloadProduct
Cardinality(_) => NotPayloadProduct
Instantiation(_) => NotPayloadProduct
}
}
17 changes: 16 additions & 1 deletion src/v3/spec/rust.dag
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ import v3.std.emit_model {
}
import v3.std.substrate {
SubstrateAccessorRealization, SubstrateAccessorBinding,
port, node, resolve_producer, lane2_workflow_at
port, node, resolve_producer, lane2_workflow_at, declaration_by_id
}
import v3.std.clean_emission {
CleanEmissionContract,
Expand Down Expand Up @@ -1289,3 +1289,18 @@ data lane2_workflow_at_binding_rust: SubstrateAccessorBinding = {
realization: rust_lane2_workflow_accessor
language: rust_language
}

// `declaration_by_id(d: Dag, id: DeclarationId) -> Declaration?` —
// id-keyed parity with `port` / `node`. Host realization is
// `Dag::declaration_opt(&DeclarationId)`; `.cloned()` mirrors the
// `port` / `node` accessor shape so the reflected `Declaration?`
// return type carries owned data at the substrate boundary.
data rust_declaration_by_id_accessor: SubstrateAccessorRealization = {
carrier: "({p0}).declaration_opt({p1}).cloned()"
}

data declaration_by_id_binding_rust: SubstrateAccessorBinding = {
accessor: declaration_by_id
realization: rust_declaration_by_id_accessor
language: rust_language
}
9 changes: 9 additions & 0 deletions src/v3/std/substrate.dag
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,15 @@ fn resolve_producer(d: Dag, port_id: PortId) -> Behavior? {
host resolve_producer
}

// Declaration-by-id accessor — id-keyed lookup parity with `port` / `node`.
// `Declaration?` mirrors the permissive reflected-substrate shape; C-8
// fail-closed lives at the caller, which treats `None` as a
// constructor-layer violation (valid `DeclarationId`s can't legitimately
// miss).
fn declaration_by_id(d: Dag, id: DeclarationId) -> Declaration? {
host declaration_by_id
}

// Lane 2 Stage 2b — reads the optional workflow fact installed on `Value` /
// `Bind` roots (same authority as `Dag::lane2_workflow_effect_at` on the Rust
// side). Target emitters map this accessor via `SubstrateAccessorBinding`.
Expand Down
Loading