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:
+24
-3
@@ -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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user