pub use super::tinylang::types::{NativeProcedure, Nil, Procedure};
use super::tinylang::TinyLang;
use crate::value::AbstractValue;
use crate::Interpreter;
use gcmodule::Trace;
use std::fmt;
type Expr = <super::MiniLang as Interpreter>::Expr;
type Value = <super::MiniLang as Interpreter>::Value;
#[derive(Trace, Debug)]
pub struct Bool(pub bool);
#[derive(Trace, Debug)]
pub struct Int(pub i64);
#[derive(Trace, Debug)]
pub struct Str(pub String);
#[derive(Trace, Debug)]
pub struct List(pub Vec<Value>);
#[derive(Trace, Debug)]
pub struct Quote(pub Expr);
impl Str {
pub fn from_escaped(mut string: &str) -> Str {
if string.starts_with('"') && string.ends_with('"') && string.len() >= 2 {
string = unsafe { string.get_unchecked(1..string.len() - 1) };
}
let string = if string.find('\\').is_some() {
let mut new_string = String::with_capacity(string.len());
let mut escaped = false;
for ch in string.chars() {
match (ch, escaped) {
('\\', false) => {
escaped = true;
}
('t', true) => {
new_string.push('\t');
}
('n', true) => {
new_string.push('\n');
}
_ => {
new_string.push(ch);
escaped = false;
}
}
}
new_string
} else {
string.to_string()
};
Str(string)
}
}
impl fmt::Display for Bool {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = if self.0 { "#t" } else { "#f" };
write!(f, "{}", s)
}
}
impl AbstractValue<TinyLang> for Bool {}
impl fmt::Display for Int {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
impl AbstractValue<TinyLang> for Int {}
impl fmt::Display for Str {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
impl AbstractValue<TinyLang> for Str {}
impl fmt::Display for List {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "'(")?;
let mut padding = "";
for v in self.0.iter() {
write!(f, "{}{}", padding, v)?;
padding = " ";
}
write!(f, ")")
}
}
impl AbstractValue<TinyLang> for List {}
impl fmt::Display for Quote {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "'{}", self.0)
}
}
impl AbstractValue<TinyLang> for Quote {}