Skip to content
Draft

perf #37

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rustyline = "9.1.0" # for the repl
home = "0.5.3" # for getting home_dir
rustyline = "9.1.0" # for the repl
home = "0.5.3" # for getting home_dir
itertools = "0.10.2" # better iterators
# colors in terminal
colored = "2"
Expand Down Expand Up @@ -35,3 +35,6 @@ debug = 1

[features]
memory_test = []

[profile.bench]
debug = true
1 change: 0 additions & 1 deletion benches/spresso_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ fn criterion_benchmark(c: &mut Criterion) {
(define sum (+ sum i))
(define i (+ i 1))
)))
(print sum)
"
.to_owned(),
),
Expand Down
60 changes: 47 additions & 13 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ use crate::env::Env;
use crate::errors::{NumericError, SpressoError};
use crate::{Token, TokenGiver, TokenHoarder};

pub type FuncType = fn(Vec<Expr>, &mut Env) -> Result<Expr, SpressoError>;
pub type FuncType = fn(&mut [Expr], &mut Env) -> Result<Expr, SpressoError>;

#[derive(Clone, Debug)]
pub struct Expr {
pub kind: ExprKind,
tokens: Option<Vec<Token>>,
tokens: Option<Vec<Rc<Token>>>,
}

impl PartialEq for Expr {
Expand All @@ -32,18 +32,30 @@ impl From<ExprKind> for Expr {
}

impl TokenHoarder for Expr {
fn with_token(mut self, token: Token) -> Self {
fn with_token(mut self, token: &Rc<Token>) -> Self {
if let Some(tokens) = &mut self.tokens {
tokens.push(token);
tokens.push(Rc::clone(token));
} else {
self.tokens = Some(vec![token]);
self.tokens = Some(vec![Rc::clone(token)]);
}
self
}

fn with_tokens(mut self, new_tokens: Vec<Rc<Token>>) -> Self
where
Self: Sized,
{
if let Some(tokens) = &mut self.tokens {
tokens.extend(new_tokens);
} else {
self.tokens = Some(new_tokens);
}
self
}
}

impl TokenGiver for Expr {
fn get_tokens(&self) -> Option<Vec<Token>> {
fn get_tokens(&self) -> Option<Vec<Rc<Token>>> {
match &self.kind {
ExprKind::List(exprs) => exprs.get_tokens(),
_ => self.tokens.clone(),
Expand All @@ -52,7 +64,21 @@ impl TokenGiver for Expr {
}

impl TokenGiver for Vec<Expr> {
fn get_tokens(&self) -> Option<Vec<Token>> {
fn get_tokens(&self) -> Option<Vec<Rc<Token>>> {
let mut tokens = Vec::new();

for expr in self {
if let Some(expr_tokens) = expr.get_tokens() {
tokens.extend(expr_tokens);
}
}

Some(tokens)
}
}

impl TokenGiver for [Expr] {
fn get_tokens(&self) -> Option<Vec<Rc<Token>>> {
let mut tokens = Vec::new();

for expr in self {
Expand Down Expand Up @@ -126,7 +152,7 @@ impl fmt::Display for Atom {
}
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub enum Number {
Int(i64),
Float(f64),
Expand Down Expand Up @@ -259,7 +285,7 @@ pub struct Lambda {
pub params: Vec<String>,
pub body: Vec<Expr>,
pub scopes: Vec<Rc<usize>>,
param_tokens: Vec<Token>,
param_tokens: Vec<Rc<Token>>,
}

impl PartialEq for Lambda {
Expand All @@ -282,16 +308,24 @@ impl Lambda {
/// Note: Lambda itself should only store the tokens of its parameters
/// Tokens of the body are stored inside the body itself.
impl TokenHoarder for Lambda {
fn with_token(mut self, token: Token) -> Self {
self.param_tokens.push(token);
fn with_token(mut self, token: &Rc<Token>) -> Self {
self.param_tokens.push(Rc::clone(token));
self
}

fn with_tokens(mut self, tokens: Vec<Rc<Token>>) -> Self
where
Self: Sized,
{
self.param_tokens.extend(tokens);
self
}
}

/// Note: Lambda itself only stores the tokens of its parameters.
/// Tokens of the body can be retrieved by `lambda.body.get_tokens()`.
impl TokenGiver for Lambda {
fn get_tokens(&self) -> Option<Vec<Token>> {
fn get_tokens(&self) -> Option<Vec<Rc<Token>>> {
Some(self.param_tokens.clone())
}
}
Expand All @@ -307,7 +341,7 @@ pub struct Macro {
pub params: Vec<String>,
pub body: Vec<Expr>,
pub scopes: Vec<Rc<usize>>,
pub param_tokens: Vec<Token>,
pub param_tokens: Vec<Rc<Token>>,
}

impl fmt::Display for Macro {
Expand Down
9 changes: 5 additions & 4 deletions src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::fmt;
use std::{fmt, rc::Rc};

use colored::Colorize;

Expand All @@ -7,7 +7,7 @@ use crate::{display_and_mark, Token, TokenGiver, TokenHoarder};
#[derive(Clone)]
pub struct SpressoError {
pub detail: SpressoErrorType,
tokens: Option<Vec<Token>>,
tokens: Option<Vec<Rc<Token>>>,
}

#[derive(Clone)]
Expand Down Expand Up @@ -47,7 +47,8 @@ impl SpressoError {
}

impl TokenHoarder for SpressoError {
fn with_token(mut self, token: Token) -> Self {
fn with_token(mut self, token: &Rc<Token>) -> Self {
let token = Rc::clone(token);
match &mut self.tokens {
Some(tokens) => tokens.push(token),
None => self.tokens = Some(vec![token]),
Expand All @@ -57,7 +58,7 @@ impl TokenHoarder for SpressoError {
}

impl TokenGiver for SpressoError {
fn get_tokens(&self) -> Option<Vec<Token>> {
fn get_tokens(&self) -> Option<Vec<Rc<Token>>> {
self.tokens.clone()
}
}
Expand Down
9 changes: 4 additions & 5 deletions src/eval/conditional.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,24 @@ use crate::{
TokenGiver, TokenHoarder,
};

pub fn if_cond(args: Vec<Expr>, env: &mut Env) -> Result<Expr, SpressoError> {
pub fn if_cond(args: &mut [Expr], env: &mut Env) -> Result<Expr, SpressoError> {
if !(args.len() == 2 || args.len() == 3) {
return Err(SpressoError::from(RuntimeError::from("If statement should have a condition, expression to evaluate when true and optionally an expression to evaluate when false.")).maybe_with_tokens(args.get_tokens()));
}

let mut args = args;
let cond = args.remove(0);
let (cond, args) = args.split_first_mut().unwrap();

let cond = execute_single(cond, env)?;

if let ExprKind::Atom(Atom::Bool(boolean)) = cond.kind {
if boolean {
// execute true
let true_cond = args.remove(0);
let true_cond = &mut args[0];
execute_single(true_cond, env)
} else {
// execute false
if args.len() > 1 {
let false_cond = args.pop().unwrap();
let false_cond = &mut args[1];
execute_single(false_cond, env)
} else {
Ok(ExprKind::Atom(Atom::Unit).into())
Expand Down
22 changes: 13 additions & 9 deletions src/eval/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,24 @@ use crate::{
TokenGiver, TokenHoarder,
};

pub fn lambda(args: Vec<Expr>, env: &mut Env) -> Result<Expr, SpressoError> {
pub fn lambda(args: &mut [Expr], env: &mut Env) -> Result<Expr, SpressoError> {
if args.len() < 2 {
return Err(SpressoError::from(RuntimeError::from(
"A lambda definition must have a param list and a body (any number of lists)",
))
.maybe_with_tokens(args.get_tokens()));
}

let fn_params = args[0].clone();
let body = args[1..].to_vec();
let (fn_params, body) = args.split_first_mut().unwrap();

match fn_params.kind {
ExprKind::Atom(Atom::Symbol(ref fn_param)) => Ok(ExprKind::Lambda(
Lambda::new(vec![fn_param.clone()], body, env.get_current_scopes())
.maybe_with_tokens(fn_params.get_tokens()),
Lambda::new(
vec![fn_param.clone()],
body.to_vec(),
env.get_current_scopes(),
)
.maybe_with_tokens(fn_params.get_tokens()),
)
.into()),
ExprKind::List(ref fn_params) => {
Expand All @@ -40,7 +43,7 @@ pub fn lambda(args: Vec<Expr>, env: &mut Env) -> Result<Expr, SpressoError> {
.collect();

Ok(ExprKind::Lambda(
Lambda::new(params?, body, env.get_current_scopes())
Lambda::new(params?, body.to_vec(), env.get_current_scopes())
.maybe_with_tokens(fn_params.get_tokens()),
)
.into())
Expand All @@ -53,8 +56,8 @@ pub fn lambda(args: Vec<Expr>, env: &mut Env) -> Result<Expr, SpressoError> {
}

pub fn execute_lambda(
lambda: Lambda,
args: Vec<Expr>,
lambda: &Lambda,
args: &mut [Expr],
env: &mut Env,
) -> Result<Expr, SpressoError> {
let args: Result<Vec<Expr>, SpressoError> = args
Expand All @@ -80,9 +83,10 @@ pub fn execute_lambda(
// execute body
let results = lambda
.body
// TODO: no clone
.clone()
.into_iter()
.map(|expr| execute_single(expr, env));
.map(|mut expr| execute_single(&mut expr, env));

let mut last_ok_result = None;
for result in results {
Expand Down
Loading
Loading