Skip to content

Commit

Permalink
Start decoupling and abstracting out list functionalities (#6)
Browse files Browse the repository at this point in the history
* Prepare list generalization

* Fix campound procedures with quoted arguments

* Rename builtin procedure source files

* Remove stupid line

* Fix 'reverse' procedure
  • Loading branch information
cowuake authored Jun 18, 2024
1 parent 0b82ab7 commit 7e93dfa
Show file tree
Hide file tree
Showing 14 changed files with 261 additions and 107 deletions.
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
File renamed without changes.
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
File renamed without changes.
Loading

0 comments on commit 7e93dfa

Please sign in to comment.