use crate::type_system::Typed;
use crate::types::ParserError;
use crate::types::{Literal, PairPattern, Pattern, TokenKind, ValuePattern};
mod block;
mod conditional;
mod infix;
mod method;
mod prefix;
mod return_expr;
mod var;
pub use self::block::Block;
pub use self::conditional::Conditional;
pub use self::infix::Infix;
pub use self::method::{Call, Method};
pub use self::prefix::Prefix;
pub use self::return_expr::ReturnExpression;
pub use self::var::VarDeclaration;
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Expression {
pub kind: ExpressionKind,
pub start_pos: usize,
pub end_pos: usize,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum ExpressionKind {
Conditional(Conditional),
List(Option<Box<Expression>>),
Literal(Literal),
Pattern(Pattern),
Type(String),
Prefix(Prefix),
Infix(Infix),
Call(Call),
Method(Method),
Block(Block),
Identifier,
Var(VarDeclaration),
Return(ReturnExpression),
}
impl ExpressionKind {
pub fn desugar(self) -> Self {
match self {
ExpressionKind::Infix(mut infix) => {
infix.left.desugar();
infix.right.desugar();
let method_name = match &infix.operator.kind {
TokenKind::Plus => "+".to_string(),
TokenKind::Minus => "-".to_string(),
TokenKind::Star => "*".to_string(),
TokenKind::Slash => "/".to_string(),
TokenKind::Percent => "%".to_string(),
TokenKind::Caret => "^".to_string(),
TokenKind::EqualEqual => "==".to_string(),
TokenKind::BangEqual => "!=".to_string(),
TokenKind::Greater => ">".to_string(),
TokenKind::GreaterEqual => ">=".to_string(),
TokenKind::Smaller => "<".to_string(),
TokenKind::SmallerEqual => "<=".to_string(),
_ => unimplemented!(),
};
ExpressionKind::Call(Call {
name: method_name,
signature: Some(Pattern::Pair(PairPattern {
left: Box::new(Pattern::Value(ValuePattern {
expression: infix.left,
})),
right: Box::new(Pattern::Value(ValuePattern {
expression: infix.right,
})),
})),
})
}
ExpressionKind::Call(Call {
ref name,
ref signature,
}) => {
if let Some(pattern) = signature {
match pattern {
Pattern::Value(ValuePattern { expression }) => {
let mut expr = expression.clone();
expr.desugar();
ExpressionKind::Call(Call {
name: name.to_string(),
signature: Some(Pattern::Value(ValuePattern { expression: expr })),
})
}
_ => self,
}
} else {
self
}
}
ExpressionKind::Method(mut method) => {
method.body.desugar();
ExpressionKind::Method(method)
}
_ => self,
}
}
}
impl Expression {
pub fn pattern_or_value_pattern(&self) -> Result<Pattern, ParserError> {
match self.kind.clone() {
ExpressionKind::Pattern(pattern) => Ok(pattern),
_ => Ok(Pattern::Value(ValuePattern {
expression: Box::new(self.clone()),
})),
}
}
pub fn expect_pattern(&self) -> Result<Pattern, ParserError> {
match self.kind.clone() {
ExpressionKind::Pattern(pattern) => Ok(pattern),
_ => Err(ParserError::ExpectedPattern),
}
}
pub fn desugar(&mut self) {
self.kind = self.kind.clone().desugar();
}
}
impl Typed for Expression {
fn get_type(&self) -> Option<String> {
match &self.kind {
ExpressionKind::Conditional(_) => Some(String::from("ConditionalExpression")),
ExpressionKind::List(_) => Some(String::from("ListExpression")),
ExpressionKind::Literal(literal) => literal.get_type(),
ExpressionKind::Pattern(pattern) => pattern.get_type(),
ExpressionKind::Type(type_id) => Some(type_id.clone()),
ExpressionKind::Prefix(_) => Some(String::from("PrefixExpression")),
ExpressionKind::Infix(_) => Some(String::from("InfixExpression")),
ExpressionKind::Call(_) => Some(String::from("CallExpression")),
ExpressionKind::Method(_) => Some(String::from("MethodExpression")),
ExpressionKind::Block(_) => Some(String::from("BlockExpression")),
ExpressionKind::Identifier => Some(String::from("Identifier")),
ExpressionKind::Var(_) => Some(String::from("VarExpression")),
ExpressionKind::Return(_) => Some(String::from("ReturnExpression")),
}
}
}