]> Repositorios git - scryer-prolog.git/commitdiff
use an enum for OpDesc spec
authorBennet Bleßmann <[email protected]>
Wed, 31 Jul 2024 21:48:27 +0000 (23:48 +0200)
committerBennet Bleßmann <[email protected]>
Mon, 5 Aug 2024 19:25:36 +0000 (21:25 +0200)
src/forms.rs
src/heap_print.rs
src/machine/arithmetic_ops.rs
src/machine/load_state.rs
src/machine/mock_wam.rs
src/machine/preprocessor.rs
src/machine/system_calls.rs
src/parser/ast.rs
src/parser/parser.rs

index d18d41f1539a171e8885c1b8fc7fefd8ed15ff40..2425b06268b2640324db08caa7e46c89148e6b8a 100644 (file)
@@ -24,8 +24,6 @@ use std::fmt;
 use std::ops::{AddAssign, Deref, DerefMut};
 use std::path::PathBuf;
 
-use crate::{is_infix, is_postfix};
-
 pub type PredicateKey = (Atom, usize); // name, arity.
 
 /*
@@ -403,16 +401,6 @@ pub struct OpDecl {
     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 {
     #[inline]
     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> {
-        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) {
             let (old_prec, old_spec) = cell.get();
@@ -447,7 +435,7 @@ impl OpDecl {
     ) -> Result<(), SessionError> {
         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 desc.post > 0 {
                     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 desc.inf > 0 {
                     return Err(SessionError::OpIsInfixAndPostFix(name));
index 4982b2dea4b95e364726ac70b8787000928f6755..a25406172f2fdbe76329e1721e57e159435097b0 100644 (file)
@@ -6,8 +6,8 @@ use crate::parser::dashu::integer::Sign;
 use crate::parser::dashu::{ibig, Integer, Rational};
 use crate::{
     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,
-    sign_char, single_quote_char, small_letter_char, solo_char, variable_indicator_char,
+    semicolon_char, sign_char, single_quote_char, small_letter_char, solo_char,
+    variable_indicator_char,
 };
 
 use crate::forms::*;
@@ -51,7 +51,7 @@ impl DirectedOp {
     fn is_prefix(&self) -> bool {
         match self {
             &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 {
         match self {
             &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() == "-" {
                 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;
                 }
             }
 
-            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 && is_strict_right)
         }
         DirectedOp::Right(_, cell) => {
             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
                 || (child_desc.get_prec() == priority && is_strict_left)
             {
                 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
             } else {
@@ -121,7 +121,7 @@ impl<'a, ElideLists> StackfulPreOrderHeapIter<'a, ElideLists> {
             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 {
             let cell = self.read_cell(h);
@@ -131,7 +131,7 @@ impl<'a, ElideLists> StackfulPreOrderHeapIter<'a, ElideLists> {
                     read_heap_cell!(self.heap[s],
                         (HeapCellValueTag::Atom, (name, _arity)) => {
                             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) {
                                         return false;
                                     } 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) {
-        if is_postfix!(spec.get_spec()) {
+        if spec.get_spec().is_postfix() {
             if self.max_depth_exhausted(max_depth) {
                 self.iter.pop_stack();
                 self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
@@ -610,7 +610,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                     right_directed_op,
                 ));
             }
-        } else if is_prefix!(spec.get_spec()) {
+        } else if spec.get_spec().is_prefix() {
             if self.max_depth_exhausted(max_depth) {
                 self.iter.pop_stack();
                 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!("...")));
             } 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);
 
                     self.state_stack
@@ -791,7 +791,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
         let dot_atom = atom!(".");
 
         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);
                 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)>>> {
         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);
                 return None;
             }
@@ -1775,7 +1775,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                 TokenOrRedirect::Op(atom, op) => {
                     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)));
                     }
                 }
@@ -2120,9 +2120,9 @@ mod tests {
         all_cells_unmarked(&wam.machine_st.heap);
 
         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
-            .insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX as u8));
+            .insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX));
 
         assert_eq!(
             &wam.parse_and_print_term("[a|[] + b].").unwrap(),
@@ -2139,10 +2139,10 @@ mod tests {
         all_cells_unmarked(&wam.machine_st.heap);
 
         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
-            .insert((atom!("yf"), Fixity::Post), OpDesc::build_with(9, YF as u8));
+            .insert((atom!("yf"), Fixity::Post), OpDesc::build_with(9, YF));
 
         assert_eq!(
             &wam.parse_and_print_term("(fy (fy 1)yf)yf.").unwrap(),
index 2616e447a1ea610ef4610f042ef653ea914793e4..a1e715e319d3ebcbf49b3d73eafb5140ad290be0 100644 (file)
@@ -1419,11 +1419,11 @@ mod tests {
         let mut wam = MachineState::new();
         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 as u8));
-        op_dir.insert((atom!("-"), Fixity::Pre), OpDesc::build_with(200, FY as u8));
-        op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX as u8));
-        op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, 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));
+        op_dir.insert((atom!("-"), Fixity::Pre), OpDesc::build_with(200, FY));
+        op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX));
+        op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX));
 
         let term_write_result =
             parse_and_write_parsed_term_to_heap(&mut wam, "3 + 4 - 1 + 2.", &op_dir).unwrap();
index 89b82f1cf6c28fb834ad16d1a7915e3db63e76de..86c1b68124c65592ae3714a0ba4cf2222a947537 100644 (file)
@@ -555,10 +555,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
                         }
                     }
                     ModuleExport::OpDecl(op_decl) => {
-                        let op_dir_value_opt = op_dir.swap_remove(&(
-                            op_decl.name,
-                            fixity(op_decl.op_desc.get_spec() as u32),
-                        ));
+                        let op_dir_value_opt = op_dir
+                            .swap_remove(&(op_decl.name, op_decl.op_desc.get_spec().fixity()));
 
                         if let Some(op_desc) = op_dir_value_opt {
                             retraction_info.push_record(op_retractor(*op_decl, op_desc));
index 0da42e08d55ad1542f491fbc2eab858f3aea145c..0a6f77239d522ff36d6121ce2cc3fe78a7ba34d9 100644 (file)
@@ -264,11 +264,11 @@ mod tests {
         let mut wam = MachineState::new();
         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 as u8));
-        op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(500, YFX as u8));
-        op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX as u8));
-        op_dir.insert((atom!("="), Fixity::In), OpDesc::build_with(700, XFX as u8));
+        op_dir.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX));
+        op_dir.insert((atom!("-"), Fixity::In), OpDesc::build_with(500, YFX));
+        op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(500, YFX));
+        op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, YFX));
+        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();
@@ -485,10 +485,10 @@ mod tests {
         let mut wam = MachineState::new();
         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 as u8));
-        op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX as u8));
-        op_dir.insert((atom!("/"), Fixity::In), OpDesc::build_with(400, 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));
+        op_dir.insert((atom!("*"), Fixity::In), OpDesc::build_with(400, YFX));
+        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();
index b6e82ab707c5d89ff8e16fc37f9ed2c11cde4d2e..ded794dd624dc3a7de40153be0d23575ff8bb592 100644 (file)
@@ -11,18 +11,12 @@ use indexmap::IndexSet;
 
 use std::cell::Cell;
 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> {
-    match spec {
-        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),
-    }
+pub(crate) fn to_op_decl_spec(spec: Atom) -> Result<OpDeclSpec, CompilationError> {
+    OpDeclSpec::try_from(spec).map_err(|_err| CompilationError::InconsistentEntry)
 }
 
 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),
     };
 
+    let spec = to_op_decl_spec(spec)?;
+
     let prec = match terms.pop().unwrap() {
         Term::Literal(_, Literal::Fixnum(bi)) => match u16::try_from(bi.get_num()) {
             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),
     };
 
-    to_op_decl(prec, spec, name)
+    Ok(to_op_decl(prec, spec, name))
 }
 
 fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, CompilationError> {
index 9cbdca3f145f49dce7b9c7b32b775b9293917d0b..ce5803756dfc8959b9c3b63f5d595b0b449f828c 100644 (file)
@@ -24,7 +24,6 @@ use crate::machine::machine_errors::*;
 use crate::machine::machine_indices::*;
 use crate::machine::machine_state::*;
 use crate::machine::partial_string::*;
-use crate::machine::preprocessor::to_op_decl;
 use crate::machine::stack::*;
 use crate::machine::streams::*;
 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 super::libraries;
+use super::preprocessor::to_op_decl;
+use super::preprocessor::to_op_decl_spec;
 
 #[cfg(feature = "repl")]
 pub(crate) fn get_key() -> KeyEvent {
@@ -3987,19 +3988,6 @@ impl Machine {
     pub(crate) fn get_next_op_db_ref(&mut self) {
         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();
 
         fn write_op_functors_to_heap(
@@ -4016,7 +4004,7 @@ impl Machine {
                     continue;
                 }
 
-                let spec_atom = get_spec(op_desc.get_spec());
+                let spec_atom = op_desc.get_spec().get_spec();
 
                 heap.extend(functor!(
                     atom!("op"),
@@ -4038,17 +4026,14 @@ impl Machine {
             let orig_op = self.deref_register(3);
 
             let spec_num = if spec.get_tag() == HeapCellValueTag::Atom {
-                (match cell_as_atom!(spec) {
-                    atom!("xfx") => XFX,
-                    atom!("xfy") => XFY,
-                    atom!("yfx") => YFX,
-                    atom!("fx") => FX,
-                    atom!("fy") => FY,
-                    atom!("xf") => XF,
-                    _ => unreachable!(),
-                }) as u8
+                Some(
+                    OpDeclSpec::try_from(cell_as_atom!(spec))
+                        .ok()
+                        .filter(|spec| matches!(spec, XFX | XFY | YFX | FX | FY | XF))
+                        .expect("we should only get valid values != YF here"),
+                )
             } else {
-                0
+                None
             };
 
             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)
-                        || (!spec.is_var() && other_spec != spec_num)
+                        || (!spec.is_var() && Some(other_spec) != spec_num)
                     {
                         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(|specifier| to_op_decl(priority, specifier, op))
             .and_then(|mut op_decl| {
                 if op_decl.op_desc.get_prec() == 0 {
                     op_decl.remove(&mut self.indices.op_dir);
index 0e98aca846cffc7eb84545c17b87570814fb6981..ec699c21136fde4a52dd443541b0e1907414d9c0 100644 (file)
@@ -26,13 +26,112 @@ pub type Specifier = u32;
 
 pub const MAX_ARITY: usize = 1023;
 
-pub const XFX: u32 = 0x0001;
-pub const XFY: u32 = 0x0002;
-pub const YFX: u32 = 0x0004;
-pub const XF: u32 = 0x0010;
-pub const YF: u32 = 0x0020;
-pub const FX: u32 = 0x0040;
-pub const FY: u32 = 0x0080;
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub enum OpDeclSpec {
+    XFX = 0x0001,
+    XFY = 0x0002,
+    YFX = 0x0004,
+    XF = 0x0010,
+    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 TERM: u32 = 0x1000;
 pub const LTERM: u32 = 0x3000;
@@ -64,13 +163,13 @@ macro_rules! is_lterm {
 macro_rules! is_op {
     ($x:expr) => {
         $x as u32
-            & ($crate::parser::ast::XF
-                | $crate::parser::ast::YF
-                | $crate::parser::ast::FX
-                | $crate::parser::ast::FY
-                | $crate::parser::ast::XFX
-                | $crate::parser::ast::XFY
-                | $crate::parser::ast::YFX)
+            & ($crate::parser::ast::XF as u32
+                | $crate::parser::ast::YF as u32
+                | $crate::parser::ast::FX as u32
+                | $crate::parser::ast::FY as u32
+                | $crate::parser::ast::XFX as u32
+                | $crate::parser::ast::XFY as u32
+                | $crate::parser::ast::YFX as u32)
             != 0
     };
 }
@@ -84,14 +183,14 @@ macro_rules! is_negate {
 #[macro_export]
 macro_rules! is_prefix {
     ($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_rules! is_postfix {
     ($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 {
     ($x:expr) => {
         ($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
     };
 }
@@ -107,49 +208,48 @@ macro_rules! is_infix {
 #[macro_export]
 macro_rules! is_xfx {
     ($x:expr) => {
-        ($x as u32 & $crate::parser::ast::XFX) != 0
+        ($x as u32 & $crate::parser::ast::XFX as u32) != 0
     };
 }
 
 #[macro_export]
 macro_rules! is_xfy {
     ($x:expr) => {
-        ($x as u32 & $crate::parser::ast::XFY) != 0
+        ($x as u32 & $crate::parser::ast::XFY as u32) != 0
     };
 }
 
 #[macro_export]
 macro_rules! is_yfx {
     ($x:expr) => {
-        ($x as u32 & $crate::parser::ast::YFX) != 0
+        ($x as u32 & $crate::parser::ast::YFX as u32) != 0
     };
 }
-
 #[macro_export]
 macro_rules! is_yf {
     ($x:expr) => {
-        ($x as u32 & $crate::parser::ast::YF) != 0
+        ($x as u32 & $crate::parser::ast::YF as u32) != 0
     };
 }
 
 #[macro_export]
 macro_rules! is_xf {
     ($x:expr) => {
-        ($x as u32 & $crate::parser::ast::XF) != 0
+        ($x as u32 & $crate::parser::ast::XF as u32) != 0
     };
 }
 
 #[macro_export]
 macro_rules! is_fx {
     ($x:expr) => {
-        ($x as u32 & $crate::parser::ast::FX) != 0
+        ($x as u32 & $crate::parser::ast::FX as u32) != 0
     };
 }
 
 #[macro_export]
 macro_rules! is_fy {
     ($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 {
     #[inline]
-    pub fn build_with(prec: u16, spec: u8) -> Self {
-        OpDesc::new().with_spec(spec).with_prec(prec)
+    pub fn build_with(prec: u16, spec: OpDeclSpec) -> Self {
+        OpDesc::new().with_spec(spec as u8).with_prec(prec)
     }
 
     #[inline]
-    pub fn get(self) -> (u16, u8) {
-        (self.prec(), self.spec())
+    pub fn get(self) -> (u16, OpDeclSpec) {
+        (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_spec(spec);
+        self.set_spec(spec as u8);
     }
 
     #[inline]
@@ -284,13 +384,13 @@ impl OpDesc {
     }
 
     #[inline]
-    pub fn get_spec(self) -> u8 {
-        self.spec()
+    pub fn get_spec(self) -> OpDeclSpec {
+        OpDeclSpec::try_from(self.spec()).expect("OpDecl always contains a valud OpDeclSpec")
     }
 
     #[inline]
     pub fn arity(self) -> usize {
-        if self.spec() as u32 & (XFX | XFY | YFX) == 0 {
+        if !self.get_spec().is_infix() {
             1
         } else {
             2
@@ -354,22 +454,10 @@ impl Unknown {
 pub fn default_op_dir() -> OpDir {
     let mut op_dir = OpDir::with_hasher(FxBuildHasher::default());
 
-    op_dir.insert(
-        (atom!(":-"), Fixity::In),
-        OpDesc::build_with(1200, XFX as u8),
-    );
-    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.insert((atom!(":-"), Fixity::In), OpDesc::build_with(1200, XFX));
+    op_dir.insert((atom!(":-"), Fixity::Pre), OpDesc::build_with(1200, FX));
+    op_dir.insert((atom!("?-"), Fixity::Pre), OpDesc::build_with(1200, FX));
+    op_dir.insert((atom!(","), Fixity::In), OpDesc::build_with(1000, XFY));
 
     op_dir
 }
index c4d509b4e80557ba846cbef2f014c5ec0df2a3ea..e89ac5a1afe9e326cfe34c0867a913342b50f50a 100644 (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 name) = self.terms.pop() {
-                if is_postfix!(assoc) {
+                if assoc.is_postfix() {
                     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
                         // or post == 0.
                         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);
@@ -923,14 +927,22 @@ impl<'a, R: CharRead> Parser<'a, R> {
                                 self.promote_atom_op(
                                     name,
                                     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);
                             }
                         }
 
-                        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 {
@@ -1066,7 +1078,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
             }
             Token::Comma => {
                 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) {
                 Some(TokenType::Open)