use crate::bug;
use crate::cfg::utils::key;
use crate::semantics::cfg::Cfg;
use crate::semantics::core::PREFIX_QUOTE;
use crate::semantics::ctx::DynCtx;
use crate::semantics::val::CallVal;
use crate::semantics::val::CellVal;
use crate::semantics::val::ListVal;
use crate::semantics::val::MapVal;
use crate::semantics::val::PairVal;
use crate::semantics::val::QuoteVal;
use crate::semantics::val::SolveVal;
use crate::semantics::val::Val;
use crate::type_::Call;
use crate::type_::Cell;
use crate::type_::Key;
use crate::type_::List;
use crate::type_::Map;
use crate::type_::Pair;
use crate::type_::Quote;
use crate::type_::Solve;
pub(in crate::cfg) enum Pattern {
Any(Option<Key>),
Val(Val),
Cell(Box<Cell<Pattern>>),
Pair(Box<Pair<Pattern, Pattern>>),
List(List<Pattern>),
Map(Map<Key, Pattern>),
Quote(Box<Quote<Pattern>>),
Call(Box<Call<Pattern, Pattern>>),
Solve(Box<Solve<Pattern, Pattern>>),
}
pub(in crate::cfg) trait PatternParse {
fn parse(self, cfg: &mut Cfg, tag: &str) -> Option<Pattern>;
}
impl PatternParse for Val {
fn parse(self, cfg: &mut Cfg, tag: &str) -> Option<Pattern> {
match self {
Val::Key(key) => key.parse(cfg, tag),
Val::Cell(cell) => cell.parse(cfg, tag),
Val::Pair(pair) => pair.parse(cfg, tag),
Val::List(list) => list.parse(cfg, tag),
Val::Map(map) => map.parse(cfg, tag),
Val::Quote(quote) => quote.parse(cfg, tag),
Val::Call(call) => call.parse(cfg, tag),
Val::Solve(solve) => solve.parse(cfg, tag),
val => Some(Pattern::Val(val)),
}
}
}
impl PatternParse for Key {
fn parse(self, _cfg: &mut Cfg, _tag: &str) -> Option<Pattern> {
if self.starts_with(PREFIX_QUOTE) {
return Some(Pattern::Val(key(&self[1 ..])));
}
let pattern = if self.is_empty() { None } else { Some(self) };
Some(Pattern::Any(pattern))
}
}
impl PatternParse for CellVal {
fn parse(self, cfg: &mut Cfg, tag: &str) -> Option<Pattern> {
let cell = Cell::from(self);
let value = cell.value.parse(cfg, tag)?;
Some(Pattern::Cell(Box::new(Cell::new(value))))
}
}
impl PatternParse for QuoteVal {
fn parse(self, cfg: &mut Cfg, tag: &str) -> Option<Pattern> {
let quote = Quote::from(self);
let value = quote.value.parse(cfg, tag)?;
Some(Pattern::Quote(Box::new(Quote::new(value))))
}
}
impl PatternParse for PairVal {
fn parse(self, cfg: &mut Cfg, tag: &str) -> Option<Pattern> {
let pair = Pair::from(self);
let left = pair.left.parse(cfg, tag)?;
let right = pair.right.parse(cfg, tag)?;
Some(Pattern::Pair(Box::new(Pair::new(left, right))))
}
}
impl PatternParse for CallVal {
fn parse(self, cfg: &mut Cfg, tag: &str) -> Option<Pattern> {
let call = Call::from(self);
let func = call.func.parse(cfg, tag)?;
let input = call.input.parse(cfg, tag)?;
Some(Pattern::Call(Box::new(Call { func, input })))
}
}
impl PatternParse for SolveVal {
fn parse(self, cfg: &mut Cfg, tag: &str) -> Option<Pattern> {
let solve = Solve::from(self);
let func = solve.func.parse(cfg, tag)?;
let output = solve.output.parse(cfg, tag)?;
Some(Pattern::Solve(Box::new(Solve { func, output })))
}
}
impl PatternParse for ListVal {
fn parse(self, cfg: &mut Cfg, tag: &str) -> Option<Pattern> {
let list = List::from(self);
let mut patterns = Vec::with_capacity(list.len());
for val in list {
patterns.push(val.parse(cfg, tag)?);
}
Some(Pattern::List(patterns.into()))
}
}
impl PatternParse for MapVal {
fn parse(self, cfg: &mut Cfg, tag: &str) -> Option<Pattern> {
let map = Map::from(self);
let mut pattern_map = Map::with_capacity(map.len());
for (k, val) in map {
pattern_map.insert(k, val.parse(cfg, tag)?);
}
Some(Pattern::Map(pattern_map))
}
}
pub(in crate::cfg) trait PatternMatch<T> {
fn match_(&self, cfg: &mut Cfg, force: bool, tag: &str, val: &T) -> bool;
}
impl PatternMatch<Val> for Pattern {
fn match_(&self, cfg: &mut Cfg, force: bool, tag: &str, val: &Val) -> bool {
match self {
Pattern::Any(name) => name.match_(cfg, force, tag, val),
Pattern::Val(expected) => expected.match_(cfg, force, tag, val),
Pattern::Cell(cell) => cell.match_(cfg, force, tag, val),
Pattern::Pair(pair) => pair.match_(cfg, force, tag, val),
Pattern::List(list) => list.match_(cfg, force, tag, val),
Pattern::Map(map) => map.match_(cfg, force, tag, val),
Pattern::Quote(quote) => quote.match_(cfg, force, tag, val),
Pattern::Call(call) => call.match_(cfg, force, tag, val),
Pattern::Solve(solve) => solve.match_(cfg, force, tag, val),
}
}
}
impl PatternMatch<Val> for Option<Key> {
fn match_(&self, _cfg: &mut Cfg, _force: bool, _tag: &str, _val: &Val) -> bool {
true
}
}
impl PatternMatch<Val> for Val {
fn match_(&self, cfg: &mut Cfg, force: bool, tag: &str, val: &Val) -> bool {
let match_ = *self == *val;
if !match_ && force {
bug!(cfg, "{tag}: expected {self}, but got {val}");
}
match_
}
}
impl PatternMatch<Val> for Cell<Pattern> {
fn match_(&self, cfg: &mut Cfg, force: bool, tag: &str, val: &Val) -> bool {
let Val::Cell(val) = val else {
if force {
bug!(cfg, "{tag}: expected a cell, but got {val}");
}
return false;
};
self.value.match_(cfg, force, tag, &val.value)
}
}
impl PatternMatch<Val> for Quote<Pattern> {
fn match_(&self, cfg: &mut Cfg, force: bool, tag: &str, val: &Val) -> bool {
let Val::Quote(val) = val else {
if force {
bug!(cfg, "{tag}: expected a quote, but got {val}");
}
return false;
};
self.value.match_(cfg, force, tag, &val.value)
}
}
impl PatternMatch<Val> for Pair<Pattern, Pattern> {
fn match_(&self, cfg: &mut Cfg, force: bool, tag: &str, val: &Val) -> bool {
let Val::Pair(val) = val else {
if force {
bug!(cfg, "{tag}: expected a pair, but got {val}");
}
return false;
};
let left = self.left.match_(cfg, force, tag, &val.left);
let right = self.right.match_(cfg, force, tag, &val.right);
left && right
}
}
impl PatternMatch<Val> for Call<Pattern, Pattern> {
fn match_(&self, cfg: &mut Cfg, force: bool, tag: &str, val: &Val) -> bool {
let Val::Call(val) = val else {
if force {
bug!(cfg, "{tag}: expected a call, but got {val}");
}
return false;
};
let func = self.func.match_(cfg, force, tag, &val.func);
let input = self.input.match_(cfg, force, tag, &val.input);
func && input
}
}
impl PatternMatch<Val> for Solve<Pattern, Pattern> {
fn match_(&self, cfg: &mut Cfg, force: bool, tag: &str, val: &Val) -> bool {
let Val::Solve(val) = val else {
if force {
bug!(cfg, "{tag}: expected a solve, but got {val}");
}
return false;
};
let func = self.func.match_(cfg, force, tag, &val.func);
let output = self.output.match_(cfg, force, tag, &val.output);
func && output
}
}
impl PatternMatch<Val> for List<Pattern> {
fn match_(&self, cfg: &mut Cfg, force: bool, tag: &str, val: &Val) -> bool {
let Val::List(val) = val else {
if force {
bug!(cfg, "{tag}: expected a list, but got {val}");
}
return false;
};
if val.len() < self.len() {
if force {
bug!(cfg, "{tag}: expected length of list to be at least {}, \
but got {val}", self.len());
}
return false;
}
let mut val_iter = val.iter();
for pattern in self {
let val = val_iter.next().unwrap();
if !pattern.match_(cfg, force, tag, val) {
return false;
}
}
true
}
}
impl PatternMatch<Val> for Map<Key, Pattern> {
fn match_(&self, cfg: &mut Cfg, force: bool, tag: &str, val: &Val) -> bool {
let Val::Map(val) = val else {
if force {
bug!(cfg, "{tag}: expected a map, but got {val}");
}
return false;
};
for (k, pattern) in self {
let Some(val) = val.get(k) else {
if force {
bug!(cfg, "{tag}: value not found for key {k} in map {val}");
}
return false;
};
if !pattern.match_(cfg, force, tag, val) {
return false;
}
}
true
}
}
pub(in crate::cfg) trait PatternAssign<Ctx, Val> {
fn assign(self, cfg: &mut Cfg, tag: &str, ctx: &mut Ctx, val: Val) -> Option<()>;
}
impl PatternAssign<Val, Val> for Pattern {
fn assign(self, cfg: &mut Cfg, tag: &str, ctx: &mut Val, val: Val) -> Option<()> {
match self {
Pattern::Any(name) => name.assign(cfg, tag, ctx, val),
Pattern::Val(expected) => expected.assign(cfg, tag, ctx, val),
Pattern::Cell(cell) => cell.assign(cfg, tag, ctx, val),
Pattern::Pair(pair) => pair.assign(cfg, tag, ctx, val),
Pattern::List(list) => list.assign(cfg, tag, ctx, val),
Pattern::Map(map) => map.assign(cfg, tag, ctx, val),
Pattern::Quote(quote) => quote.assign(cfg, tag, ctx, val),
Pattern::Call(call) => call.assign(cfg, tag, ctx, val),
Pattern::Solve(solve) => solve.assign(cfg, tag, ctx, val),
}
}
}
impl PatternAssign<Val, Val> for Option<Key> {
fn assign(self, cfg: &mut Cfg, _tag: &str, ctx: &mut Val, val: Val) -> Option<()> {
let Some(key) = self else {
return Some(());
};
ctx.set(cfg, key, val);
if cfg.is_aborted() {
return None;
}
Some(())
}
}
impl PatternAssign<Val, Val> for Val {
fn assign(self, _cfg: &mut Cfg, _tag: &str, _ctx: &mut Val, _val: Val) -> Option<()> {
Some(())
}
}
impl PatternAssign<Val, Val> for Cell<Pattern> {
fn assign(self, cfg: &mut Cfg, tag: &str, ctx: &mut Val, val: Val) -> Option<()> {
let Val::Cell(val) = val else {
bug!(cfg, "{tag}: expected a cell, but got {val}");
return None;
};
let val = Cell::from(val);
self.value.assign(cfg, tag, ctx, val.value)?;
Some(())
}
}
impl PatternAssign<Val, Val> for Quote<Pattern> {
fn assign(self, cfg: &mut Cfg, tag: &str, ctx: &mut Val, val: Val) -> Option<()> {
let Val::Quote(val) = val else {
bug!(cfg, "{tag}: expected a quote, but got {val}");
return None;
};
let val = Quote::from(val);
self.value.assign(cfg, tag, ctx, val.value)?;
Some(())
}
}
impl PatternAssign<Val, Val> for Pair<Pattern, Pattern> {
fn assign(self, cfg: &mut Cfg, tag: &str, ctx: &mut Val, val: Val) -> Option<()> {
let Val::Pair(val) = val else {
bug!(cfg, "{tag}: expected a pair, but got {val}");
return None;
};
let val = Pair::from(val);
self.left.assign(cfg, tag, ctx, val.left)?;
self.right.assign(cfg, tag, ctx, val.right)?;
Some(())
}
}
impl PatternAssign<Val, Val> for Call<Pattern, Pattern> {
fn assign(self, cfg: &mut Cfg, tag: &str, c: &mut Val, val: Val) -> Option<()> {
let Val::Call(val) = val else {
bug!(cfg, "{tag}: expected a call, but got {val}");
return None;
};
let val = Call::from(val);
self.func.assign(cfg, tag, c, val.func)?;
self.input.assign(cfg, tag, c, val.input)?;
Some(())
}
}
impl PatternAssign<Val, Val> for Solve<Pattern, Pattern> {
fn assign(self, cfg: &mut Cfg, tag: &str, c: &mut Val, val: Val) -> Option<()> {
let Val::Solve(val) = val else {
bug!(cfg, "{tag}: expected a solve, but got {val}");
return None;
};
let val = Solve::from(val);
self.func.assign(cfg, tag, c, val.func)?;
self.output.assign(cfg, tag, c, val.output)?;
Some(())
}
}
impl PatternAssign<Val, Val> for List<Pattern> {
fn assign(self, cfg: &mut Cfg, tag: &str, ctx: &mut Val, val: Val) -> Option<()> {
let Val::List(val) = val else {
bug!(cfg, "{tag}: expected a list, but got {val}");
return None;
};
if val.len() < self.len() {
bug!(cfg, "{tag}: expected length of list to be at least {}, \
but got {val}", self.len());
return None;
}
let mut val_iter = List::from(val).into_iter();
for p in self {
p.assign(cfg, tag, ctx, val_iter.next().unwrap())?;
}
Some(())
}
}
impl PatternAssign<Val, Val> for Map<Key, Pattern> {
fn assign(self, cfg: &mut Cfg, tag: &str, ctx: &mut Val, val: Val) -> Option<()> {
let Val::Map(mut val) = val else {
bug!(cfg, "{tag}: expected a map, but got {val}");
return None;
};
for (k, pattern) in self {
let Some(val) = val.remove(&k) else {
bug!(cfg, "{tag}: value not found for key {k} in map {val}");
return None;
};
pattern.assign(cfg, tag, ctx, val)?;
}
Some(())
}
}