From 5c6518f7d69c72f4f69bf0660d4f7798dc1b2d38 Mon Sep 17 00:00:00 2001 From: Sameer Rahmani Date: Mon, 2 Nov 2020 00:55:56 +0000 Subject: [PATCH] Add the StringRepr trait to be used in printing evaluation results in REPL All the expressions and basically anything that needs to be printed out into the REPL as a result of evaluation has to implement this trait. It differs from the `std::fmt::Display` trait in the way that the runtime instance is available to this function. --- bootstrap/src/ast.rs | 26 +++++++++++++++++++++--- bootstrap/src/core.rs | 4 ++-- bootstrap/src/types/collections/list.rs | 27 ++++++++++++++++++++++--- bootstrap/src/types/number.rs | 8 +++++++- bootstrap/src/types/symbol.rs | 16 +++++++-------- 5 files changed, 64 insertions(+), 17 deletions(-) diff --git a/bootstrap/src/ast.rs b/bootstrap/src/ast.rs index 80cbf5e..4e23359 100644 --- a/bootstrap/src/ast.rs +++ b/bootstrap/src/ast.rs @@ -46,6 +46,15 @@ pub trait Expression { fn eval(&self, rt: &RT, scope: &Scope) -> PossibleExpr; } +/// It differs from the `fmt::Display` in the way that anything that +/// we want to show in a repl as the result of an evaluation and needs +/// the runtime details has to implement this trait. But we use the +/// `fmt::Display` as a formatter and in a way that it doesn't need the +/// runtime. +pub trait StringRepr { + fn string_repr(&self, rt: &RT) -> String; +} + #[derive(Debug, Eq, PartialEq, Clone)] pub enum Expr { Sym(Symbol), @@ -53,18 +62,18 @@ pub enum Expr { Num(Number), Comment, Error(String), - Cons(Box), + Cons(collections::List), Nil, NoMatch, } impl Expr { pub fn make_list(elements: &[Expr]) -> Expr { - Expr::Cons(Box::new(collections::List::new(elements))) + Expr::Cons(collections::List::new(elements)) } pub fn list_to_cons(l: collections::List) -> Expr { - Expr::Cons(Box::new(l)) + Expr::Cons(l) } pub fn make_empty_list() -> collections::List { @@ -93,3 +102,14 @@ impl fmt::Display for Expr { } } } + +impl StringRepr for Expr { + fn string_repr(&self, rt: &RT) -> String { + match self { + Expr::Num(n) => n.string_repr(rt), + Expr::Sym(s) => s.string_repr(rt), + Expr::Cons(c) => c.string_repr(rt), + _ => "NA".to_string(), + } + } +} diff --git a/bootstrap/src/core.rs b/bootstrap/src/core.rs index 40f87b8..bdb9adf 100644 --- a/bootstrap/src/core.rs +++ b/bootstrap/src/core.rs @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -use crate::ast::{Expr, Expression, PossibleExpr}; +use crate::ast::{Expr, Expression, PossibleExpr, StringRepr}; use crate::errors::err; use crate::reader::read_string; use crate::runtime::RT; @@ -60,7 +60,7 @@ pub fn read_eval_print(rt: &RT, input: &str) { } match result_expr { - Ok(expr) => println!("{}", expr), + Ok(expr) => println!("{}", expr.string_repr(rt)), Err(e) => println!("{}", e), } } diff --git a/bootstrap/src/types/collections/list.rs b/bootstrap/src/types/collections/list.rs index 49a8acd..f9108a5 100644 --- a/bootstrap/src/types/collections/list.rs +++ b/bootstrap/src/types/collections/list.rs @@ -14,13 +14,15 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + //use crate::builtins::def; -use crate::ast::{Expr, Expression, PossibleExpr}; +use crate::ast::{Expr, Expression, PossibleExpr, StringRepr}; use crate::errors::err; use crate::runtime::RT; use crate::scope::Scope; use crate::types::collections::core::Seq; use crate::types::Symbol; +use std::fmt; #[derive(Debug, Eq, PartialEq, Clone)] pub struct List { @@ -74,11 +76,30 @@ impl Expression for List { let first = self.first().unwrap(); let rest = self.rest(); - Err(err("NotImplemented".to_string())) - //Ok(Expr::Cons(Box::new(*self))) + + Ok(Expr::Cons(self.clone())) // match first { // Expr::Sym(sum) => {} // _ => Err(err("NotImplemented".to_string())), // } } } + +impl fmt::Display for List { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let elems: Vec = self + .elements + .clone() + .iter() + .map(|x| format!("{}", x)) + .collect(); + + write!(f, "({})", &elems.join(" ")) + } +} + +impl StringRepr for List { + fn string_repr(&self, rt: &RT) -> String { + format!("{}", self) + } +} diff --git a/bootstrap/src/types/number.rs b/bootstrap/src/types/number.rs index ea39357..34e15bb 100644 --- a/bootstrap/src/types/number.rs +++ b/bootstrap/src/types/number.rs @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -use crate::ast::{Expr, Expression, PossibleExpr}; +use crate::ast::{Expr, Expression, PossibleExpr, StringRepr}; use crate::runtime::RT; use crate::scope::Scope; use std::fmt; @@ -61,3 +61,9 @@ impl fmt::Display for Number { } } } + +impl StringRepr for Number { + fn string_repr(&self, rt: &RT) -> String { + format!("{}", self) + } +} diff --git a/bootstrap/src/types/symbol.rs b/bootstrap/src/types/symbol.rs index b004e3f..1c25ea5 100644 --- a/bootstrap/src/types/symbol.rs +++ b/bootstrap/src/types/symbol.rs @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -use crate::ast::{Expr, Expression, Location, PossibleExpr}; +use crate::ast::{Expr, Expression, Location, PossibleExpr, StringRepr}; use crate::errors::err; use crate::runtime::RT; use crate::scope::Scope; @@ -97,12 +97,12 @@ impl Expression for Symbol { impl fmt::Display for Symbol { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self.ns { - Some(n) => write!(f, "#'{}/{}", &n, &self.name), - _ => panic!( - "Displaying symbol '{:?}' without evaluating it.", - &self.name - ), - } + write!(f, "{}", &self.name) + } +} + +impl StringRepr for Symbol { + fn string_repr(&self, rt: &RT) -> String { + format!("#'{}/{}", &rt.current_ns().name, &self.name) } }