Implement running main

main
mat ess 2023-07-21 09:40:38 -04:00
parent a1e5aef811
commit 501dfff220
1 changed files with 47 additions and 29 deletions

View File

@ -8,7 +8,11 @@ pub type Dictionary<T> = HashMap<Name, T>;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Value { pub enum Value {
Closure(Dictionary<Value>, Vec<Name>, Expression), Closure {
environment: Dictionary<Value>,
parameters: Vec<Name>,
result: Expression,
},
Boolean(bool), Boolean(bool),
Integer(i64), Integer(i64),
} }
@ -19,7 +23,7 @@ pub enum Error {
UnboundName(Name), UnboundName(Name),
#[error("Tried to call a term which was not a function")] #[error("Tried to call a term which was not a function")]
NotAFunction, NotAFunction,
#[error("Mismatched number of function arguments and parameters: expected {0}, got {1}")] #[error("Mismatched number of function parameters and arguments: expected {0}, got {1}")]
ArgumentsMismatch(usize, usize), ArgumentsMismatch(usize, usize),
#[error("No function called main to run")] #[error("No function called main to run")]
MissingMainFunction, MissingMainFunction,
@ -39,13 +43,16 @@ impl Interpreter {
} }
} }
fn nested(environment: Dictionary<Value>) -> Self {
Interpreter { environment }
}
pub fn run(&mut self, program: &Program) -> Result<Value> { pub fn run(&mut self, program: &Program) -> Result<Value> {
for item in program { for item in program {
self.interpret_item(item)?; self.interpret_item(item)?;
} }
if let Some(main) = self.environment.get("main") { if let Some(main) = self.environment.get("main").cloned() {
// should main be an expression? a standalone closure type? self.call_closure(&main, &vec![])
todo!()
} else { } else {
Err(Error::MissingMainFunction) Err(Error::MissingMainFunction)
} }
@ -58,11 +65,11 @@ impl Interpreter {
parameters, parameters,
body, body,
} => { } => {
let closure = Value::Closure( let closure = Value::Closure {
self.environment.clone(), environment: self.environment.clone(),
parameters.clone(), parameters: parameters.clone(),
Expression::Block(Box::new(body.clone())), result: Expression::Block(Box::new(body.clone())),
); };
self.environment.insert(name.clone(), closure.clone()); self.environment.insert(name.clone(), closure.clone());
Ok(closure) Ok(closure)
} }
@ -87,30 +94,41 @@ impl Interpreter {
.ok_or(Error::UnboundName(name.clone())) .ok_or(Error::UnboundName(name.clone()))
.cloned(), .cloned(),
Expression::Block(b) => self.evaluate_block(b.as_ref()), Expression::Block(b) => self.evaluate_block(b.as_ref()),
Expression::Lambda { parameters, result } => Ok(Value::Closure( Expression::Lambda { parameters, result } => Ok(Value::Closure {
self.environment.clone(), environment: self.environment.clone(),
parameters.clone(), parameters: parameters.clone(),
*result.clone(), result: *result.clone(),
)), }),
Expression::Call { callee, arguments } => match callee.as_ref() { Expression::Call { callee, arguments } => {
Expression::Lambda { parameters, result } => { let callee = self.evaluate(callee.as_ref())?;
if parameters.len() != arguments.len() { self.call_closure(&callee, arguments)
return Err(Error::ArgumentsMismatch(parameters.len(), arguments.len())); }
}
let mut nested = self.clone();
for (name, argument) in parameters.iter().zip(arguments) {
// we don't want arguments to refer to each other, so use the parent interpreter
nested.bind(name.clone(), argument)?;
}
nested.evaluate(result)
}
_ => Err(Error::NotAFunction),
},
Expression::Boolean(b) => Ok(Value::Boolean(*b)), Expression::Boolean(b) => Ok(Value::Boolean(*b)),
Expression::Integer(i) => Ok(Value::Integer(*i)), Expression::Integer(i) => Ok(Value::Integer(*i)),
} }
} }
fn call_closure(&mut self, callee: &Value, arguments: &Vec<Expression>) -> Result<Value> {
match callee {
Value::Closure {
environment,
parameters,
result,
} => {
if parameters.len() != arguments.len() {
return Err(Error::ArgumentsMismatch(parameters.len(), arguments.len()));
}
let mut nested = Interpreter::nested(environment.clone());
for (name, argument) in parameters.iter().zip(arguments) {
// we don't want arguments to refer to each other, so use the parent interpreter
nested.bind(name.clone(), argument)?;
}
nested.evaluate(result)
}
_ => Err(Error::NotAFunction),
}
}
fn evaluate_block(&mut self, block: &Block) -> Result<Value> { fn evaluate_block(&mut self, block: &Block) -> Result<Value> {
let mut nested = self.clone(); let mut nested = self.clone();
for binding in &block.bindings { for binding in &block.bindings {