test: red for env-construction drift-shape pin
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
//! Drift-shape pin for env construction (env-construction unify
|
||||
//! milestone). Asserts that `build_check_env(&ws)` agrees with an
|
||||
//! in-test reproduction of the pre-refactor inline seeding on every
|
||||
//! workspace-flat field. Future-you adds a new workspace-flat env
|
||||
//! field without updating `build_check_env` -> this test fails before
|
||||
//! the bug ships.
|
||||
//!
|
||||
//! Fixture: a two-module workspace covering one `Def::Class`, one
|
||||
//! `Def::Instance`, one user ADT, and one cross-module import (the
|
||||
//! same shape that `test_mono_imports_*` use).
|
||||
|
||||
use ailang_check::{build_check_env, build_module_globals, build_module_types, Env};
|
||||
use ailang_core::ast::Def;
|
||||
use ailang_core::load_workspace;
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::Path;
|
||||
|
||||
fn examples_dir() -> std::path::PathBuf {
|
||||
let manifest = env!("CARGO_MANIFEST_DIR");
|
||||
Path::new(manifest).parent().unwrap().parent().unwrap().join("examples")
|
||||
}
|
||||
|
||||
/// In-test reproduction of the pre-refactor `check_in_workspace`
|
||||
/// workspace-flat seeding (lib.rs as of commit a9c685d). Kept as a
|
||||
/// frozen reference: any future divergence between this body and
|
||||
/// `build_check_env` makes the assertion below fail.
|
||||
fn build_env_inline_pre_refactor(ws: &ailang_core::workspace::Workspace) -> Env {
|
||||
let mut env = Env::default();
|
||||
ailang_check::builtins::install(&mut env);
|
||||
|
||||
// env.types + env.ctor_index — workspace-flat from every Def::Type.
|
||||
for m in ws.modules.values() {
|
||||
for d in &m.defs {
|
||||
if let Def::Type(td) = d {
|
||||
for c in &td.ctors {
|
||||
env.ctor_index.insert(
|
||||
c.name.clone(),
|
||||
ailang_check::CtorRef { type_name: td.name.clone() },
|
||||
);
|
||||
}
|
||||
env.types.insert(td.name.clone(), td.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// env.module_globals — per-module .fns projection.
|
||||
let mg = build_module_globals(ws).expect("build_module_globals");
|
||||
env.module_globals = mg
|
||||
.iter()
|
||||
.map(|(k, v)| (k.clone(), v.fns.clone()))
|
||||
.collect();
|
||||
|
||||
// env.module_types — workspace-wide.
|
||||
env.module_types = build_module_types(ws);
|
||||
|
||||
// env.module_imports — per-module alias map.
|
||||
for m in ws.modules.values() {
|
||||
let mut import_map: BTreeMap<String, String> = BTreeMap::new();
|
||||
for imp in &m.imports {
|
||||
let key = imp.alias.clone().unwrap_or_else(|| imp.module.clone());
|
||||
import_map.insert(key, imp.module.clone());
|
||||
}
|
||||
env.module_imports.insert(m.name.clone(), import_map);
|
||||
}
|
||||
|
||||
// env.class_methods — workspace-merged from each module's
|
||||
// ModuleGlobals.class_methods.
|
||||
for g in mg.values() {
|
||||
for (n, e) in &g.class_methods {
|
||||
env.class_methods.insert(n.clone(), e.clone());
|
||||
}
|
||||
}
|
||||
|
||||
// env.class_superclasses — walk every module's Def::Class.
|
||||
for m in ws.modules.values() {
|
||||
for d in &m.defs {
|
||||
if let Def::Class(cd) = d {
|
||||
if let Some(sc) = &cd.superclass {
|
||||
env.class_superclasses.insert(cd.name.clone(), sc.class.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// env.workspace_registry — clone of ws.registry.
|
||||
env.workspace_registry = ws.registry.clone();
|
||||
|
||||
env
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_check_env_matches_inline_seeding() {
|
||||
let entry = examples_dir().join("test_mono_imports_main.ail.json");
|
||||
let ws = load_workspace(&entry).expect("load test_mono_imports_main");
|
||||
|
||||
let env_helper = build_check_env(&ws);
|
||||
let env_inline = build_env_inline_pre_refactor(&ws);
|
||||
|
||||
// env.types — IndexMap<String, TypeDef>: compare key-set + name.
|
||||
assert_eq!(
|
||||
env_helper.types.keys().collect::<Vec<_>>(),
|
||||
env_inline.types.keys().collect::<Vec<_>>(),
|
||||
"env.types key-set differs"
|
||||
);
|
||||
for k in env_helper.types.keys() {
|
||||
assert_eq!(
|
||||
env_helper.types[k].name,
|
||||
env_inline.types[k].name,
|
||||
"env.types[{k}] type-def name differs"
|
||||
);
|
||||
}
|
||||
|
||||
// env.ctor_index — IndexMap<String, CtorRef>: compare key-set +
|
||||
// type_name.
|
||||
assert_eq!(
|
||||
env_helper.ctor_index.keys().collect::<Vec<_>>(),
|
||||
env_inline.ctor_index.keys().collect::<Vec<_>>(),
|
||||
"env.ctor_index key-set differs"
|
||||
);
|
||||
for k in env_helper.ctor_index.keys() {
|
||||
assert_eq!(
|
||||
env_helper.ctor_index[k].type_name,
|
||||
env_inline.ctor_index[k].type_name,
|
||||
"env.ctor_index[{k}].type_name differs"
|
||||
);
|
||||
}
|
||||
|
||||
// env.module_globals — BTreeMap<String, IndexMap<String, Type>>.
|
||||
assert_eq!(
|
||||
env_helper.module_globals.keys().collect::<Vec<_>>(),
|
||||
env_inline.module_globals.keys().collect::<Vec<_>>(),
|
||||
"env.module_globals key-set differs"
|
||||
);
|
||||
for k in env_helper.module_globals.keys() {
|
||||
assert_eq!(
|
||||
env_helper.module_globals[k].keys().collect::<Vec<_>>(),
|
||||
env_inline.module_globals[k].keys().collect::<Vec<_>>(),
|
||||
"env.module_globals[{k}] inner key-set differs"
|
||||
);
|
||||
}
|
||||
|
||||
// env.module_types — same shape as module_globals.
|
||||
assert_eq!(
|
||||
env_helper.module_types.keys().collect::<Vec<_>>(),
|
||||
env_inline.module_types.keys().collect::<Vec<_>>(),
|
||||
"env.module_types key-set differs"
|
||||
);
|
||||
for k in env_helper.module_types.keys() {
|
||||
assert_eq!(
|
||||
env_helper.module_types[k].keys().collect::<Vec<_>>(),
|
||||
env_inline.module_types[k].keys().collect::<Vec<_>>(),
|
||||
"env.module_types[{k}] inner key-set differs"
|
||||
);
|
||||
}
|
||||
|
||||
// env.module_imports — BTreeMap<String, BTreeMap<String, String>>:
|
||||
// direct equality.
|
||||
assert_eq!(
|
||||
env_helper.module_imports, env_inline.module_imports,
|
||||
"env.module_imports differs"
|
||||
);
|
||||
|
||||
// env.class_methods — BTreeMap<String, ClassMethodEntry>:
|
||||
// compare key-set (entry shape has no PartialEq).
|
||||
assert_eq!(
|
||||
env_helper.class_methods.keys().collect::<Vec<_>>(),
|
||||
env_inline.class_methods.keys().collect::<Vec<_>>(),
|
||||
"env.class_methods key-set differs"
|
||||
);
|
||||
|
||||
// env.class_superclasses — direct equality.
|
||||
assert_eq!(
|
||||
env_helper.class_superclasses, env_inline.class_superclasses,
|
||||
"env.class_superclasses differs"
|
||||
);
|
||||
|
||||
// env.effect_ops — IndexMap<String, EffectOpSig>: compare key-set.
|
||||
assert_eq!(
|
||||
env_helper.effect_ops.keys().collect::<Vec<_>>(),
|
||||
env_inline.effect_ops.keys().collect::<Vec<_>>(),
|
||||
"env.effect_ops key-set differs"
|
||||
);
|
||||
|
||||
// env.workspace_registry — entries key-set must match.
|
||||
assert_eq!(
|
||||
env_helper.workspace_registry.entries.keys().collect::<Vec<_>>(),
|
||||
env_inline.workspace_registry.entries.keys().collect::<Vec<_>>(),
|
||||
"env.workspace_registry.entries key-set differs"
|
||||
);
|
||||
|
||||
// Per-call overlay fields must NOT be seeded by the helper.
|
||||
assert_eq!(env_helper.current_module, "", "current_module is overlay");
|
||||
assert!(env_helper.globals.is_empty(), "globals is overlay");
|
||||
assert!(env_helper.imports.is_empty(), "imports is overlay");
|
||||
assert!(env_helper.rigid_vars.is_empty(), "rigid_vars is overlay");
|
||||
}
|
||||
Reference in New Issue
Block a user