Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start decoupling and abstracting out list functionalities #6

Merged
merged 5 commits into from
Jun 18, 2024
Merged
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
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use super::{
eval,
s_list::SList,
s_procedure::{ProcedureArgs, ProcedureEnv, ProcedureOutput},
Accessor, SExpr, SchemeEnvironment, SchemeList,
};

pub fn r_apply(args: ProcedureArgs, env: ProcedureEnv) -> ProcedureOutput {
if args.len() != 2 {
return Err(format!("Exception in apply: expected 2 arguments, found {}", args.len()));
if args.s_len() != 2 {
return Err(format!("Exception in apply: expected 2 arguments, found {}", args.s_len()));
}

let symbol = &args[0];
Expand All @@ -28,16 +29,16 @@ pub fn r_apply(args: ProcedureArgs, env: ProcedureEnv) -> ProcedureOutput {
}

pub fn r_eval(args: ProcedureArgs, env: ProcedureEnv) -> ProcedureOutput {
if args.len() != 1 {
return Err(format!("Exception in eval: expected 1 argument, found {}", args.len()));
if args.s_len() != 1 {
return Err(format!("Exception in eval: expected 1 argument, found {}", args.s_len()));
}

eval(&args[0], env.clone())
}

pub fn r_display(args: ProcedureArgs, env: ProcedureEnv) -> ProcedureOutput {
if args.len() != 1 {
return Err(format!("Exception in display: expected 1 argument, found {}", args.len()));
if args.s_len() != 1 {
return Err(format!("Exception in display: expected 1 argument, found {}", args.s_len()));
}

match eval(&args[0], env.clone()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use super::{
eval,
s_list::SList,
s_procedure::{ProcedureArgs, ProcedureEnv, ProcedureOutput},
Accessor, SExpr, SchemeList, SchemePair,
};

pub fn r_set_car(args: ProcedureArgs, env: ProcedureEnv) -> ProcedureOutput {
if args.len() != 2 {
return Err(format!("Exception in set-car!: expected 2 arguments, found {}", args.len()));
if args.s_len() != 2 {
return Err(format!("Exception in set-car!: expected 2 arguments, found {}", args.s_len()));
}

match &args[0] {
Expand Down Expand Up @@ -36,8 +37,8 @@ pub fn r_set_car(args: ProcedureArgs, env: ProcedureEnv) -> ProcedureOutput {
}

pub fn r_cons(args: ProcedureArgs, env: ProcedureEnv) -> ProcedureOutput {
if args.len() != 2 {
return Err(format!("Exception in cons: expected 2 arguments, found {}", args.len()));
if args.s_len() != 2 {
return Err(format!("Exception in cons: expected 2 arguments, found {}", args.s_len()));
}

let car = eval(&args[0], env.clone());
Expand Down Expand Up @@ -75,30 +76,38 @@ pub fn r_list(args: ProcedureArgs, _: ProcedureEnv) -> ProcedureOutput {
}

pub fn r_flatten(args: ProcedureArgs, _: ProcedureEnv) -> ProcedureOutput {
if args.len() != 1 {
return Err(format!("Exception in flatten: expected 1 argument, found {}", args.len()));
let length = args.s_len();
if length != 1 {
return Err(format!("Exception in flatten: expected 1 argument, found {}", length));
}

args[0].flatten()
}

pub fn r_unflatten(args: ProcedureArgs, _: ProcedureEnv) -> ProcedureOutput {
if args.len() != 1 {
return Err(format!("Exception in unflatten: expected 1 argument, found {}", args.len()));
let length = args.s_len();
if length != 1 {
return Err(format!("Exception in unflatten: expected 1 argument, found {}", length));
}

args[0].unflatten()
}

pub fn r_car(args: ProcedureArgs, env: ProcedureEnv) -> ProcedureOutput {
if args.len() != 1 {
return Err(format!("Exception in car: expected 1 argument, found {}", args.len()));
let length = args.s_len();
if length != 1 {
return Err(format!("Exception in car: expected 1 argument, found {}", length));
}

match eval(&args[0], env.clone())? {
SExpr::List(vec) => {
if vec.borrow().len() > 0 {
Ok(vec.borrow()[0].clone())
SExpr::Pair(pair) => {
let car = pair.borrow().0.clone();
Ok(*car)
}
SExpr::List(list) => {
if list.borrow().s_len() > 0 {
let car = list.borrow().s_car().unwrap().clone();
Ok(car)
} else {
Err(String::from("Exception: #<procedure car> cannot take a quoted empty list"))
}
Expand All @@ -108,20 +117,42 @@ pub fn r_car(args: ProcedureArgs, env: ProcedureEnv) -> ProcedureOutput {
}

pub fn r_cdr(args: ProcedureArgs, env: ProcedureEnv) -> ProcedureOutput {
if args.len() != 1 {
if args.s_len() != 1 {
return Err(String::from("Exception: #<special-form cdr> can take one only argument"));
}

match eval(&args[0], env.clone())? {
SExpr::List(vec) => match vec.borrow().len() {
1.. => {
let mut cdr = vec.borrow().clone();
cdr.remove(0);

Ok(SExpr::List(SchemeList::new(cdr)))
SExpr::Pair(pair) => {
let cdr = pair.borrow().1.clone();
Ok(*cdr)
}
SExpr::List(list) => {
let list = list.borrow();
match list.s_len() {
1.. => {
let cdr = list.s_cdr().map(|x| x.clone()).collect();
Ok(SExpr::List(SchemeList::new(cdr)))
}
_ => {
Err(String::from("Exception: #<procedure cdr> cannot take a quoted empty list"))
}
}
_ => Err(String::from("Exception: #<procedure cdr> cannot take a quoted empty list")),
},
}
_ => Err(String::from("Exception: #<procedure cdr> cannot be applied to quoted symbol")),
}
}

pub fn r_reverse(args: ProcedureArgs, _: ProcedureEnv) -> ProcedureOutput {
let length = args.s_len();
if length != 1 {
return Err(format!("Exception in #<reverse>: expected 1 argument, found {}", length));
}

match &args[0] {
SExpr::List(list) => {
let reversed = list.borrow().s_reverse();
Ok(SExpr::List(SchemeList::new(reversed)))
}
_ => Err(String::from("Exception in #<reverse>: expected a list")),
}
}
21 changes: 11 additions & 10 deletions schemius/src/core/builtins/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use super::{accessor::*, environment::*, evaluator::*, s_expression::*};

mod base;
mod booleans;
mod lists;
mod numbers;
mod base_procs;
mod boolean_procs;
mod list_procs;
mod number_procs;
mod special_forms;
mod strings;
mod string_procs;

use base::*;
use booleans::*;
use lists::*;
use numbers::*;
use base_procs::*;
use boolean_procs::*;
use list_procs::*;
use number_procs::*;
use special_forms::*;
use strings::*;
use string_procs::*;

pub struct Primitive;
pub struct SpecialForm;
Expand Down Expand Up @@ -55,6 +55,7 @@ impl Primitive {
pub const IS_VECTOR: ProcedureSignature = r_is_vector;
pub const IS_ZERO: ProcedureSignature = r_is_zero;
pub const ENVIRONMENT_BINDINGS: ProcedureSignature = r_environment_bindings;
pub const REVERSE: ProcedureSignature = r_reverse;
pub const MAKE_STRING: ProcedureSignature = r_make_string;
pub const STRING: ProcedureSignature = r_string;
pub const STRING_APPEND: ProcedureSignature = r_string_append;
Expand Down
Loading