96 lines
2.6 KiB
Rust
96 lines
2.6 KiB
Rust
use std::{collections::{HashMap, LinkedList}, mem::Discriminant};
|
|
|
|
use super::{Identifier, value::Value, expr::Operation, types::{Type, PrimitiveType}, Declaration};
|
|
|
|
#[derive(Debug, Default, Clone)]
|
|
pub struct ValueBindings<'a>(Option<&'a ValueBindings<'a>>, HashMap<u128, Value>);
|
|
|
|
impl<'a> ValueBindings<'a> {
|
|
pub fn builtins() -> Self {
|
|
Self::default()
|
|
.bind(&Identifier::identifier_Int(), Value::Type(Type::Primitive(PrimitiveType::Int)))
|
|
}
|
|
|
|
pub fn bind(mut self, ident: &Identifier, value: Value) -> Self {
|
|
self.1.insert(ident.1 as u128, value);
|
|
self
|
|
}
|
|
|
|
pub fn bind_all(mut self, other: LinkedList<(&Identifier, &Value)>) -> Self{
|
|
self.1.extend(
|
|
other.into_iter()
|
|
.map(|(ident, val)| (ident.1 as u128, val.clone()))
|
|
);
|
|
self
|
|
}
|
|
|
|
pub fn bind_all_owned(mut self, other: LinkedList<(Identifier, Value)>) -> Self{
|
|
self.1.extend(
|
|
other.into_iter()
|
|
.map(|(ident, val)| (ident.1 as u128, val))
|
|
);
|
|
self
|
|
}
|
|
|
|
pub fn lookup(&self, ident: &Identifier) -> Option<&Value> {
|
|
self.1.get(&(ident.1 as u128))
|
|
.or_else(|| self.0.and_then(|binding| binding.lookup(ident)))
|
|
}
|
|
|
|
pub fn nested_scope(&'a self) -> ValueBindings<'a> {
|
|
ValueBindings(Some(self), HashMap::new())
|
|
}
|
|
|
|
pub fn get_main(&self) -> Option<&Value> {
|
|
self.1.get(&3).or_else(|| self.0.and_then(ValueBindings::get_main))
|
|
}
|
|
}
|
|
|
|
pub enum EvaluateError {
|
|
UndefinedValue(Identifier),
|
|
EvaluatingZeroLengthExpr,
|
|
ArgumentCountMismatch(Operation, usize, usize),
|
|
FunctionArgumentCountMismatch(usize, usize),
|
|
TypeMismatch(Discriminant<Value>, Discriminant<Value>),
|
|
NoMain,
|
|
MainHasArgs,
|
|
IncompleteConditional,
|
|
}
|
|
|
|
pub type Result = std::result::Result<Value, EvaluateError>;
|
|
|
|
pub fn display_program(program: Vec<Declaration>) -> std::result::Result<String, EvaluateError> {
|
|
let bindings = ValueBindings::builtins();
|
|
let bindings = program.iter()
|
|
.fold(bindings, |bindings, declaration|
|
|
bindings.bind(&declaration.identifier, declaration.value.clone())
|
|
);
|
|
|
|
program.into_iter()
|
|
.map(|decl| {
|
|
Ok(match decl.value.simplify(&bindings)? {
|
|
Value::Function(args, val) => {
|
|
format!(
|
|
"{0} has type {1}\n{0} takes the arguments: {2}\n",
|
|
decl.identifier,
|
|
decl.value_type.simplify(&bindings)?,
|
|
args.into_iter()
|
|
.map(|arg| arg.to_string())
|
|
.collect::<Vec<_>>()
|
|
.join(", "),
|
|
)
|
|
}
|
|
other => {
|
|
format!(
|
|
"{0} has type {1}\n{0} has the value {2}\n",
|
|
decl.identifier,
|
|
decl.value_type.simplify(&bindings)?,
|
|
other,
|
|
)
|
|
}
|
|
})
|
|
})
|
|
.collect::<std::result::Result<Vec<_>, _>>()
|
|
.map(|lines| lines.join("\n"))
|
|
}
|