Implement running main
parent
a1e5aef811
commit
501dfff220
|
@ -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,17 +94,31 @@ 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())?;
|
||||||
|
self.call_closure(&callee, arguments)
|
||||||
|
}
|
||||||
|
Expression::Boolean(b) => Ok(Value::Boolean(*b)),
|
||||||
|
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() {
|
if parameters.len() != arguments.len() {
|
||||||
return Err(Error::ArgumentsMismatch(parameters.len(), arguments.len()));
|
return Err(Error::ArgumentsMismatch(parameters.len(), arguments.len()));
|
||||||
}
|
}
|
||||||
let mut nested = self.clone();
|
let mut nested = Interpreter::nested(environment.clone());
|
||||||
for (name, argument) in parameters.iter().zip(arguments) {
|
for (name, argument) in parameters.iter().zip(arguments) {
|
||||||
// we don't want arguments to refer to each other, so use the parent interpreter
|
// we don't want arguments to refer to each other, so use the parent interpreter
|
||||||
nested.bind(name.clone(), argument)?;
|
nested.bind(name.clone(), argument)?;
|
||||||
|
@ -105,9 +126,6 @@ impl Interpreter {
|
||||||
nested.evaluate(result)
|
nested.evaluate(result)
|
||||||
}
|
}
|
||||||
_ => Err(Error::NotAFunction),
|
_ => Err(Error::NotAFunction),
|
||||||
},
|
|
||||||
Expression::Boolean(b) => Ok(Value::Boolean(*b)),
|
|
||||||
Expression::Integer(i) => Ok(Value::Integer(*i)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue