Skip to content

Commit

Permalink
Improve predicate support
Browse files Browse the repository at this point in the history
  • Loading branch information
cowuake committed Apr 16, 2024
1 parent e5cefbb commit 0984c25
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 25 deletions.
5 changes: 4 additions & 1 deletion schemius/src/core/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ impl Primitive {
pub const IS_NUMBER: ProcedureSignature = r_is_number;
pub const IS_EXACT: ProcedureSignature = r_is_exact;
pub const IS_PAIR: ProcedureSignature = r_is_pair;
pub const IS_SYMBOL: ProcedureSignature = r_is_symbol;
pub const IS_LIST: ProcedureSignature = r_is_list;
pub const IS_VECTOR: ProcedureSignature = r_is_vector;
pub const IS_PROCEDURE: ProcedureSignature = r_is_procedure;
pub const IS_NULL: ProcedureSignature = r_is_null;
pub const ENVIRONMENT_BINDINGS: ProcedureSignature = r_environment_bindings;
pub const STRING_SET: ProcedureSignature = r_string_set;
pub const FLATTEN: ProcedureSignature = r_flatten;
Expand Down Expand Up @@ -860,7 +862,8 @@ fn_is! {
r_is_pair, is_pair, "pair?"
r_is_vector, is_vector, "vector?"
r_is_procedure, is_procedure, "procedure?"
// r_is_symbol, is_symbol, "symbol?"
r_is_symbol, is_symbol, "symbol?"
r_is_null, is_null, "null?"
}

fn r_string_set(args: ProcedureArgs, _: ProcedureEnv) -> ProcedureOutput {
Expand Down
2 changes: 2 additions & 0 deletions schemius/src/core/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ impl Default for Environment {
(String::from("cond"), SExpr::Procedure(Procedure::SpecialForm(SpecialForm::COND))),
(String::from("display"), SExpr::Procedure(Procedure::Primitive(Primitive::DISPLAY))),
(String::from("char?"), SExpr::Procedure(Procedure::Primitive(Primitive::IS_CHAR))),
(String::from("symbol?"), SExpr::Procedure(Procedure::Primitive(Primitive::IS_SYMBOL))),
(String::from("string?"), SExpr::Procedure(Procedure::Primitive(Primitive::IS_STRING))),
(
String::from("boolean?"),
Expand All @@ -147,6 +148,7 @@ impl Default for Environment {
String::from("procedure?"),
SExpr::Procedure(Procedure::Primitive(Primitive::IS_PROCEDURE)),
),
(String::from("null?"), SExpr::Procedure(Procedure::Primitive(Primitive::IS_NULL))),
(String::from("time"), SExpr::Procedure(Procedure::SpecialForm(SpecialForm::TIME))),
(
String::from("environment-bindings"),
Expand Down
6 changes: 6 additions & 0 deletions schemius/src/core/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ fn parse_token(line: &mut String, token: &String) -> SExpr {
return SExpr::Boolean(true);
} else if token == "#f" {
return SExpr::Boolean(false);
} else if token == "-nan.0" || token == "+nan.0" {
return SExpr::Number(SNumber::Float(NativeFloat::NAN));
} else if token == "-inf.0" {
return SExpr::Number(SNumber::Float(NativeFloat::NEG_INFINITY));
} else if token == "+inf.0" {
return SExpr::Number(SNumber::Float(NativeFloat::INFINITY));
} else if token.starts_with('"') {
return SExpr::String(SchemeString::new(
token.get(1..token.len() - 1).unwrap().to_string(),
Expand Down
63 changes: 40 additions & 23 deletions schemius/src/core/s_expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub mod s_number;
pub mod s_procedure;

use super::accessor::*;
use std::fmt;
use std::{fmt, result};

pub use self::{s_number::*, s_procedure::*};
type SAccessor<T> = ThreadSafeAccessor<T>;
Expand Down Expand Up @@ -75,26 +75,23 @@ impl fmt::Display for SExpr {
}

impl SExpr {
pub fn is_symbol(&self, repr: Option<&str>) -> Result<bool, String> {
pub fn symbol_is(&self, repr: &str) -> Result<bool, String> {
match self {
SExpr::Symbol(val) => match repr {
Some(token) => {
if val.as_str() == token {
Ok(true)
} else {
Ok(false)
}
SExpr::Symbol(val) => {
if val.as_str() == repr {
Ok(true)
} else {
Ok(false)
}
None => Ok(true),
},
}
_ => Ok(false),
}
}

#[allow(dead_code)]
fn is_left_bracket(&self) -> Result<bool, String> {
if self.is_symbol(Some(Bracket::LEFT_ROUND)).unwrap()
|| self.is_symbol(Some(Bracket::LEFT_SQUARE)).unwrap()
if self.symbol_is(Bracket::LEFT_ROUND).unwrap()
|| self.symbol_is(Bracket::LEFT_SQUARE).unwrap()
{
Ok(true)
} else {
Expand All @@ -104,8 +101,8 @@ impl SExpr {

#[allow(dead_code)]
fn is_right_bracket(&self) -> Result<bool, String> {
if self.is_symbol(Some(Bracket::RIGHT_ROUND)).unwrap()
|| self.is_symbol(Some(Bracket::RIGHT_SQUARE)).unwrap()
if self.symbol_is(Bracket::RIGHT_ROUND).unwrap()
|| self.symbol_is(Bracket::RIGHT_SQUARE).unwrap()
{
Ok(true)
} else {
Expand All @@ -120,6 +117,13 @@ impl SExpr {
}
}

pub fn is_symbol(&self) -> Result<bool, String> {
match self {
SExpr::Symbol(_) => Ok(true),
_ => Ok(false),
}
}

pub fn is_string(&self) -> Result<bool, String> {
match self {
SExpr::String(_) => Ok(true),
Expand Down Expand Up @@ -183,11 +187,24 @@ impl SExpr {
}
}

pub fn is_null(&self) -> result::Result<bool, String> {
match self {
SExpr::List(list) => {
if list.borrow().is_empty() {
Ok(true)
} else {
Ok(false)
}
}
_ => Ok(false),
}
}

pub fn matching_brackets(&self) -> Option<Vec<(usize, usize, usize)>> {
match self {
SExpr::List(list) => {
let list = list.borrow();
if !list.first().unwrap().is_symbol(Some("(")).unwrap() {
if !list.first().unwrap().symbol_is("(").unwrap() {
return None;
}

Expand All @@ -198,7 +215,7 @@ impl SExpr {
.enumerate()
.filter(|x| {
(pairs.is_empty() || pairs.iter().all(|(_, right)| right != &x.0))
&& x.1.is_symbol(Some(")")).unwrap()
&& x.1.symbol_is(")").unwrap()
})
.min_by(|x, y| (x.0).cmp(&y.0))
.map(|x| x.0)
Expand All @@ -208,7 +225,7 @@ impl SExpr {
.enumerate()
.filter(|x| {
(pairs.is_empty() || pairs.iter().all(|(left, _)| left != &x.0))
&& x.1.is_symbol(Some("(")).unwrap()
&& x.1.symbol_is("(").unwrap()
})
.filter(|x| x.0 < right)
.max_by(|x, y| (x.0).cmp(&y.0))
Expand Down Expand Up @@ -246,14 +263,14 @@ impl SExpr {
Ok(SExpr::List(flattened)) => {
let borrowed_flattened = flattened.borrow();

if borrowed_flattened.first().unwrap().is_symbol(Some("(")).unwrap() {
if borrowed_flattened.first().unwrap().symbol_is("(").unwrap() {
return None;
}

let indexes: Vec<usize> = borrowed_flattened
.iter()
.enumerate()
.filter(|(_, x)| x.is_symbol(Some(symbol)).unwrap())
.filter(|(_, x)| x.symbol_is(symbol).unwrap())
.map(|(i, _)| i - 1)
.collect();

Expand Down Expand Up @@ -306,7 +323,7 @@ impl SExpr {
let cloned = list.clone();
let mut unflattened = cloned.borrow_mut();

if !unflattened.first().unwrap().is_symbol(Some("(")).unwrap() {
if !unflattened.first().unwrap().symbol_is("(").unwrap() {
return Ok(self.clone());
}

Expand All @@ -320,15 +337,15 @@ impl SExpr {
match unflattened
.iter()
.enumerate()
.filter(|x| x.1.is_symbol(Some(")")).unwrap())
.filter(|x| x.1.symbol_is(")").unwrap())
.min_by(|x, y| (x.0).cmp(&y.0))
.map(|x| x.0)
{
Some(r) => {
match unflattened
.iter()
.enumerate()
.filter(|x| x.1.is_symbol(Some("(")).unwrap())
.filter(|x| x.1.symbol_is("(").unwrap())
.filter(|x| x.0 < r)
.max_by(|x, y| (x.0).cmp(&y.0))
.map(|x| x.0)
Expand Down
21 changes: 20 additions & 1 deletion schemius/tests/sparse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ fn interpreter_number_comparison() {
}

#[test]
fn interpreter_sepr_type() {
fn interpreter_sexpr_type() {
integration_subtest_eval_to! {
{ expression: "(boolean? #f)", expected: "#t" };
{ expression: r#"(string? "hello")"#, expected: "#t" };
Expand All @@ -204,5 +204,24 @@ fn interpreter_sepr_type() {
{ expression: "(list? '(1 . 2))", expected: "#f" };
{ expression: "(pair? '(1 2 3))", expected: "#t" };
{ expression: "(pair? '(1 . 2))", expected: "#t" };
{ expression: "(symbol? 'hello)", expected: "#t" };
{ expression: r#"(symbol? "hello")"#, expected: "#f" };
}
}

#[test]
fn interpreter_sexpr_null() {
integration_subtest_eval_to! {
{ expression: "(null? '())", expected: "#t" };
{ expression: "(null? '(1 2 3))", expected: "#f" };
{ expression: "(null? 1)", expected: "#f" };
{ expression: "(null? #f)", expected: "#f" };
{ expression: "(null? 'hello)", expected: "#f" };
{ expression: "(null? 0)", expected: "#f" };
{ expression: "(null? 0.0)", expected: "#f" };
{ expression: "(null? 1/2)", expected: "#f" };
{ expression: "(null? +nan.0)", expected: "#f" };
{ expression: "(null? -inf.0)", expected: "#f" };
{ expression: "(null? +inf.0)", expected: "#f" };
}
}

0 comments on commit 0984c25

Please sign in to comment.