use crate::types::{Expression, ExpressionKind};
use crate::parser::Parser;
use crate::type_system::Typed;
use crate::types::ParserError;
use std::collections::HashMap;
mod field;
mod pair;
mod tuple;
mod value;
mod variable;
pub use self::field::*;
pub use self::pair::*;
pub use self::tuple::*;
pub use self::value::*;
pub use self::variable::*;
pub type LinearizeResult = Result<HashMap<VariablePattern, Box<Expression>>, ParserError>;
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum Pattern {
Field(FieldPattern),
Tuple(TuplePattern),
Value(ValuePattern),
Variable(VariablePattern),
Pair(PairPattern),
}
impl Pattern {
fn _pattern_or_value_pattern(
&self,
expression: Box<Expression>,
) -> Result<Pattern, ParserError> {
match expression.kind {
ExpressionKind::Pattern(pattern) => Ok(pattern),
_ => Ok(Pattern::Value(ValuePattern { expression })),
}
}
pub fn expect_field(self) -> Result<FieldPattern, ParserError> {
match self {
Pattern::Field(pattern) => Ok(pattern),
_ => Err(ParserError::UnexpectedPattern {
expected: String::from("FieldPattern"),
found: self
.get_type()
.unwrap_or(String::from("<dynamically typed>")),
}),
}
}
pub fn expect_tuple(self) -> Result<TuplePattern, ParserError> {
match self {
Pattern::Tuple(pattern) => Ok(pattern),
_ => Err(ParserError::UnexpectedPattern {
expected: String::from("TuplePattern"),
found: self
.get_type()
.unwrap_or(String::from("<dynamically typed>")),
}),
}
}
pub fn expect_value(self) -> Result<Expression, ParserError> {
match self {
Pattern::Value(pattern) => Ok(*pattern.expression),
_ => Err(ParserError::UnexpectedPattern {
expected: String::from("ValuePattern"),
found: self
.get_type()
.unwrap_or(String::from("<dynamically typed>")),
}),
}
}
pub fn expect_variable(self) -> Result<VariablePattern, ParserError> {
match self {
Pattern::Variable(pattern) => Ok(pattern),
_ => Err(ParserError::UnexpectedPattern {
expected: String::from("VariablePattern"),
found: self
.get_type()
.unwrap_or(String::from("<dynamically typed>")),
}),
}
}
pub fn expect_pair(self) -> Result<PairPattern, ParserError> {
match self {
Pattern::Pair(pattern) => Ok(pattern),
_ => Err(ParserError::UnexpectedPattern {
expected: String::from("PairPattern"),
found: self
.get_type()
.unwrap_or(String::from("<dynamically typed>")),
}),
}
}
}
impl Typed for Pattern {
fn get_type(&self) -> Option<String> {
match self {
Pattern::Field(_) => Some(String::from("FieldPattern")),
Pattern::Tuple(_) => Some(String::from("TuplePattern")),
Pattern::Value(_) => Some(String::from("ValuePattern")),
Pattern::Variable(_) => Some(String::from("VariablePattern")),
Pattern::Pair(_) => Some(String::from("PairPattern")),
}
}
}
impl Pattern {
pub fn linearize(&self, parser: &Parser, other: Pattern) -> LinearizeResult {
match self {
Pattern::Field(reference) => self.linearize_field(parser, reference.clone(), other),
Pattern::Tuple(reference) => self.linearize_tuple(parser, reference.clone(), other),
Pattern::Value(reference) => self.linearize_value(parser, reference.clone(), other),
Pattern::Variable(reference) => self.linearize_variable(reference.clone(), other),
Pattern::Pair(reference) => self.linearize_pair(parser, reference.clone(), other),
}
}
pub fn matches_with(&self, parser: &Parser, other: Pattern) -> bool {
match self.linearize(parser, other) {
Ok(_) => true,
Err(_) => false,
}
}
pub fn get_precedence(&self) -> usize {
match self {
Pattern::Value(_) => 2,
_ => 1,
}
}
pub fn desugar(&mut self) -> Self {
match self {
Pattern::Field(pattern) => Pattern::Field(pattern.clone().desugar()),
Pattern::Tuple(pattern) => Pattern::Tuple(pattern.clone().desugar()),
Pattern::Value(pattern) => Pattern::Value(pattern.clone().desugar()),
Pattern::Variable(pattern) => Pattern::Variable(pattern.clone().desugar()),
Pattern::Pair(pattern) => Pattern::Pair(pattern.clone().desugar()),
}
}
fn linearize_field(
&self,
parser: &Parser,
reference: FieldPattern,
other: Pattern,
) -> LinearizeResult {
if let Pattern::Field(given) = other {
if given.name != reference.name {
return Err(ParserError::NoMatch);
}
given.value.linearize(parser, *reference.value)
} else {
Err(ParserError::NoMatch)
}
}
fn linearize_tuple(
&self,
parser: &Parser,
reference: TuplePattern,
other: Pattern,
) -> LinearizeResult {
if let Pattern::Tuple(TuplePattern {
child: other_pattern,
}) = other
{
reference.child.linearize(parser, *other_pattern)
} else {
Err(ParserError::NoMatch)
}
}
fn linearize_value(
&self,
parser: &Parser,
reference: ValuePattern,
other: Pattern,
) -> LinearizeResult {
let reference_lexeme =
parser.get_lexeme(reference.expression.start_pos, reference.expression.end_pos)?;
if let Pattern::Value(ValuePattern { expression }) = other {
let given_lexeme = parser.get_lexeme(expression.start_pos, expression.end_pos)?;
if reference.expression.kind == expression.kind && reference_lexeme == given_lexeme {
Ok(HashMap::new())
} else {
Err(ParserError::NoMatch)
}
} else {
Err(ParserError::NoMatch)
}
}
fn linearize_variable(&self, reference: VariablePattern, other: Pattern) -> LinearizeResult {
let mut variables = HashMap::new();
if let Some(name) = reference.name {
if let Pattern::Value(ValuePattern { expression }) = other {
variables.insert(
VariablePattern {
name: Some(name),
type_id: None,
},
expression,
);
} else {
return Err(ParserError::NoMatch);
}
}
Ok(variables)
}
fn linearize_pair(
&self,
parser: &Parser,
reference: PairPattern,
other: Pattern,
) -> LinearizeResult {
if let Pattern::Pair(PairPattern { left, right }) = other {
let mut left_map = reference.left.linearize(parser, *left)?;
let right_map = reference.right.linearize(parser, *right)?;
left_map.extend(right_map);
Ok(left_map)
} else {
Err(ParserError::NoMatch)
}
}
}
impl std::fmt::Display for Pattern {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Pattern::Field(pattern) => write!(f, "{}", pattern),
Pattern::Tuple(pattern) => write!(f, "{}", pattern),
Pattern::Value(pattern) => write!(f, "{}", pattern),
Pattern::Variable(pattern) => write!(f, "{}", pattern),
Pattern::Pair(pattern) => write!(f, "{}", pattern),
}
}
}