feat(prelude): add print function
This commit is contained in:
parent
b51e185c21
commit
8f1b1840ad
@ -1,3 +1,5 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
use super::environment::Environment;
|
use super::environment::Environment;
|
||||||
use super::environment::EnvironmentLayer;
|
use super::environment::EnvironmentLayer;
|
||||||
use super::expression::Expression;
|
use super::expression::Expression;
|
||||||
@ -13,6 +15,19 @@ pub enum EvalError {
|
|||||||
NotASymbol(Expression),
|
NotASymbol(Expression),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for EvalError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
EvalError::SymbolNotBound(s) => write!(f, "Symbol {} is not bound", s),
|
||||||
|
EvalError::NotAFunction(e) => write!(f, "Expression {} is not a function", e),
|
||||||
|
EvalError::NotANumber(e) => write!(f, "Expression {} is not a number", e),
|
||||||
|
EvalError::ArgumentError(s) => write!(f, "Argument error: {}", s),
|
||||||
|
EvalError::TypeError(s) => write!(f, "Type error: {}", s),
|
||||||
|
EvalError::NotASymbol(e) => write!(f, "Expression {} is not a symbol", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A CellIterator is a convenience struct to iterate a linked cons list.
|
/// A CellIterator is a convenience struct to iterate a linked cons list.
|
||||||
/// The Iterator returns Ok(Expression) as long, as there are elements in the list.
|
/// The Iterator returns Ok(Expression) as long, as there are elements in the list.
|
||||||
/// Err(EvalError) is returned when the right side of a cons cell is not another cons cell or nil.
|
/// Err(EvalError) is returned when the right side of a cons cell is not another cons cell or nil.
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
use super::environment::Environment;
|
use super::environment::Environment;
|
||||||
use super::eval::CellIterator;
|
use super::eval::CellIterator;
|
||||||
use super::eval::EvalError;
|
use super::eval::EvalError;
|
||||||
@ -36,6 +38,24 @@ impl From<fn(&Environment, Expression) -> Result<Expression, EvalError>> for Exp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Vec<Expression>> for Expression {
|
||||||
|
fn from(mut value: Vec<Expression>) -> Self {
|
||||||
|
let mut current = Expression::Nil;
|
||||||
|
|
||||||
|
for e in value.iter_mut().rev() {
|
||||||
|
current = Expression::Cell(Box::new(e.to_owned()), Box::new(current));
|
||||||
|
}
|
||||||
|
|
||||||
|
current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(Expression, Expression)> for Expression {
|
||||||
|
fn from(value: (Expression, Expression)) -> Self {
|
||||||
|
Expression::Cell(Box::new(value.0), Box::new(value.1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryInto<i64> for Expression {
|
impl TryInto<i64> for Expression {
|
||||||
type Error = EvalError;
|
type Error = EvalError;
|
||||||
fn try_into(self) -> Result<i64, Self::Error> {
|
fn try_into(self) -> Result<i64, Self::Error> {
|
||||||
@ -48,15 +68,27 @@ impl TryInto<i64> for Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<Expression>> for Expression {
|
impl TryInto<f64> for Expression {
|
||||||
fn from(mut value: Vec<Expression>) -> Self {
|
type Error = EvalError;
|
||||||
let mut current = Expression::Nil;
|
fn try_into(self) -> Result<f64, Self::Error> {
|
||||||
|
match self {
|
||||||
for e in value.iter_mut().rev() {
|
Expression::Float(f) => Ok(f),
|
||||||
current = Expression::Cell(Box::new(e.to_owned()), Box::new(current));
|
_ => Err(EvalError::TypeError(
|
||||||
|
"Expression is not a Float".to_string(),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
current
|
impl TryInto<String> for Expression {
|
||||||
|
type Error = EvalError;
|
||||||
|
fn try_into(self) -> Result<String, Self::Error> {
|
||||||
|
match self {
|
||||||
|
Expression::String(s) => Ok(s),
|
||||||
|
_ => Err(EvalError::TypeError(
|
||||||
|
"Expression is not a String".to_string(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,3 +123,35 @@ impl TryInto<(Expression, Expression)> for Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Expression {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Expression::Cell(a, b) => {
|
||||||
|
match self.clone().try_into() as Result<Vec<Expression>, EvalError> {
|
||||||
|
Ok(lst) => write!(
|
||||||
|
f,
|
||||||
|
"({})",
|
||||||
|
lst.iter()
|
||||||
|
.map(|e| e.to_string())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(" ")
|
||||||
|
),
|
||||||
|
Err(_) => write!(f, "({} . {})", a, b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expression::Function(_) => write!(f, "<function>"),
|
||||||
|
Expression::AnonymousFunction {
|
||||||
|
argument_symbols,
|
||||||
|
body,
|
||||||
|
} => write!(f, "(lambda ({}) {})", argument_symbols.join(" "), body),
|
||||||
|
Expression::Quote(e) => write!(f, "'{}", e),
|
||||||
|
Expression::Symbol(s) => write!(f, "{}", s),
|
||||||
|
Expression::Integer(i) => write!(f, "{}", i),
|
||||||
|
Expression::Float(fl) => write!(f, "{}", fl),
|
||||||
|
Expression::String(s) => write!(f, "\"{}\"", s),
|
||||||
|
Expression::True => write!(f, "true"),
|
||||||
|
Expression::Nil => write!(f, "nil"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -170,6 +170,13 @@ pub fn prelude_set(env: &Environment, expr: Expression) -> Result<Expression, Ev
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn prelude_print(env: &Environment, expr: Expression) -> Result<Expression, EvalError> {
|
||||||
|
let [e] = expr.try_into()?;
|
||||||
|
let e = eval(env, e)?;
|
||||||
|
println!("Prelude: {}", e);
|
||||||
|
Ok(e)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mk_prelude(layer: &mut EnvironmentLayer) {
|
pub fn mk_prelude(layer: &mut EnvironmentLayer) {
|
||||||
layer.set("+".to_string(), Expression::Function(prelude_add));
|
layer.set("+".to_string(), Expression::Function(prelude_add));
|
||||||
layer.set("-".to_string(), Expression::Function(prelude_sub));
|
layer.set("-".to_string(), Expression::Function(prelude_sub));
|
||||||
@ -182,4 +189,5 @@ pub fn mk_prelude(layer: &mut EnvironmentLayer) {
|
|||||||
layer.set(">".to_string(), Expression::Function(prelude_gt));
|
layer.set(">".to_string(), Expression::Function(prelude_gt));
|
||||||
layer.set("let".to_string(), Expression::Function(prelude_let));
|
layer.set("let".to_string(), Expression::Function(prelude_let));
|
||||||
layer.set("set".to_string(), Expression::Function(prelude_set));
|
layer.set("set".to_string(), Expression::Function(prelude_set));
|
||||||
|
layer.set("print".to_string(), Expression::Function(prelude_print));
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/main.rs
16
src/main.rs
@ -7,9 +7,9 @@ use crate::lisp::{eval, Environment};
|
|||||||
fn main() {
|
fn main() {
|
||||||
let program1 = "((lambda (x y) (+ (if (< x 10) (* x 11) x) y)) 2 20)";
|
let program1 = "((lambda (x y) (+ (if (< x 10) (* x 11) x) y)) 2 20)";
|
||||||
let program2 = "(set myvar \"hello world!\")";
|
let program2 = "(set myvar \"hello world!\")";
|
||||||
let program3 = "myvar";
|
let program3 = "(print myvar)";
|
||||||
|
|
||||||
let mut environment = Environment::default();
|
let environment = Environment::default();
|
||||||
|
|
||||||
for r in ExpressionStream::from_char_stream(
|
for r in ExpressionStream::from_char_stream(
|
||||||
program1
|
program1
|
||||||
@ -19,11 +19,13 @@ fn main() {
|
|||||||
) {
|
) {
|
||||||
match r {
|
match r {
|
||||||
Err(err) => println!("ParserError: {:?}", err),
|
Err(err) => println!("ParserError: {:?}", err),
|
||||||
Ok(expr) => println!(
|
Ok(expr) => {
|
||||||
"{:?} \n vvvvvvvvvvv \n {:?}\n",
|
println!("Evaluating: {}", expr.clone());
|
||||||
expr.clone(),
|
match eval(&environment, expr) {
|
||||||
eval(&environment, expr)
|
Ok(e) => println!("=> {}", e),
|
||||||
),
|
Err(e) => println!("Error: {}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user