Reorganize
parent
501dfff220
commit
e84b351daa
|
@ -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 {
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
|
@ -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> ";";
|
|
@ -1,7 +0,0 @@
|
||||||
pub mod parse;
|
|
||||||
// |
|
|
||||||
// |
|
|
||||||
// syntax
|
|
||||||
// |
|
|
||||||
// v
|
|
||||||
pub mod evaluate;
|
|
Loading…
Reference in New Issue