use an enum for OpDesc spec

This commit is contained in:
Bennet Bleßmann
2024-07-31 23:48:27 +02:00
parent 2814d79b56
commit 409f56ea37
9 changed files with 216 additions and 148 deletions

View File

@@ -24,8 +24,6 @@ use std::fmt;
use std::ops::{AddAssign, Deref, DerefMut}; use std::ops::{AddAssign, Deref, DerefMut};
use std::path::PathBuf; use std::path::PathBuf;
use crate::{is_infix, is_postfix};
pub type PredicateKey = (Atom, usize); // name, arity. pub type PredicateKey = (Atom, usize); // name, arity.
/* /*
@@ -403,16 +401,6 @@ pub struct OpDecl {
pub(crate) name: Atom, pub(crate) name: Atom,
} }
#[inline(always)]
pub(crate) fn fixity(spec: u32) -> Fixity {
match spec {
XFY | XFX | YFX => Fixity::In,
XF | YF => Fixity::Post,
FX | FY => Fixity::Pre,
_ => unreachable!(),
}
}
impl OpDecl { impl OpDecl {
#[inline] #[inline]
pub(crate) fn new(op_desc: OpDesc, name: Atom) -> Self { pub(crate) fn new(op_desc: OpDesc, name: Atom) -> Self {
@@ -429,7 +417,7 @@ impl OpDecl {
} }
pub(crate) fn insert_into_op_dir(&self, op_dir: &mut OpDir) -> Option<OpDesc> { pub(crate) fn insert_into_op_dir(&self, op_dir: &mut OpDir) -> Option<OpDesc> {
let key = (self.name, fixity(self.op_desc.get_spec() as u32)); let key = (self.name, self.op_desc.get_spec().fixity());
if let Some(cell) = op_dir.get_mut(&key) { if let Some(cell) = op_dir.get_mut(&key) {
let (old_prec, old_spec) = cell.get(); let (old_prec, old_spec) = cell.get();
@@ -447,7 +435,7 @@ impl OpDecl {
) -> Result<(), SessionError> { ) -> Result<(), SessionError> {
let (spec, name) = (self.op_desc.get_spec(), self.name); let (spec, name) = (self.op_desc.get_spec(), self.name);
if is_infix!(spec as u32) { if spec.is_infix() {
if let Some(desc) = existing_desc { if let Some(desc) = existing_desc {
if desc.post > 0 { if desc.post > 0 {
return Err(SessionError::OpIsInfixAndPostFix(name)); return Err(SessionError::OpIsInfixAndPostFix(name));
@@ -455,7 +443,7 @@ impl OpDecl {
} }
} }
if is_postfix!(spec as u32) { if spec.is_postfix() {
if let Some(desc) = existing_desc { if let Some(desc) = existing_desc {
if desc.inf > 0 { if desc.inf > 0 {
return Err(SessionError::OpIsInfixAndPostFix(name)); return Err(SessionError::OpIsInfixAndPostFix(name));

View File

@@ -6,8 +6,8 @@ use crate::parser::dashu::integer::Sign;
use crate::parser::dashu::{ibig, Integer, Rational}; use crate::parser::dashu::{ibig, Integer, Rational};
use crate::{ use crate::{
alpha_numeric_char, capital_letter_char, cut_char, decimal_digit_char, graphic_token_char, alpha_numeric_char, capital_letter_char, cut_char, decimal_digit_char, graphic_token_char,
is_fx, is_infix, is_postfix, is_prefix, is_xf, is_xfx, is_xfy, is_yfx, semicolon_char, semicolon_char, sign_char, single_quote_char, small_letter_char, solo_char,
sign_char, single_quote_char, small_letter_char, solo_char, variable_indicator_char, variable_indicator_char,
}; };
use crate::forms::*; use crate::forms::*;
@@ -51,7 +51,7 @@ impl DirectedOp {
fn is_prefix(&self) -> bool { fn is_prefix(&self) -> bool {
match self { match self {
&DirectedOp::Left(_name, cell) | &DirectedOp::Right(_name, cell) => { &DirectedOp::Left(_name, cell) | &DirectedOp::Right(_name, cell) => {
is_prefix!(cell.get_spec() as u32) cell.get_spec().is_prefix()
} }
} }
} }
@@ -60,7 +60,7 @@ impl DirectedOp {
fn is_negative_sign(&self) -> bool { fn is_negative_sign(&self) -> bool {
match self { match self {
&DirectedOp::Left(name, cell) | &DirectedOp::Right(name, cell) => { &DirectedOp::Left(name, cell) | &DirectedOp::Right(name, cell) => {
name == atom!("-") && is_prefix!(cell.get_spec() as u32) name == atom!("-") && cell.get_spec().is_prefix()
} }
} }
} }
@@ -78,24 +78,24 @@ fn needs_bracketing(child_desc: OpDesc, op: &DirectedOp) -> bool {
if &*name.as_str() == "-" { if &*name.as_str() == "-" {
let child_assoc = child_desc.get_spec(); let child_assoc = child_desc.get_spec();
if is_prefix!(spec) && (is_postfix!(child_assoc) || is_infix!(child_assoc)) { if spec.is_prefix() && (child_assoc.is_postfix() || child_assoc.is_infix()) {
return true; return true;
} }
} }
let is_strict_right = is_yfx!(spec) || is_xfx!(spec) || is_fx!(spec); let is_strict_right = spec.is_strict_right();
child_desc.get_prec() > priority child_desc.get_prec() > priority
|| (child_desc.get_prec() == priority && is_strict_right) || (child_desc.get_prec() == priority && is_strict_right)
} }
DirectedOp::Right(_, cell) => { DirectedOp::Right(_, cell) => {
let (priority, spec) = cell.get(); let (priority, spec) = cell.get();
let is_strict_left = is_xfx!(spec) || is_xfy!(spec) || is_xf!(spec); let is_strict_left = spec.is_strict_left();
if child_desc.get_prec() > priority if child_desc.get_prec() > priority
|| (child_desc.get_prec() == priority && is_strict_left) || (child_desc.get_prec() == priority && is_strict_left)
{ {
true true
} else if (is_postfix!(spec) || is_infix!(spec)) && !is_postfix!(child_desc.get_spec()) } else if (spec.is_postfix() || spec.is_infix()) && !child_desc.get_spec().is_postfix()
{ {
*cell != child_desc && child_desc.get_prec() == priority *cell != child_desc && child_desc.get_prec() == priority
} else { } else {
@@ -121,7 +121,7 @@ impl<'a, ElideLists> StackfulPreOrderHeapIter<'a, ElideLists> {
None => return false, None => return false,
}; };
let mut parent_spec = DirectedOp::Left(atom!("-"), OpDesc::build_with(200, FY as u8)); let mut parent_spec = DirectedOp::Left(atom!("-"), OpDesc::build_with(200, FY));
loop { loop {
let cell = self.read_cell(h); let cell = self.read_cell(h);
@@ -131,7 +131,7 @@ impl<'a, ElideLists> StackfulPreOrderHeapIter<'a, ElideLists> {
read_heap_cell!(self.heap[s], read_heap_cell!(self.heap[s],
(HeapCellValueTag::Atom, (name, _arity)) => { (HeapCellValueTag::Atom, (name, _arity)) => {
if let Some(spec) = fetch_atom_op_spec(name, None, op_dir) { if let Some(spec) = fetch_atom_op_spec(name, None, op_dir) {
if is_postfix!(spec.get_spec() as u32) || is_infix!(spec.get_spec() as u32) { if spec.get_spec().is_postfix() || spec.get_spec().is_infix() {
if needs_bracketing(spec, &parent_spec) { if needs_bracketing(spec, &parent_spec) {
return false; return false;
} else { } else {
@@ -592,7 +592,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
} }
fn enqueue_op(&mut self, mut max_depth: usize, name: Atom, spec: OpDesc) { fn enqueue_op(&mut self, mut max_depth: usize, name: Atom, spec: OpDesc) {
if is_postfix!(spec.get_spec()) { if spec.get_spec().is_postfix() {
if self.max_depth_exhausted(max_depth) { if self.max_depth_exhausted(max_depth) {
self.iter.pop_stack(); self.iter.pop_stack();
self.state_stack.push(TokenOrRedirect::Atom(atom!("..."))); self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
@@ -610,7 +610,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
right_directed_op, right_directed_op,
)); ));
} }
} else if is_prefix!(spec.get_spec()) { } else if spec.get_spec().is_prefix() {
if self.max_depth_exhausted(max_depth) { if self.max_depth_exhausted(max_depth) {
self.iter.pop_stack(); self.iter.pop_stack();
self.state_stack.push(TokenOrRedirect::Atom(atom!("..."))); self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
@@ -639,7 +639,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
self.state_stack.push(TokenOrRedirect::Atom(atom!("..."))); self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
} else if self.check_max_depth(&mut max_depth) { } else if self.check_max_depth(&mut max_depth) {
if is_xfy!(spec.get_spec()) { if matches!(spec.get_spec(), XFY) {
let left_directed_op = DirectedOp::Left(name, spec); let left_directed_op = DirectedOp::Left(name, spec);
self.state_stack self.state_stack
@@ -791,7 +791,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
let dot_atom = atom!("."); let dot_atom = atom!(".");
if let Some(spec) = op_desc { if let Some(spec) = op_desc {
if dot_atom == name && is_infix!(spec.get_spec()) && !self.ignore_ops { if dot_atom == name && spec.get_spec().is_infix() && !self.ignore_ops {
self.push_list(max_depth); self.push_list(max_depth);
return true; return true;
} }
@@ -1328,7 +1328,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
fn close_list(&mut self, switch: Rc<Cell<(bool, usize)>>) -> Option<Rc<Cell<(bool, usize)>>> { fn close_list(&mut self, switch: Rc<Cell<(bool, usize)>>) -> Option<Rc<Cell<(bool, usize)>>> {
if let Some(TokenOrRedirect::Op(_, op_desc)) = self.state_stack.last() { if let Some(TokenOrRedirect::Op(_, op_desc)) = self.state_stack.last() {
if is_postfix!(op_desc.get_spec()) || is_infix!(op_desc.get_spec()) { if op_desc.get_spec().is_postfix() || op_desc.get_spec().is_infix() {
self.state_stack.push(TokenOrRedirect::ChildCloseList); self.state_stack.push(TokenOrRedirect::ChildCloseList);
return None; return None;
} }
@@ -1775,7 +1775,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
TokenOrRedirect::Op(atom, op) => { TokenOrRedirect::Op(atom, op) => {
self.print_op(&atom.as_str()); self.print_op(&atom.as_str());
if is_prefix!(op.get_spec()) { if op.get_spec().is_prefix() {
self.set_parent_of_first_op(Some(DirectedOp::Left(atom, op))); self.set_parent_of_first_op(Some(DirectedOp::Left(atom, op)));
} }
} }
@@ -2120,9 +2120,9 @@ mod tests {
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(&wam.machine_st.heap);
wam.op_dir wam.op_dir
.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX as u8)); .insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX));
wam.op_dir wam.op_dir
.insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX as u8)); .insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX));
assert_eq!( assert_eq!(
&wam.parse_and_print_term("[a|[] + b].").unwrap(), &wam.parse_and_print_term("[a|[] + b].").unwrap(),
@@ -2139,10 +2139,10 @@ mod tests {
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(&wam.machine_st.heap);
wam.op_dir wam.op_dir
.insert((atom!("fy"), Fixity::Pre), OpDesc::build_with(9, FY as u8)); .insert((atom!("fy"), Fixity::Pre), OpDesc::build_with(9, FY));
wam.op_dir wam.op_dir
.insert((atom!("yf"), Fixity::Post), OpDesc::build_with(9, YF as u8)); .insert((atom!("yf"), Fixity::Post), OpDesc::build_with(9, YF));
assert_eq!( assert_eq!(
&wam.parse_and_print_term("(fy (fy 1)yf)yf.").unwrap(), &wam.parse_and_print_term("(fy (fy 1)yf)yf.").unwrap(),

View File

@@ -1419,11 +1419,11 @@ mod tests {
let mut wam = MachineState::new(); let mut wam = MachineState::new();
let mut op_dir = default_op_dir(); let mut op_dir = default_op_dir();
op_dir.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX as u8)); op_dir.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX));
op_dir.insert((atom!("-"), Fixity::In), OpDesc::build_with(500, YFX as u8)); op_dir.insert((atom!("-"), Fixity::In), OpDesc::build_with(500, YFX));
op_dir.insert((atom!("-"), Fixity::Pre), OpDesc::build_with(200, FY as u8)); op_dir.insert((atom!("-"), Fixity::Pre), OpDesc::build_with(200, FY));
op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX as u8)); op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX));
op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX as u8)); op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX));
let term_write_result = let term_write_result =
parse_and_write_parsed_term_to_heap(&mut wam, "3 + 4 - 1 + 2.", &op_dir).unwrap(); parse_and_write_parsed_term_to_heap(&mut wam, "3 + 4 - 1 + 2.", &op_dir).unwrap();

View File

@@ -555,10 +555,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
} }
ModuleExport::OpDecl(op_decl) => { ModuleExport::OpDecl(op_decl) => {
let op_dir_value_opt = op_dir.swap_remove(&( let op_dir_value_opt = op_dir
op_decl.name, .swap_remove(&(op_decl.name, op_decl.op_desc.get_spec().fixity()));
fixity(op_decl.op_desc.get_spec() as u32),
));
if let Some(op_desc) = op_dir_value_opt { if let Some(op_desc) = op_dir_value_opt {
retraction_info.push_record(op_retractor(*op_decl, op_desc)); retraction_info.push_record(op_retractor(*op_decl, op_desc));

View File

@@ -264,11 +264,11 @@ mod tests {
let mut wam = MachineState::new(); let mut wam = MachineState::new();
let mut op_dir = default_op_dir(); let mut op_dir = default_op_dir();
op_dir.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX as u8)); op_dir.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX));
op_dir.insert((atom!("-"), Fixity::In), OpDesc::build_with(500, YFX as u8)); op_dir.insert((atom!("-"), Fixity::In), OpDesc::build_with(500, YFX));
op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(500, YFX as u8)); op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(500, YFX));
op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX as u8)); op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX));
op_dir.insert((atom!("="), Fixity::In), OpDesc::build_with(700, XFX as u8)); op_dir.insert((atom!("="), Fixity::In), OpDesc::build_with(700, XFX));
{ {
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap(); parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
@@ -485,10 +485,10 @@ mod tests {
let mut wam = MachineState::new(); let mut wam = MachineState::new();
let mut op_dir = default_op_dir(); let mut op_dir = default_op_dir();
op_dir.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX as u8)); op_dir.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX));
op_dir.insert((atom!("-"), Fixity::In), OpDesc::build_with(500, YFX as u8)); op_dir.insert((atom!("-"), Fixity::In), OpDesc::build_with(500, YFX));
op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX as u8)); op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX));
op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX as u8)); op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX));
{ {
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap(); parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();

View File

@@ -11,18 +11,12 @@ use indexmap::IndexSet;
use std::cell::Cell; use std::cell::Cell;
use std::convert::TryFrom; use std::convert::TryFrom;
pub(crate) fn to_op_decl(prec: u16, spec: OpDeclSpec, name: Atom) -> OpDecl {
OpDecl::new(OpDesc::build_with(prec, spec), name)
}
pub(crate) fn to_op_decl(prec: u16, spec: Atom, name: Atom) -> Result<OpDecl, CompilationError> { pub(crate) fn to_op_decl_spec(spec: Atom) -> Result<OpDeclSpec, CompilationError> {
match spec { OpDeclSpec::try_from(spec).map_err(|_err| CompilationError::InconsistentEntry)
atom!("xfx") => Ok(OpDecl::new(OpDesc::build_with(prec, XFX as u8), name)),
atom!("xfy") => Ok(OpDecl::new(OpDesc::build_with(prec, XFY as u8), name)),
atom!("yfx") => Ok(OpDecl::new(OpDesc::build_with(prec, YFX as u8), name)),
atom!("fx") => Ok(OpDecl::new(OpDesc::build_with(prec, FX as u8), name)),
atom!("fy") => Ok(OpDecl::new(OpDesc::build_with(prec, FY as u8), name)),
atom!("xf") => Ok(OpDecl::new(OpDesc::build_with(prec, XF as u8), name)),
atom!("yf") => Ok(OpDecl::new(OpDesc::build_with(prec, YF as u8), name)),
_ => Err(CompilationError::InconsistentEntry),
}
} }
fn setup_op_decl(mut terms: Vec<Term>, atom_tbl: &AtomTable) -> Result<OpDecl, CompilationError> { fn setup_op_decl(mut terms: Vec<Term>, atom_tbl: &AtomTable) -> Result<OpDecl, CompilationError> {
@@ -38,6 +32,8 @@ fn setup_op_decl(mut terms: Vec<Term>, atom_tbl: &AtomTable) -> Result<OpDecl, C
_ => return Err(CompilationError::InconsistentEntry), _ => return Err(CompilationError::InconsistentEntry),
}; };
let spec = to_op_decl_spec(spec)?;
let prec = match terms.pop().unwrap() { let prec = match terms.pop().unwrap() {
Term::Literal(_, Literal::Fixnum(bi)) => match u16::try_from(bi.get_num()) { Term::Literal(_, Literal::Fixnum(bi)) => match u16::try_from(bi.get_num()) {
Ok(n) if n <= 1200 => n, Ok(n) if n <= 1200 => n,
@@ -46,7 +42,7 @@ fn setup_op_decl(mut terms: Vec<Term>, atom_tbl: &AtomTable) -> Result<OpDecl, C
_ => return Err(CompilationError::InconsistentEntry), _ => return Err(CompilationError::InconsistentEntry),
}; };
to_op_decl(prec, spec, name) Ok(to_op_decl(prec, spec, name))
} }
fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, CompilationError> { fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, CompilationError> {

View File

@@ -24,7 +24,6 @@ use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*; use crate::machine::machine_indices::*;
use crate::machine::machine_state::*; use crate::machine::machine_state::*;
use crate::machine::partial_string::*; use crate::machine::partial_string::*;
use crate::machine::preprocessor::to_op_decl;
use crate::machine::stack::*; use crate::machine::stack::*;
use crate::machine::streams::*; use crate::machine::streams::*;
use crate::machine::{get_structure_index, Machine, VERIFY_ATTR_INTERRUPT_LOC}; use crate::machine::{get_structure_index, Machine, VERIFY_ATTR_INTERRUPT_LOC};
@@ -102,6 +101,8 @@ use warp::hyper::{HeaderMap, Method};
use warp::{Buf, Filter}; use warp::{Buf, Filter};
use super::libraries; use super::libraries;
use super::preprocessor::to_op_decl;
use super::preprocessor::to_op_decl_spec;
#[cfg(feature = "repl")] #[cfg(feature = "repl")]
pub(crate) fn get_key() -> KeyEvent { pub(crate) fn get_key() -> KeyEvent {
@@ -3987,19 +3988,6 @@ impl Machine {
pub(crate) fn get_next_op_db_ref(&mut self) { pub(crate) fn get_next_op_db_ref(&mut self) {
let prec = self.deref_register(1); let prec = self.deref_register(1);
fn get_spec(op_spec: u8) -> Atom {
match op_spec as u32 {
XFX => atom!("xfx"),
XFY => atom!("xfy"),
YFX => atom!("yfx"),
FX => atom!("fx"),
FY => atom!("fy"),
XF => atom!("xf"),
YF => atom!("yf"),
_ => unreachable!(),
}
}
let h = self.machine_st.heap.len(); let h = self.machine_st.heap.len();
fn write_op_functors_to_heap( fn write_op_functors_to_heap(
@@ -4016,7 +4004,7 @@ impl Machine {
continue; continue;
} }
let spec_atom = get_spec(op_desc.get_spec()); let spec_atom = op_desc.get_spec().get_spec();
heap.extend(functor!( heap.extend(functor!(
atom!("op"), atom!("op"),
@@ -4038,17 +4026,14 @@ impl Machine {
let orig_op = self.deref_register(3); let orig_op = self.deref_register(3);
let spec_num = if spec.get_tag() == HeapCellValueTag::Atom { let spec_num = if spec.get_tag() == HeapCellValueTag::Atom {
(match cell_as_atom!(spec) { Some(
atom!("xfx") => XFX, OpDeclSpec::try_from(cell_as_atom!(spec))
atom!("xfy") => XFY, .ok()
atom!("yfx") => YFX, .filter(|spec| matches!(spec, XFX | XFY | YFX | FX | FY | XF))
atom!("fx") => FX, .expect("we should only get valid values != YF here"),
atom!("fy") => FY, )
atom!("xf") => XF,
_ => unreachable!(),
}) as u8
} else { } else {
0 None
}; };
let num_functors = if !orig_op.is_var() { let num_functors = if !orig_op.is_var() {
@@ -4111,7 +4096,7 @@ impl Machine {
} }
if (!orig_op.is_var() && atom_as_cell!(name) != orig_op) if (!orig_op.is_var() && atom_as_cell!(name) != orig_op)
|| (!spec.is_var() && other_spec != spec_num) || (!spec.is_var() && Some(other_spec) != spec_num)
{ {
return None; return None;
} }
@@ -5051,8 +5036,9 @@ impl Machine {
} }
); );
let result = to_op_decl(priority, specifier, op) let result = to_op_decl_spec(specifier)
.map_err(SessionError::from) .map_err(SessionError::from)
.map(|specifier| to_op_decl(priority, specifier, op))
.and_then(|mut op_decl| { .and_then(|mut op_decl| {
if op_decl.op_desc.get_prec() == 0 { if op_decl.op_desc.get_prec() == 0 {
op_decl.remove(&mut self.indices.op_dir); op_decl.remove(&mut self.indices.op_dir);

View File

@@ -26,13 +26,112 @@ pub type Specifier = u32;
pub const MAX_ARITY: usize = 1023; pub const MAX_ARITY: usize = 1023;
pub const XFX: u32 = 0x0001; #[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub const XFY: u32 = 0x0002; pub enum OpDeclSpec {
pub const YFX: u32 = 0x0004; XFX = 0x0001,
pub const XF: u32 = 0x0010; XFY = 0x0002,
pub const YF: u32 = 0x0020; YFX = 0x0004,
pub const FX: u32 = 0x0040; XF = 0x0010,
pub const FY: u32 = 0x0080; YF = 0x0020,
FX = 0x0040,
FY = 0x0080,
}
pub use OpDeclSpec::*;
impl OpDeclSpec {
pub const fn value(self) -> u32 {
self as u32
}
pub fn get_spec(self) -> Atom {
match self {
XFX => atom!("xfx"),
XFY => atom!("xfy"),
YFX => atom!("yfx"),
FX => atom!("fx"),
FY => atom!("fy"),
XF => atom!("xf"),
YF => atom!("yf"),
}
}
pub const fn is_prefix(self) -> bool {
matches!(self, Self::FX | Self::FY)
}
pub const fn is_postfix(self) -> bool {
matches!(self, Self::XF | Self::YF)
}
pub const fn is_infix(self) -> bool {
matches!(self, Self::XFX | Self::XFY | Self::YFX)
}
pub const fn is_strict_left(self) -> bool {
matches!(self, Self::XFX | Self::XFY | Self::XF)
}
pub const fn is_strict_right(self) -> bool {
matches!(self, Self::XFX | Self::YFX | Self::FX)
}
#[inline(always)]
pub(crate) fn fixity(self) -> Fixity {
match self {
XFY | XFX | YFX => Fixity::In,
XF | YF => Fixity::Post,
FX | FY => Fixity::Pre,
}
}
}
impl From<OpDeclSpec> for u8 {
fn from(value: OpDeclSpec) -> Self {
value as u8
}
}
impl From<OpDeclSpec> for u32 {
fn from(value: OpDeclSpec) -> Self {
value as u32
}
}
impl TryFrom<u8> for OpDeclSpec {
type Error = ();
fn try_from(value: u8) -> Result<Self, Self::Error> {
Ok(match value {
0x0001 => XFX,
0x0002 => XFY,
0x0004 => YFX,
0x0010 => XF,
0x0020 => YF,
0x0040 => FX,
0x0080 => FY,
_ => return Err(()),
})
}
}
impl TryFrom<Atom> for OpDeclSpec {
type Error = ();
fn try_from(value: Atom) -> Result<Self, Self::Error> {
Ok(match value {
atom!("xfx") => Self::XFX,
atom!("xfy") => Self::XFY,
atom!("yfx") => Self::YFX,
atom!("fx") => Self::FX,
atom!("fy") => Self::FY,
atom!("xf") => Self::XF,
atom!("yf") => Self::YF,
_ => return Err(()),
})
}
}
pub const DELIMITER: u32 = 0x0100; pub const DELIMITER: u32 = 0x0100;
pub const TERM: u32 = 0x1000; pub const TERM: u32 = 0x1000;
pub const LTERM: u32 = 0x3000; pub const LTERM: u32 = 0x3000;
@@ -64,13 +163,13 @@ macro_rules! is_lterm {
macro_rules! is_op { macro_rules! is_op {
($x:expr) => { ($x:expr) => {
$x as u32 $x as u32
& ($crate::parser::ast::XF & ($crate::parser::ast::XF as u32
| $crate::parser::ast::YF | $crate::parser::ast::YF as u32
| $crate::parser::ast::FX | $crate::parser::ast::FX as u32
| $crate::parser::ast::FY | $crate::parser::ast::FY as u32
| $crate::parser::ast::XFX | $crate::parser::ast::XFX as u32
| $crate::parser::ast::XFY | $crate::parser::ast::XFY as u32
| $crate::parser::ast::YFX) | $crate::parser::ast::YFX as u32)
!= 0 != 0
}; };
} }
@@ -84,14 +183,14 @@ macro_rules! is_negate {
#[macro_export] #[macro_export]
macro_rules! is_prefix { macro_rules! is_prefix {
($x:expr) => { ($x:expr) => {
$x as u32 & ($crate::parser::ast::FX | $crate::parser::ast::FY) != 0 $x as u32 & ($crate::parser::ast::FX as u32 | $crate::parser::ast::FY as u32) != 0
}; };
} }
#[macro_export] #[macro_export]
macro_rules! is_postfix { macro_rules! is_postfix {
($x:expr) => { ($x:expr) => {
$x as u32 & ($crate::parser::ast::XF | $crate::parser::ast::YF) != 0 $x as u32 & ($crate::parser::ast::XF as u32 | $crate::parser::ast::YF as u32) != 0
}; };
} }
@@ -99,7 +198,9 @@ macro_rules! is_postfix {
macro_rules! is_infix { macro_rules! is_infix {
($x:expr) => { ($x:expr) => {
($x as u32 ($x as u32
& ($crate::parser::ast::XFX | $crate::parser::ast::XFY | $crate::parser::ast::YFX)) & ($crate::parser::ast::XFX as u32
| $crate::parser::ast::XFY as u32
| $crate::parser::ast::YFX as u32))
!= 0 != 0
}; };
} }
@@ -107,49 +208,48 @@ macro_rules! is_infix {
#[macro_export] #[macro_export]
macro_rules! is_xfx { macro_rules! is_xfx {
($x:expr) => { ($x:expr) => {
($x as u32 & $crate::parser::ast::XFX) != 0 ($x as u32 & $crate::parser::ast::XFX as u32) != 0
}; };
} }
#[macro_export] #[macro_export]
macro_rules! is_xfy { macro_rules! is_xfy {
($x:expr) => { ($x:expr) => {
($x as u32 & $crate::parser::ast::XFY) != 0 ($x as u32 & $crate::parser::ast::XFY as u32) != 0
}; };
} }
#[macro_export] #[macro_export]
macro_rules! is_yfx { macro_rules! is_yfx {
($x:expr) => { ($x:expr) => {
($x as u32 & $crate::parser::ast::YFX) != 0 ($x as u32 & $crate::parser::ast::YFX as u32) != 0
}; };
} }
#[macro_export] #[macro_export]
macro_rules! is_yf { macro_rules! is_yf {
($x:expr) => { ($x:expr) => {
($x as u32 & $crate::parser::ast::YF) != 0 ($x as u32 & $crate::parser::ast::YF as u32) != 0
}; };
} }
#[macro_export] #[macro_export]
macro_rules! is_xf { macro_rules! is_xf {
($x:expr) => { ($x:expr) => {
($x as u32 & $crate::parser::ast::XF) != 0 ($x as u32 & $crate::parser::ast::XF as u32) != 0
}; };
} }
#[macro_export] #[macro_export]
macro_rules! is_fx { macro_rules! is_fx {
($x:expr) => { ($x:expr) => {
($x as u32 & $crate::parser::ast::FX) != 0 ($x as u32 & $crate::parser::ast::FX as u32) != 0
}; };
} }
#[macro_export] #[macro_export]
macro_rules! is_fy { macro_rules! is_fy {
($x:expr) => { ($x:expr) => {
($x as u32 & $crate::parser::ast::FY) != 0 ($x as u32 & $crate::parser::ast::FY as u32) != 0
}; };
} }
@@ -264,18 +364,18 @@ pub struct OpDesc {
impl OpDesc { impl OpDesc {
#[inline] #[inline]
pub fn build_with(prec: u16, spec: u8) -> Self { pub fn build_with(prec: u16, spec: OpDeclSpec) -> Self {
OpDesc::new().with_spec(spec).with_prec(prec) OpDesc::new().with_spec(spec as u8).with_prec(prec)
} }
#[inline] #[inline]
pub fn get(self) -> (u16, u8) { pub fn get(self) -> (u16, OpDeclSpec) {
(self.prec(), self.spec()) (self.prec(), self.get_spec())
} }
pub fn set(&mut self, prec: u16, spec: u8) { pub fn set(&mut self, prec: u16, spec: OpDeclSpec) {
self.set_prec(prec); self.set_prec(prec);
self.set_spec(spec); self.set_spec(spec as u8);
} }
#[inline] #[inline]
@@ -284,13 +384,13 @@ impl OpDesc {
} }
#[inline] #[inline]
pub fn get_spec(self) -> u8 { pub fn get_spec(self) -> OpDeclSpec {
self.spec() OpDeclSpec::try_from(self.spec()).expect("OpDecl always contains a valud OpDeclSpec")
} }
#[inline] #[inline]
pub fn arity(self) -> usize { pub fn arity(self) -> usize {
if self.spec() as u32 & (XFX | XFY | YFX) == 0 { if !self.get_spec().is_infix() {
1 1
} else { } else {
2 2
@@ -354,22 +454,10 @@ impl Unknown {
pub fn default_op_dir() -> OpDir { pub fn default_op_dir() -> OpDir {
let mut op_dir = OpDir::with_hasher(FxBuildHasher::default()); let mut op_dir = OpDir::with_hasher(FxBuildHasher::default());
op_dir.insert( op_dir.insert((atom!(":-"), Fixity::In), OpDesc::build_with(1200, XFX));
(atom!(":-"), Fixity::In), op_dir.insert((atom!(":-"), Fixity::Pre), OpDesc::build_with(1200, FX));
OpDesc::build_with(1200, XFX as u8), op_dir.insert((atom!("?-"), Fixity::Pre), OpDesc::build_with(1200, FX));
); op_dir.insert((atom!(","), Fixity::In), OpDesc::build_with(1000, XFY));
op_dir.insert(
(atom!(":-"), Fixity::Pre),
OpDesc::build_with(1200, FX as u8),
);
op_dir.insert(
(atom!("?-"), Fixity::Pre),
OpDesc::build_with(1200, FX as u8),
);
op_dir.insert(
(atom!(","), Fixity::In),
OpDesc::build_with(1000, XFY as u8),
);
op_dir op_dir
} }

View File

@@ -385,10 +385,10 @@ impl<'a, R: CharRead> Parser<'a, R> {
} }
} }
fn push_unary_op(&mut self, td: TokenDesc, spec: Specifier, assoc: u32) { fn push_unary_op(&mut self, td: TokenDesc, spec: Specifier, assoc: OpDeclSpec) {
if let Some(mut arg1) = self.terms.pop() { if let Some(mut arg1) = self.terms.pop() {
if let Some(mut name) = self.terms.pop() { if let Some(mut name) = self.terms.pop() {
if is_postfix!(assoc) { if assoc.is_postfix() {
mem::swap(&mut arg1, &mut name); mem::swap(&mut arg1, &mut name);
} }
@@ -912,7 +912,11 @@ impl<'a, R: CharRead> Parser<'a, R> {
// can't be prefix, so either inf == 0 // can't be prefix, so either inf == 0
// or post == 0. // or post == 0.
self.reduce_op(inf + post); self.reduce_op(inf + post);
self.promote_atom_op(name, inf + post, spec & (XFX | XFY | YFX | YF | XF)); self.promote_atom_op(
name,
inf + post,
spec & (XFX as u32 | XFY as u32 | YFX as u32 | YF as u32 | XF as u32),
);
} }
_ => { _ => {
self.reduce_op(inf + post); self.reduce_op(inf + post);
@@ -923,14 +927,22 @@ impl<'a, R: CharRead> Parser<'a, R> {
self.promote_atom_op( self.promote_atom_op(
name, name,
inf + post, inf + post,
spec & (XFX | XFY | YFX | XF | YF), spec & (XFX as u32
| XFY as u32
| YFX as u32
| XF as u32
| YF as u32),
); );
return Ok(true); return Ok(true);
} }
} }
self.promote_atom_op(name, pre, spec & (FX | FY | NEGATIVE_SIGN)); self.promote_atom_op(
name,
pre,
spec & (FX as u32 | FY as u32 | NEGATIVE_SIGN),
);
} }
} }
} else { } else {
@@ -1066,7 +1078,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
} }
Token::Comma => { Token::Comma => {
self.reduce_op(1000); self.reduce_op(1000);
self.shift(Token::Comma, 1000, XFY); self.shift(Token::Comma, 1000, XFY as u32);
} }
Token::End => match self.stack.last().map(|t| t.tt) { Token::End => match self.stack.last().map(|t| t.tt) {
Some(TokenType::Open) Some(TokenType::Open)