Skip to content

Commit

Permalink
Add module for constants
Browse files Browse the repository at this point in the history
  • Loading branch information
cowuake committed Aug 15, 2024
1 parent 4902a80 commit 4a90c8e
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 86 deletions.
9 changes: 6 additions & 3 deletions schemius/src/core/builtins/special_forms.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::time::Instant;

use crate::core::constants::tokens;

use super::{
eval, r_eval,
s_list::SList,
Expand Down Expand Up @@ -298,11 +300,12 @@ pub fn r_quasiquote(args: ProcedureArgs, env: ProcedureEnv) -> SpecialFormOutput
Ok(expr) => match expr {
SExpr::List(list) => {
let s_list = SExpr::List(list.clone());
let quasiquotes = s_list.find_symbol("quasiquote");
let quasiquotes = s_list.find_symbol(tokens::QUASIQUOTE_EXPLICIT);
let mapping = s_list.matching_brackets().unwrap();

let unquotes = s_list.find_symbol("unquote");
let unquotes_splicing = s_list.find_symbol("unquote-splicing");
let unquotes = s_list.find_symbol(tokens::UNQUOTE_EXPLICIT);
let unquotes_splicing =
s_list.find_symbol(tokens::UNQUOTE_SPLICING_EXPLICIT);
let mut unquotes = if let Some(unquotes) = unquotes {
unquotes.iter().map(|x| (false, *x)).collect()
} else {
Expand Down
44 changes: 44 additions & 0 deletions schemius/src/core/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
pub mod tokens {
pub const EOF: &str = "EOF";
pub const OPEN_PAREN: &str = "(";
pub const CLOSED_PAREN: &str = ")";
pub const OPEN_BRACKET: &str = "[";
pub const CLOSED_BRACKET: &str = "]";
pub const PREFIX: &str = "#";
pub const VECTOR_OPEN: &str = "#(";
pub const QUOTE: &str = "'";
pub const QUOTE_EXPLICIT: &str = "quote";
pub const QUASIQUOTE: &str = "`";
pub const QUASIQUOTE_EXPLICIT: &str = "quasiquote";
pub const DOT: &str = ".";
pub const UNQUOTE: &str = ",";
pub const UNQUOTE_EXPLICIT: &str = "unquote";
pub const UNQUOTE_SPLICING: &str = ",@";
pub const UNQUOTE_SPLICING_EXPLICIT: &str = "unquote-splicing";
pub const TRUE: &str = "#t";
pub const FALSE: &str = "#f";
pub const PREFIX_CHAR: &str = "#\\";
pub const PREFIX_STRING: &str = "\"";
pub const SUFFIX_STRING: &str = "\"";
pub const PREFIX_COMMENT: &str = ";";
pub const PREFIX_BINARY: &str = "#b";
pub const PREFIX_OCTAL: &str = "#o";
pub const PREFIX_HEX: &str = "#x";
pub const PREFIX_DECIMAL: &str = "#d";
pub const PREFIX_EXACT: &str = "#e";
pub const PREFIX_INEXACT: &str = "#i";
pub const POSITIVE_INFINITY: &str = "+inf.0";
pub const NEGATIVE_INFINITY: &str = "-inf.0";
pub const POSITIVE_NAN: &str = "+nan.0";
pub const NEGATIVE_NAN: &str = "-nan.0";
}

pub mod numbers {
pub const AVOGADRO: f64 = 6.0221515e23;
pub const BOLTZMANN: f64 = 1.380650e23;
pub const EULER: f64 = 2.718281828459045;
pub const GOLDEN_RATIO: f64 = 1.618033988749895;
pub const GRAVITATIONAL_CONSTANT: f64 = 6.67300e-11;
pub const PI: f64 = 3.141592653589793;
pub const PLANCK: f64 = 6.626068e-34;
}
19 changes: 11 additions & 8 deletions schemius/src/core/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::io::{self, Write};
use crate::core::reader;
use crate::scheme::prelude::PRELUDE;

use super::constants::tokens;
use super::environment::Environment;
use super::evaluator::EvalOutput;
use super::{evaluator::Evaluator, s_expression::SExpr};
Expand Down Expand Up @@ -56,7 +57,7 @@ impl Interpreter {

let next = next_line(self).unwrap_or("".to_string());

if next.is_empty() || next.starts_with(';') {
if next.is_empty() || next.starts_with(tokens::PREFIX_COMMENT) {
continue;
}

Expand Down Expand Up @@ -88,11 +89,13 @@ impl Interpreter {
self.current_expression = next_line(self)?;
self.read(next_line);

if self.current_expression.is_empty() || self.current_expression.starts_with(';') {
if self.current_expression.is_empty()
|| self.current_expression.starts_with(tokens::PREFIX_COMMENT)
{
continue;
}

if self.current_expression == "EOF" {
if self.current_expression == tokens::EOF {
break;
}

Expand Down Expand Up @@ -122,10 +125,10 @@ impl Interpreter {

fn is_preliminarily_validated(&self, expression_string: &str) -> bool {
// TODO: Judge the validity of the approach and extend the function if it's worth
!((expression_string.trim().starts_with('(')
&& !expression_string.trim_end().ends_with(')'))
|| (expression_string.trim().starts_with('[')
&& !expression_string.trim_end().ends_with(']')))
!((expression_string.trim().starts_with(tokens::OPEN_PAREN)
&& !expression_string.trim_end().ends_with(tokens::CLOSED_PAREN))
|| (expression_string.trim().starts_with(tokens::OPEN_BRACKET)
&& !expression_string.trim_end().ends_with(tokens::CLOSED_BRACKET)))
}

pub fn eval_expression(&mut self, expression_string: String) -> EvalOutput {
Expand Down Expand Up @@ -175,7 +178,7 @@ fn read_line_from_file(interpreter: &mut Interpreter) -> Result<String, String>

Ok(line)
} else {
Ok(String::from("EOF"))
Ok(String::from(tokens::EOF))
}
}

Expand Down
1 change: 1 addition & 0 deletions schemius/src/core/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod accessor;
mod builtins;
mod constants;
mod environment;
mod evaluator;
pub mod interpreter;
Expand Down
81 changes: 46 additions & 35 deletions schemius/src/core/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use lazy_static::lazy_static;
use num::Num;
use regex::Regex;

use super::{accessor::Accessor, s_expression::*};
use super::{accessor::Accessor, constants::tokens, s_expression::*};

lazy_static! {
static ref TOKEN_REGEX: Regex =
Expand All @@ -27,9 +27,9 @@ pub fn read(line: &mut String) -> Result<SExpr, String> {
fn has_balanced_parentheses(s: &str) -> bool {
let mut balance = 0;
for c in s.chars() {
match c {
'(' | '[' => balance += 1,
')' | ']' => balance -= 1,
match c.to_string().as_str() {
tokens::OPEN_PAREN | tokens::OPEN_BRACKET => balance += 1,
tokens::CLOSED_PAREN | tokens::CLOSED_BRACKET => balance -= 1,
_ => {}
}
if balance < 0 {
Expand Down Expand Up @@ -58,17 +58,18 @@ fn advance(line: &mut String, string_token: &String) -> Result<SExpr, String> {
let opening_token = string_token.as_str();

match opening_token {
"(" | "[" | "#(" => {
tokens::OPEN_PAREN | tokens::OPEN_BRACKET | tokens::VECTOR_OPEN => {
let mut new_list = VectorImplementation::new();

loop {
let token: String = init(line);

if (opening_token == "(" && token == ")") || (opening_token == "[" && token == "]")
if (opening_token == tokens::OPEN_PAREN && token == tokens::CLOSED_PAREN)
|| (opening_token == tokens::OPEN_BRACKET && token == tokens::CLOSED_BRACKET)
{
if new_list.len() == 3 && token != "]" {
if new_list.len() == 3 && token != tokens::CLOSED_BRACKET {
if let SExpr::Symbol(sym) = &new_list.s_ref(1).unwrap() {
if sym.as_str() == "." {
if sym.as_str() == tokens::DOT {
return Ok(SExpr::Pair(SchemePair::new((
Box::new(new_list.s_ref(0).unwrap().clone()),
Box::new(new_list.s_ref(2).unwrap().clone()),
Expand All @@ -80,7 +81,7 @@ fn advance(line: &mut String, string_token: &String) -> Result<SExpr, String> {
return Ok(SExpr::List(SchemeList::new(ListImplementation::from_iter(
new_list,
))));
} else if opening_token == "#(" && token == ")" {
} else if opening_token == tokens::VECTOR_OPEN && token == tokens::CLOSED_PAREN {
return Ok(SExpr::Vector(SchemeVector::new(VectorImplementation::from(
new_list,
))));
Expand All @@ -95,32 +96,34 @@ fn advance(line: &mut String, string_token: &String) -> Result<SExpr, String> {

fn parse_token(line: &mut String, token: &str) -> Result<SExpr, String> {
match token {
"#t" => Ok(SExpr::Boolean(true)),
"#f" => Ok(SExpr::Boolean(false)),
"-nan.0" | "+nan.0" => Ok(SExpr::Number(SNumber::Float(NativeFloat::NAN))),
"-inf.0" => Ok(SExpr::Number(SNumber::Float(NativeFloat::NEG_INFINITY))),
"+inf.0" => Ok(SExpr::Number(SNumber::Float(NativeFloat::INFINITY))),
tokens::TRUE => Ok(SExpr::Boolean(true)),
tokens::FALSE => Ok(SExpr::Boolean(false)),
tokens::NEGATIVE_NAN | tokens::POSITIVE_NAN => {
Ok(SExpr::Number(SNumber::Float(NativeFloat::NAN)))
}
tokens::NEGATIVE_INFINITY => Ok(SExpr::Number(SNumber::Float(NativeFloat::NEG_INFINITY))),
tokens::POSITIVE_INFINITY => Ok(SExpr::Number(SNumber::Float(NativeFloat::INFINITY))),
token if token.starts_with('"') => {
Ok(SExpr::String(SchemeString::new(token.get(1..token.len() - 1).unwrap().to_string())))
}
"'" | "`" | "," | ",@" => {
tokens::QUOTE | tokens::QUASIQUOTE | tokens::UNQUOTE | tokens::UNQUOTE_SPLICING => {
let internal_token = init(line);
let quoted = advance(line, &internal_token)?;
let mut vec = ListImplementation::new();

let string_token = match token {
"'" => "quote".to_string(),
"`" => "quasiquote".to_string(),
"," => "unquote".to_string(),
",@" => "unquote-splicing".to_string(),
tokens::QUOTE => tokens::QUOTE_EXPLICIT.to_string(),
tokens::QUASIQUOTE => tokens::QUASIQUOTE_EXPLICIT.to_string(),
tokens::UNQUOTE => tokens::UNQUOTE_EXPLICIT.to_string(),
tokens::UNQUOTE_SPLICING => tokens::UNQUOTE_SPLICING_EXPLICIT.to_string(),
_ => token.to_string(),
};

vec.push(SExpr::Symbol(string_token));
vec.push(quoted);
Ok(SExpr::List(SchemeList::new(vec)))
}
token if token.starts_with(r#"#\"#) => {
token if token.starts_with(tokens::PREFIX_CHAR) => {
match token.len() {
3 => Ok(SExpr::Char(token.chars().last().unwrap())),
_ => {
Expand All @@ -133,7 +136,7 @@ fn parse_token(line: &mut String, token: &str) -> Result<SExpr, String> {
}
_ => {
let n_prefixes = if token.len() > 2
&& token.chars().nth(0) == Some('#')
&& token.chars().nth(0) == tokens::PREFIX.chars().next()
&& token.chars().nth(1).is_some_and(|c| c.is_alphabetic())
{
if token.len() > 4
Expand All @@ -150,24 +153,32 @@ fn parse_token(line: &mut String, token: &str) -> Result<SExpr, String> {

let (has_prefix, radix, is_exact) = if n_prefixes == 2 {
match (&token[0..2], &token[2..4]) {
("#b", "#e") | ("#e", "#b") => (true, 2, Some(true)),
("#b", "#i") | ("#i", "#b") => (true, 2, Some(false)),
("#o", "#e") | ("#e", "#o") => (true, 8, Some(true)),
("#o", "#i") | ("#i", "#o") => (true, 8, Some(false)),
("#d", "#e") | ("#e", "#d") => (true, 10, Some(true)),
("#d", "#i") | ("#i", "#d") => (true, 10, Some(false)),
("#x", "#e") | ("#e", "#x") => (true, 16, Some(true)),
("#x", "#i") | ("#i", "#x") => (true, 16, Some(false)),
(tokens::PREFIX_BINARY, tokens::PREFIX_EXACT)
| (tokens::PREFIX_EXACT, tokens::PREFIX_BINARY) => (true, 2, Some(true)),
(tokens::PREFIX_BINARY, tokens::PREFIX_INEXACT)
| (tokens::PREFIX_INEXACT, tokens::PREFIX_BINARY) => (true, 2, Some(false)),
(tokens::PREFIX_OCTAL, tokens::PREFIX_EXACT)
| (tokens::PREFIX_EXACT, tokens::PREFIX_OCTAL) => (true, 8, Some(true)),
(tokens::PREFIX_OCTAL, tokens::PREFIX_INEXACT)
| (tokens::PREFIX_INEXACT, tokens::PREFIX_OCTAL) => (true, 8, Some(false)),
(tokens::PREFIX_DECIMAL, tokens::PREFIX_EXACT)
| (tokens::PREFIX_EXACT, tokens::PREFIX_DECIMAL) => (true, 10, Some(true)),
(tokens::PREFIX_DECIMAL, tokens::PREFIX_INEXACT)
| (tokens::PREFIX_INEXACT, tokens::PREFIX_DECIMAL) => (true, 10, Some(false)),
(tokens::PREFIX_HEX, tokens::PREFIX_EXACT)
| (tokens::PREFIX_EXACT, tokens::PREFIX_HEX) => (true, 16, Some(true)),
(tokens::PREFIX_HEX, tokens::PREFIX_INEXACT)
| (tokens::PREFIX_INEXACT, tokens::PREFIX_HEX) => (true, 16, Some(false)),
_ => (false, 10, None),
}
} else if n_prefixes == 1 {
match &token[0..2] {
"#b" => (true, 2, None),
"#o" => (true, 8, None),
"#d" => (true, 10, None),
"#x" => (true, 16, None),
"#e" => (true, 10, Some(true)),
"#i" => (true, 10, Some(false)),
tokens::PREFIX_BINARY => (true, 2, None),
tokens::PREFIX_OCTAL => (true, 8, None),
tokens::PREFIX_DECIMAL => (true, 10, None),
tokens::PREFIX_HEX => (true, 16, None),
tokens::PREFIX_EXACT => (true, 10, Some(true)),
tokens::PREFIX_INEXACT => (true, 10, Some(false)),
_ => (false, 10, None),
}
} else {
Expand Down
Loading

0 comments on commit 4a90c8e

Please sign in to comment.