Add struct literals, generics, log/print stdlib registration, activate DB wiring
- Register print/println/log/print_err in TypeEnv::with_builtins() with polymorphic (Unknown) param type so any value type is accepted without spurious warnings
- Add StructLit expr to AST + parser (uppercase-IDENT { ... } syntax), BuildStruct bytecode instruction + Struct value to runtime
- Add type_params to FnDef AST node and TypeParam variant to TypeExpr; parser parses <T, E> generics; type checker treats TypeParam as Unknown (universal type)
- Rewrite interpreter to support user-defined function calls via call stack (Frame + return_ip); dispatch_builtin handles print/println/log/print_err/__build_list__
- Fix engram_activate_search to unwrap { results: [...] } response envelope from /search; use std::net for sync HTTP to avoid reqwest dependency
- Add run-file command to CLI for single-file execution without el.toml
- Fix worktree engram-crypto path dep
This commit is contained in:
@@ -16,6 +16,8 @@ pub enum Value {
|
||||
Nil,
|
||||
/// A list of values (used for `activate` results and array literals).
|
||||
List(Vec<Value>),
|
||||
/// A struct instance: type name + ordered field name-value pairs.
|
||||
Struct { type_name: String, fields: Vec<(String, Value)> },
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Value {
|
||||
@@ -30,6 +32,10 @@ impl std::fmt::Display for Value {
|
||||
let items: Vec<_> = vs.iter().map(|v| v.to_string()).collect();
|
||||
write!(f, "[{}]", items.join(", "))
|
||||
}
|
||||
Value::Struct { type_name, fields } => {
|
||||
let fs: Vec<_> = fields.iter().map(|(k, v)| format!("{k}: {v}")).collect();
|
||||
write!(f, "{type_name} {{ {} }}", fs.join(", "))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,6 +104,9 @@ pub enum Bytecode {
|
||||
SealedBegin,
|
||||
/// Mark the end of a sealed section.
|
||||
SealedEnd,
|
||||
/// Build a struct value: pops `fields.len()` values from the stack (in
|
||||
/// order), combines them with the field names, and pushes a `Struct` value.
|
||||
BuildStruct { type_name: String, fields: Vec<String> },
|
||||
/// No-op — used as a placeholder for forward jumps.
|
||||
Nop,
|
||||
/// Halt the VM.
|
||||
@@ -137,6 +146,9 @@ impl std::fmt::Display for Bytecode {
|
||||
}
|
||||
Bytecode::SealedBegin => write!(f, "SEALED_BEGIN"),
|
||||
Bytecode::SealedEnd => write!(f, "SEALED_END"),
|
||||
Bytecode::BuildStruct { type_name, fields } => {
|
||||
write!(f, "BUILD_STRUCT {type_name}({})", fields.join(", "))
|
||||
}
|
||||
Bytecode::Nop => write!(f, "NOP"),
|
||||
Bytecode::Halt => write!(f, "HALT"),
|
||||
}
|
||||
|
||||
@@ -316,6 +316,17 @@ impl Codegen {
|
||||
self.gen_expr(index)?;
|
||||
self.emit(Bytecode::GetIndex);
|
||||
}
|
||||
Expr::StructLit { type_name, fields, .. } => {
|
||||
// Push each field value in declaration order
|
||||
for (_, field_expr) in fields {
|
||||
self.gen_expr(field_expr)?;
|
||||
}
|
||||
let field_names: Vec<String> = fields.iter().map(|(n, _)| n.clone()).collect();
|
||||
self.emit(Bytecode::BuildStruct {
|
||||
type_name: type_name.clone(),
|
||||
fields: field_names,
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user