Merge worktree-agent: add struct literals, generics, print/log builtins

This commit is contained in:
Will Anderson
2026-04-28 11:51:02 -05:00
40 changed files with 4058 additions and 72 deletions
+35
View File
@@ -441,6 +441,41 @@ impl TypeChecker {
Type::Map { key: Box::new(key_ty), value: Box::new(val_ty) }
}
}
Expr::StructLit { type_name, fields, .. } => {
// Look up the type definition
match self.env.get_type(type_name).cloned() {
Some(TypeDef::Struct { fields: declared_fields, .. }) => {
// Check that all provided fields are valid and have compatible types
for (field_name, field_expr) in fields {
let got_ty = self.infer_expr(field_expr);
if let Some((_, expected_ty)) = declared_fields.iter().find(|(n, _)| n == field_name) {
if !self.env.check_compatible(&got_ty, expected_ty) {
self.emit_error(TypeErrorKind::TypeMismatch {
expected: expected_ty.to_string(),
got: got_ty.to_string(),
});
}
} else {
self.emit_error(TypeErrorKind::UnknownField {
type_name: type_name.clone(),
field: field_name.clone(),
});
}
}
Type::Named(type_name.clone())
}
Some(_) => {
self.emit_error(TypeErrorKind::UndefinedType(
format!("{type_name} is not a struct type"),
));
Type::Unknown
}
None => {
self.emit_error(TypeErrorKind::UndefinedType(type_name.clone()));
Type::Unknown
}
}
}
}
}
+17
View File
@@ -97,6 +97,7 @@ pub struct TypeEnv {
}
impl TypeEnv {
/// Create a fresh environment pre-populated with built-in types and functions.
pub fn with_builtins() -> Self {
let mut env = Self::default();
env.types.insert("Int".into(), TypeDef::Primitive(Type::Int));
@@ -105,6 +106,17 @@ impl TypeEnv {
env.types.insert("Bool".into(), TypeDef::Primitive(Type::Bool));
env.types.insert("Uuid".into(), TypeDef::Primitive(Type::Uuid));
env.types.insert("Void".into(), TypeDef::Primitive(Type::Void));
// Register built-in output functions — accept any value (Unknown = polymorphic)
let void_fn_any = Type::Fn {
params: vec![Type::Unknown],
return_type: Box::new(Type::Void),
};
env.functions.insert("print".into(), void_fn_any.clone());
env.functions.insert("println".into(), void_fn_any.clone());
env.functions.insert("log".into(), void_fn_any.clone());
env.functions.insert("print_err".into(), void_fn_any);
env
}
@@ -274,6 +286,11 @@ impl TypeEnv {
let val_ty = self.resolve_type_expr(value)?;
Ok(Type::Map { key: Box::new(key_ty), value: Box::new(val_ty) })
}
el_parser::TypeExpr::TypeParam(_) => {
// Generic type parameters resolve to Unknown at the call site —
// the actual type is inferred from arguments during call checking.
Ok(Type::Unknown)
}
}
}
}