#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SpecialForm {
Quote,
Quasiquote,
If,
Cond,
When,
Unless,
Let,
LetStar,
LetRec,
Lambda,
Define,
Set,
Begin,
And,
Or,
Not,
Try,
MacroexpandOne,
MacroexpandAll,
Delay,
Eval,
Provide,
Require,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum VmDisposition {
Compiled,
Fallback,
}
impl SpecialForm {
pub const ALL: &'static [Self] = &[
Self::Quote,
Self::Quasiquote,
Self::If,
Self::Cond,
Self::When,
Self::Unless,
Self::Let,
Self::LetStar,
Self::LetRec,
Self::Lambda,
Self::Define,
Self::Set,
Self::Begin,
Self::And,
Self::Or,
Self::Not,
Self::Try,
Self::MacroexpandOne,
Self::MacroexpandAll,
Self::Delay,
Self::Eval,
Self::Provide,
Self::Require,
];
pub fn symbol(self) -> &'static str {
match self {
Self::Quote => "quote",
Self::Quasiquote => "quasiquote",
Self::If => "if",
Self::Cond => "cond",
Self::When => "when",
Self::Unless => "unless",
Self::Let => "let",
Self::LetStar => "let*",
Self::LetRec => "letrec",
Self::Lambda => "lambda",
Self::Define => "define",
Self::Set => "set!",
Self::Begin => "begin",
Self::And => "and",
Self::Or => "or",
Self::Not => "not",
Self::Try => "try",
Self::MacroexpandOne => "macroexpand-1",
Self::MacroexpandAll => "macroexpand",
Self::Delay => "delay",
Self::Eval => "eval",
Self::Provide => "provide",
Self::Require => "require",
}
}
pub fn vm_disposition(self) -> VmDisposition {
match self {
Self::Quote
| Self::If
| Self::Begin
| Self::Define
| Self::Let
| Self::Lambda
| Self::Set
| Self::And
| Self::Or
| Self::Not
| Self::Try => VmDisposition::Compiled,
Self::Require
| Self::Provide
| Self::Delay
| Self::Eval
| Self::MacroexpandAll
| Self::MacroexpandOne => VmDisposition::Fallback,
Self::Quasiquote
| Self::Cond
| Self::When
| Self::Unless
| Self::LetStar
| Self::LetRec => VmDisposition::Fallback,
}
}
pub fn from_symbol(s: &str) -> Option<Self> {
Some(match s {
"quote" => Self::Quote,
"quasiquote" => Self::Quasiquote,
"if" => Self::If,
"cond" => Self::Cond,
"when" => Self::When,
"unless" => Self::Unless,
"let" => Self::Let,
"let*" => Self::LetStar,
"letrec" => Self::LetRec,
"lambda" => Self::Lambda,
"define" => Self::Define,
"set!" => Self::Set,
"begin" => Self::Begin,
"and" => Self::And,
"or" => Self::Or,
"not" => Self::Not,
"try" => Self::Try,
"macroexpand-1" => Self::MacroexpandOne,
"macroexpand" => Self::MacroexpandAll,
"delay" => Self::Delay,
"eval" => Self::Eval,
"provide" => Self::Provide,
"require" => Self::Require,
_ => return None,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn recognizes_core_forms() {
assert_eq!(SpecialForm::from_symbol("if"), Some(SpecialForm::If));
assert_eq!(
SpecialForm::from_symbol("lambda"),
Some(SpecialForm::Lambda)
);
assert_eq!(SpecialForm::from_symbol("let*"), Some(SpecialForm::LetStar));
assert_eq!(SpecialForm::from_symbol("set!"), Some(SpecialForm::Set));
assert_eq!(SpecialForm::from_symbol("foo"), None);
}
}