Skip to content
Merged
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
16 changes: 16 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,23 @@ These items can land as soon as E0c's `TypeRendering` boundary exists
and M4 Lane 1 Tier 2.5 corrects algebra profiles. They do not require
M4 completion or full language plugin extraction.

- [x] Coercion data structures in stage0 (`TypeCheckpoint`, `InhabitantDecl`,
`CallableRepr`, `CoercionRegistry`) mirroring `std/coercion.dag` schema
- [x] Per-language checkpoint + inhabitant data populated from
`dsl/extdeps/languages/{rust,python,go}/types.dag` declarations
- [x] `target_primitive_type` reads `CoercionRegistry.lookup_checkpoint`
instead of per-language `*_TYPE_MAP` hash maps
- [x] Container identity (`is_known_keyed_container_name`,
`is_known_element_container_name`) derived from inhabitant arity
- [x] `target_container_template_bare` provides algebra-based bare templates
for the TypeRendering path (no sharing wrapping baked in)
- [x] Per-language registries built once via `lazy_static` singletons
(`RUST_REGISTRY`, `PYTHON_REGISTRY`, etc.) — O(1) per lookup
- [x] 7 coercion registry tests: checkpoint resolution, cross-language
inhabitants, is_copy data, template application
- [ ] `build_type_rendering` reads `TypeCheckpoint` data for primitives
(currently reads through `target_primitive_type` → coercion registry;
needs direct integration for fail-closed contract)
- [ ] `build_type_rendering` reads `InhabitantDecl` data for algebra
containers (FreeMonoid → Vec, PartialFunction → HashMap, etc.)
- [ ] `build_type_rendering` reads `CallableRepr` for callable types
Expand Down
106 changes: 106 additions & 0 deletions src/v2/stage0/src/compiler_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,112 @@ mod compiler_tests {
);
}

// =========================================================================
// Coercion registry tests
// =========================================================================

#[test]
fn coercion_rust_checkpoint_resolves_primitives() {
use crate::v2_coercion::*;
use crate::v2_compiler_emit::RenderTarget;
let reg = registry_for_target(&RenderTarget::Rust);
assert_eq!(coerce_primitive_type(&reg, "Int"), "i64");
assert_eq!(coerce_primitive_type(&reg, "Float"), "f64");
assert_eq!(coerce_primitive_type(&reg, "Bool"), "bool");
assert_eq!(coerce_primitive_type(&reg, "String"), "String");
assert_eq!(coerce_primitive_type(&reg, "Unit"), "()");
assert_eq!(coerce_primitive_type(&reg, "Bytes"), "Vec<u8>");
assert_eq!(coerce_primitive_type(&reg, "Json"), "serde_json::Value");
// Unknown type falls through unchanged (transitional)
assert_eq!(coerce_primitive_type(&reg, "FooBar"), "FooBar");
}

#[test]
fn coercion_python_checkpoint_resolves_primitives() {
use crate::v2_coercion::*;
use crate::v2_compiler_emit::RenderTarget;
let reg = registry_for_target(&RenderTarget::Python);
assert_eq!(coerce_primitive_type(&reg, "Int"), "int");
assert_eq!(coerce_primitive_type(&reg, "String"), "str");
assert_eq!(coerce_primitive_type(&reg, "Bool"), "bool");
}

#[test]
fn coercion_go_checkpoint_resolves_primitives() {
use crate::v2_coercion::*;
use crate::v2_compiler_emit::RenderTarget;
let reg = registry_for_target(&RenderTarget::Go);
assert_eq!(coerce_primitive_type(&reg, "Int"), "int64");
assert_eq!(coerce_primitive_type(&reg, "String"), "string");
assert_eq!(coerce_primitive_type(&reg, "Unit"), "struct{}");
}

#[test]
fn coercion_inhabitant_resolves_containers() {
use crate::v2_coercion::*;
use crate::v2_compiler_emit::RenderTarget;
let rust = registry_for_target(&RenderTarget::Rust);
// FreeMonoid → Vec<{0}>
assert_eq!(
coerce_container_template(&rust, "List"),
Some("Vec<{0}>".to_string())
);
assert_eq!(
coerce_container_template(&rust, "FreeMonoid"),
Some("Vec<{0}>".to_string())
);
// PartialFunction → HashMap<{0}, {1}>
assert_eq!(
coerce_container_template(&rust, "Map"),
Some("HashMap<{0}, {1}>".to_string())
);
// BooleanAlgebra → BTreeSet<{0}>
assert_eq!(
coerce_container_template(&rust, "Set"),
Some("std::collections::BTreeSet<{0}>".to_string())
);
// Unknown container → None
assert_eq!(coerce_container_template(&rust, "FooBar"), None);
}

#[test]
fn coercion_cross_language_inhabitant_templates() {
use crate::v2_coercion::*;
use crate::v2_compiler_emit::RenderTarget;
let py = registry_for_target(&RenderTarget::Python);
assert_eq!(coerce_container_template(&py, "List"), Some("list[{0}]".to_string()));
assert_eq!(coerce_container_template(&py, "Map"), Some("dict[{0}, {1}]".to_string()));
assert_eq!(coerce_container_template(&py, "Set"), Some("set[{0}]".to_string()));

let go = registry_for_target(&RenderTarget::Go);
assert_eq!(coerce_container_template(&go, "List"), Some("[]{0}".to_string()));
assert_eq!(coerce_container_template(&go, "Map"), Some("map[{0}]{1}".to_string()));
assert_eq!(coerce_container_template(&go, "Set"), Some("map[{0}]struct{}".to_string()));
}

#[test]
fn coercion_is_copy_from_checkpoint() {
use crate::v2_coercion::*;
use crate::v2_compiler_emit::RenderTarget;
let rust = registry_for_target(&RenderTarget::Rust);
assert_eq!(rust.is_copy("Int"), Some(true));
assert_eq!(rust.is_copy("Bool"), Some(true));
assert_eq!(rust.is_copy("String"), Some(false));
assert_eq!(rust.is_copy("Unknown"), None);

let py = registry_for_target(&RenderTarget::Python);
assert_eq!(py.is_copy("Int"), None);
}

#[test]
fn coercion_template_application() {
use crate::v2_coercion::*;
assert_eq!(apply_inhabitant_template1("Vec<{0}>", "i64"), "Vec<i64>");
assert_eq!(apply_inhabitant_template2("HashMap<{0}, {1}>", "String", "i64"), "HashMap<String, i64>");
assert_eq!(apply_inhabitant_template1("[]{0}", "int64"), "[]int64");
assert_eq!(apply_inhabitant_template2("map[{0}]{1}", "string", "int64"), "map[string]int64");
}

/// Profile the gist pipeline by stage: tokenize, parse, resolve.
/// Reports per-file and per-stage wall-clock times.
#[test]
Expand Down
1 change: 1 addition & 0 deletions src/v2/stage0/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub mod v2_compiler_emit_go;
pub mod v2_compiler_emit_python;
pub mod v2_compiler_emit_rust;
pub mod v2_compiler_compile;
pub mod v2_coercion;
pub mod v2_rt;

#[cfg(test)]
Expand Down
Loading
Loading