Add tuple and map literals

This commit introduces support for tuple and map literals in the AST.
Tuples are now represented by `UntypedKind::Tuple` and maps by
`UntypedKind::Map`.
The `Binder` has been updated to correctly handle these new node types
and infer their types.
The `VM` now also supports evaluating tuple and map literals.
This commit is contained in:
Michael Schimmel
2026-02-17 13:07:17 +01:00
parent d55422272b
commit 9afde5a301
5 changed files with 92 additions and 177 deletions
+24 -3
View File
@@ -1,5 +1,6 @@
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
use std::any::Any;
use crate::ast::compiler::bound_nodes::{Address, BoundKind};
use crate::ast::nodes::Node;
@@ -28,9 +29,6 @@ struct CallFrame {
pub struct VM {
stack: Vec<Value>,
// Globals are mutable shared state within the VM thread.
// However, if we move to frozen roots, this might change to a read-only structure.
// For now, mutable RefCell Vec is fine for single threaded execution.
globals: Rc<RefCell<Vec<Value>>>,
frames: Vec<CallFrame>,
}
@@ -151,6 +149,29 @@ impl VM {
},
_ => Err(format!("Attempt to call non-function: {}", func_val)),
}
},
BoundKind::Tuple { elements } => {
let mut vals = Vec::with_capacity(elements.len());
for e in elements {
vals.push(self.eval(e)?);
}
Ok(Value::List(Rc::new(vals)))
},
BoundKind::Map { entries } => {
let mut map = HashMap::new();
for (k, v) in entries {
let key = self.eval(k)?;
let val = self.eval(v)?;
if let Value::Keyword(kw) = key {
map.insert(kw, val);
} else {
return Err(format!("Map key must be keyword, got {}", key));
}
}
Ok(Value::Record(Rc::new(map)))
}
}
}