Reorganize

main
mat ess 2023-07-24 12:22:57 -04:00
parent 501dfff220
commit e84b351daa
5 changed files with 59 additions and 17 deletions

View File

@ -1,13 +1,15 @@
use std::collections::HashMap; use std::{collections::HashMap, fmt::Display};
use thiserror::Error; use thiserror::Error;
use crate::builtins::{self, Builtin};
use crate::syntax::{Block, Expression, InteractiveEntry, Item, Name, Program}; use crate::syntax::{Block, Expression, InteractiveEntry, Item, Name, Program};
pub type Dictionary<T> = HashMap<Name, T>; pub type Dictionary<T> = HashMap<Name, T>;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Value { pub enum Value {
Builtin(Builtin),
Closure { Closure {
environment: Dictionary<Value>, environment: Dictionary<Value>,
parameters: Vec<Name>, parameters: Vec<Name>,
@ -15,6 +17,19 @@ pub enum Value {
}, },
Boolean(bool), Boolean(bool),
Integer(i64), Integer(i64),
Unit,
}
impl Display for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Value::Builtin(b) => write!(f, "<builtin:{b:?}>"),
Value::Closure { parameters, .. } => write!(f, "<closure({})>", parameters.join(", ")),
Value::Boolean(b) => write!(f, "{b}"),
Value::Integer(i) => write!(f, "{i}"),
Value::Unit => write!(f, "()"),
}
}
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]
@ -27,9 +42,11 @@ pub enum Error {
ArgumentsMismatch(usize, usize), ArgumentsMismatch(usize, usize),
#[error("No function called main to run")] #[error("No function called main to run")]
MissingMainFunction, MissingMainFunction,
#[error("Problem with builtin call: {0}")]
BuiltinError(#[from] builtins::Error),
} }
pub type Result<T> = std::result::Result<T, Error>; type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Interpreter { pub struct Interpreter {
@ -39,7 +56,7 @@ pub struct Interpreter {
impl Interpreter { impl Interpreter {
pub fn new() -> Self { pub fn new() -> Self {
Interpreter { Interpreter {
environment: Dictionary::new(), environment: Builtin::dictionary(),
} }
} }
@ -52,7 +69,7 @@ impl Interpreter {
self.interpret_item(item)?; self.interpret_item(item)?;
} }
if let Some(main) = self.environment.get("main").cloned() { if let Some(main) = self.environment.get("main").cloned() {
self.call_closure(&main, &vec![]) self.apply_call(&main, &vec![])
} else { } else {
Err(Error::MissingMainFunction) Err(Error::MissingMainFunction)
} }
@ -101,14 +118,15 @@ impl Interpreter {
}), }),
Expression::Call { callee, arguments } => { Expression::Call { callee, arguments } => {
let callee = self.evaluate(callee.as_ref())?; let callee = self.evaluate(callee.as_ref())?;
self.call_closure(&callee, arguments) self.apply_call(&callee, arguments)
} }
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)),
Expression::Unit => Ok(Value::Unit),
} }
} }
fn call_closure(&mut self, callee: &Value, arguments: &Vec<Expression>) -> Result<Value> { fn apply_call(&mut self, callee: &Value, arguments: &Vec<Expression>) -> Result<Value> {
match callee { match callee {
Value::Closure { Value::Closure {
environment, environment,
@ -121,10 +139,27 @@ impl Interpreter {
let mut nested = Interpreter::nested(environment.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)?; self.bind_nested(name.clone(), argument, &mut nested)?;
} }
nested.evaluate(result) nested.evaluate(result)
} }
Value::Builtin(b) => {
if arguments.len() < b.min_parameters() {
return Err(Error::ArgumentsMismatch(
b.min_parameters(),
arguments.len(),
));
} else if let Some(max) = b.max_parameters() {
if arguments.len() > max {
return Err(Error::ArgumentsMismatch(max, arguments.len()));
}
}
let arguments = arguments
.iter()
.map(|term| self.evaluate(term))
.collect::<Result<Vec<_>>>()?;
b.call(arguments).map_err(Error::BuiltinError)
}
_ => Err(Error::NotAFunction), _ => Err(Error::NotAFunction),
} }
} }
@ -142,6 +177,17 @@ impl Interpreter {
self.environment.insert(name, value.clone()); self.environment.insert(name, value.clone());
Ok(value) Ok(value)
} }
fn bind_nested(
&mut self,
name: Name,
term: &Expression,
nested: &mut Interpreter,
) -> Result<Value> {
let value = self.evaluate(term)?;
nested.environment.insert(name, value.clone());
Ok(value)
}
} }
impl Default for Interpreter { impl Default for Interpreter {

View File

@ -1,3 +1,5 @@
pub mod builtins;
pub mod cli; pub mod cli;
pub mod phase; pub mod evaluate;
pub mod parse;
pub mod syntax; pub mod syntax;

View File

@ -2,9 +2,9 @@ use lalrpop_util::{lalrpop_mod, lexer::Token, ParseError};
use crate::syntax::{InteractiveEntry, Program}; use crate::syntax::{InteractiveEntry, Program};
lalrpop_mod!(parser, "/phase/parse/parser.rs"); lalrpop_mod!(parser, "/parse/parser.rs");
pub type Result<'input, T> = std::result::Result<T, ParseError<usize, Token<'input>, &'static str>>; type Result<'input, T> = std::result::Result<T, ParseError<usize, Token<'input>, &'static str>>;
pub fn parse_program(input: &str) -> Result<Program> { pub fn parse_program(input: &str) -> Result<Program> {
parser::ProgramParser::new().parse(input) parser::ProgramParser::new().parse(input)

View File

@ -41,6 +41,7 @@ Atom: Expression = {
Integer => Expression::Integer(<>), Integer => Expression::Integer(<>),
Boolean => Expression::Boolean(<>), Boolean => Expression::Boolean(<>),
"(" <Expression> ")", "(" <Expression> ")",
"(" ")" => Expression::Unit,
}; };
BlockBinding = <Binding> ";"; BlockBinding = <Binding> ";";

View File

@ -1,7 +0,0 @@
pub mod parse;
// |
// |
// syntax
// |
// v
pub mod evaluate;