feat: implement Schema module for versioned types
Add Schema module with functions for creating and migrating versioned values. This provides the runtime foundation for schema evolution. Schema module functions: - Schema.versioned(typeName, version, value) - create versioned value - Schema.migrate(value, targetVersion) - migrate to new version - Schema.getVersion(value) - get version number Changes: - Add Versioned, Migrate, GetVersion builtins to interpreter - Add Schema module to global environment - Add Schema module type to type environment - Add 4 tests for schema operations - Add examples/versioning.lux demonstrating usage Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,11 @@ pub enum BuiltinFn {
|
||||
Print,
|
||||
ToString,
|
||||
TypeOf,
|
||||
|
||||
// Schema Evolution
|
||||
Versioned, // Create versioned value: versioned("TypeName", 1, value)
|
||||
Migrate, // Migrate to version: migrate(versionedValue, targetVersion)
|
||||
GetVersion, // Get version number: getVersion(versionedValue)
|
||||
}
|
||||
|
||||
/// Runtime value
|
||||
@@ -770,6 +775,20 @@ impl Interpreter {
|
||||
env.define("print", Value::Builtin(BuiltinFn::Print));
|
||||
env.define("toString", Value::Builtin(BuiltinFn::ToString));
|
||||
env.define("typeOf", Value::Builtin(BuiltinFn::TypeOf));
|
||||
|
||||
// Schema Evolution module
|
||||
let schema_module = Value::Record(HashMap::from([
|
||||
(
|
||||
"versioned".to_string(),
|
||||
Value::Builtin(BuiltinFn::Versioned),
|
||||
),
|
||||
("migrate".to_string(), Value::Builtin(BuiltinFn::Migrate)),
|
||||
(
|
||||
"getVersion".to_string(),
|
||||
Value::Builtin(BuiltinFn::GetVersion),
|
||||
),
|
||||
]));
|
||||
env.define("Schema", schema_module);
|
||||
}
|
||||
|
||||
/// Execute a program
|
||||
@@ -1860,6 +1879,72 @@ impl Interpreter {
|
||||
args[0].type_name().to_string(),
|
||||
)))
|
||||
}
|
||||
|
||||
// Schema Evolution
|
||||
BuiltinFn::Versioned => {
|
||||
// versioned(typeName: String, version: Int, value: Any) -> Versioned
|
||||
if args.len() != 3 {
|
||||
return Err(err("Schema.versioned requires 3 arguments: typeName, version, value"));
|
||||
}
|
||||
let type_name = match &args[0] {
|
||||
Value::String(s) => s.clone(),
|
||||
_ => return Err(err("Schema.versioned: first argument must be a String")),
|
||||
};
|
||||
let version = match &args[1] {
|
||||
Value::Int(n) => *n as u32,
|
||||
_ => return Err(err("Schema.versioned: second argument must be an Int")),
|
||||
};
|
||||
Ok(EvalResult::Value(Value::Versioned {
|
||||
type_name,
|
||||
version,
|
||||
value: Box::new(args[2].clone()),
|
||||
}))
|
||||
}
|
||||
|
||||
BuiltinFn::Migrate => {
|
||||
// migrate(value: Versioned, targetVersion: Int) -> Versioned
|
||||
if args.len() != 2 {
|
||||
return Err(err("Schema.migrate requires 2 arguments: value, targetVersion"));
|
||||
}
|
||||
let target = match &args[1] {
|
||||
Value::Int(n) => *n as u32,
|
||||
_ => return Err(err("Schema.migrate: second argument must be an Int")),
|
||||
};
|
||||
match &args[0] {
|
||||
Value::Versioned { type_name, version, value } => {
|
||||
if *version == target {
|
||||
// Same version, return as-is
|
||||
Ok(EvalResult::Value(args[0].clone()))
|
||||
} else if *version < target {
|
||||
// Upgrade - for now just update version (no migration logic)
|
||||
Ok(EvalResult::Value(Value::Versioned {
|
||||
type_name: type_name.clone(),
|
||||
version: target,
|
||||
value: value.clone(),
|
||||
}))
|
||||
} else {
|
||||
Err(err(&format!(
|
||||
"Cannot downgrade from version {} to {}",
|
||||
version, target
|
||||
)))
|
||||
}
|
||||
}
|
||||
_ => Err(err("Schema.migrate: first argument must be a Versioned value")),
|
||||
}
|
||||
}
|
||||
|
||||
BuiltinFn::GetVersion => {
|
||||
// getVersion(value: Versioned) -> Int
|
||||
if args.len() != 1 {
|
||||
return Err(err("Schema.getVersion requires 1 argument"));
|
||||
}
|
||||
match &args[0] {
|
||||
Value::Versioned { version, .. } => {
|
||||
Ok(EvalResult::Value(Value::Int(*version as i64)))
|
||||
}
|
||||
_ => Err(err("Schema.getVersion: argument must be a Versioned value")),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user