use crate::{Symbol, Tag, Value};
#[derive(Debug, Clone, PartialEq)]
pub enum Stmt {
None,
Value(Value),
Word(Symbol),
List(Vec<Stmt>),
Map(Vec<(Symbol, Stmt)>),
Call(Box<Stmt>, Vec<Stmt>), Return(Box<Stmt>),
If(Vec<(Stmt, Vec<Stmt>)>),
For(Option<Symbol>, Symbol, Box<Stmt>, Vec<Stmt>), While(Box<Stmt>, Vec<Stmt>),
Assign(Symbol, Box<Stmt>, bool), Tag(Tag),
Fn(Vec<Symbol>, Vec<Stmt>), Args(Vec<(Symbol, Stmt)>), }
impl From<Tag> for Stmt {
fn from(tag: Tag) -> Stmt {
Stmt::Tag(tag)
}
}
impl From<String> for Stmt {
fn from(s: String) -> Stmt {
Stmt::Value(s.into())
}
}
impl From<&str> for Stmt {
fn from(s: &str) -> Stmt {
Stmt::Value(s.into())
}
}
impl Stmt {
pub fn is_some(&self) -> bool {
!self.is_none()
}
pub fn is_none(&self) -> bool {
matches!(self, Stmt::None)
}
pub fn to_str(&self) -> &str {
match self {
Stmt::Value(Value::String(s)) => s.to_str(),
Stmt::Word(s) => s.to_str(),
_ => "",
}
}
pub fn to_string(&self) -> String {
match self {
Stmt::None => "Stmt::None".to_string(),
Stmt::Value(Value::String(s)) => format!(r#""{}""#, s),
Stmt::Value(v) => format!("{}", v),
Stmt::Word(s) => s.to_string(),
Stmt::Tag(tag) => format!("{:?}", tag),
Stmt::Return(ex) => format!("return {:?}", ex),
Stmt::Args(args) => args
.iter()
.map(|(k, v)| format!("{}: {:?}", k, v))
.collect::<Vec<_>>()
.join(", "),
Stmt::List(list) => format!(
"[{}]",
list.iter()
.map(|ex| ex.to_string())
.collect::<Vec<_>>()
.join(", ")
),
Stmt::Map(map) => format!(
"{{{}}}",
map.iter()
.map(|(k, v)| format!("{}: {}", k.to_string(), v.to_string()))
.collect::<Vec<_>>()
.join(", ")
),
Stmt::Assign(var, expr, re) => {
format!("{} {}= {:?}", var, if *re { ":" } else { "" }, expr)
}
Stmt::If(..) => "IF: Coming Soon™".to_string(),
Stmt::For(..) => "FOR: Coming Soon™".to_string(),
Stmt::While(test, body) => format!("while({:?}) {:?}", test, body),
Stmt::Fn(args, body) => format!("fn({:?}) {:?}", args, body),
Stmt::Call(name, args) => format!(
"{}({})",
name.to_string(),
args.iter()
.map(|a| a.to_string())
.collect::<Vec<_>>()
.join(", ")
),
}
}
}