Skip to content

Commit

Permalink
Table driven operator precedence (#1075)
Browse files Browse the repository at this point in the history
Prefer operator precedence from mathics-scanner tables.

---------

Co-authored-by: Juan Mauricio Matera <[email protected]>
  • Loading branch information
rocky and mmatera authored Aug 29, 2024
1 parent ef8a0ce commit a3478d2
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 19 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/osx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ jobs:
- name: Install Mathics3 with full Python dependencies
run: |
# We can comment out after next Mathics-Scanner release
# python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner[full]
python -m pip install Mathics-Scanner
python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner[full]
# python -m pip install Mathics-Scanner[full]
make develop-full
- name: Test Mathics3
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ubuntu-cython.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ jobs:
sudo apt-get update -qq && sudo apt-get install -qq liblapack-dev llvm-dev tesseract-ocr
python -m pip install --upgrade pip
# We can comment out after next Mathics-Scanner release
# python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner[full]
python -m pip install Mathics-Scanner
python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner[full]
# python -m pip install Mathics-Scanner[full]
- name: Install Mathics with full dependencies
run: |
make develop-full-cython
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ jobs:
run: |
python -m pip install --upgrade pip
# We can comment out after next Mathics-Scanner release
# python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner[full]
python -m pip install Mathics-Scanner
python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner[full]
# python -m pip install Mathics-Scanner[full]
make develop-full
- name: Test Mathics
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ jobs:
- name: Install Mathics3 with Python dependencies
run: |
# We can comment out after next Mathics-Scanner release
# python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner[full]
python -m pip install Mathics-Scanner
python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner[full]
# python -m pip install Mathics-Scanner[full]
make develop-full
- name: Test Mathics3
# Limit pip install to a basic install *without* full dependencies.
Expand Down
11 changes: 6 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,17 @@ build:
# because pip install doesn't handle
# INSTALL_REQUIRES properly
#: Set up to run from the source tree
develop: mathics/data/op-tables.json
develop: mathics/data/op-tables.json mathics/data/operators.json
$(PIP) install -e .[dev]

# See note above on ./setup.py
#: Set up to run from the source tree with full dependencies
develop-full: mathics/data/op-tables.json
develop-full: mathics/data/op-tables.json mathics/data/operators.json
$(PIP) install -e .[dev,full]

# See note above on ./setup.py
#: Set up to run from the source tree with full dependencies and Cython
develop-full-cython: mathics/data/op-tables.json
develop-full-cython: mathics/data/op-tables.json mathics/data/operators.json
$(PIP) install -e .[dev,full,cython]


Expand Down Expand Up @@ -141,10 +141,11 @@ doctest:
latexdoc texdoc doc:
(cd mathics/doc/latex && $(MAKE) doc)

#: Build JSON ASCII to unicode opcode tables
mathics/data/op-tables.json:
#: Build JSON ASCII to unicode opcode table and operator table
mathics/data/op-tables.json mathics/data/operators.json:
$(BASH) ./admin-tools/make-op-tables.sh


#: Remove ChangeLog
rmChangeLog:
$(RM) ChangeLog || true
Expand Down
3 changes: 2 additions & 1 deletion admin-tools/make-op-tables.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ mydir=$(dirname $bs)
PYTHON=${PYTHON:-python}

cd $mydir/../mathics/data
mathics-generate-json-table \
mathics3-generate-json-table \
--field=ascii-operator-to-symbol \
--field=ascii-operator-to-unicode \
--field=ascii-operator-to-wl-unicode \
--field=operator-to-ascii \
--field=operator-to-unicode \
-o op-tables.json
mathics3-generate-operator-json-table -o operator-tables.json
25 changes: 21 additions & 4 deletions mathics/core/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
"""

import importlib
import os.path as osp
import re
from functools import lru_cache, total_ordering
from itertools import chain
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union, cast

import mpmath
import pkg_resources
import sympy

from mathics.core.atoms import (
Expand Down Expand Up @@ -67,6 +69,21 @@
from mathics.eval.numerify import numerify
from mathics.eval.scoping import dynamic_scoping

try:
import ujson
except ImportError:
import json as ujson

ROOT_DIR = pkg_resources.resource_filename("mathics", "")

# Load the conversion tables from disk
characters_path = osp.join(ROOT_DIR, "data", "operator-tables.json")
assert osp.exists(
characters_path
), f"Operator precedence tables are missing; expected to be in {characters_path}"
with open(characters_path, "r") as f:
operator_data = ujson.load(f)


class Builtin:
"""
Expand Down Expand Up @@ -982,16 +999,16 @@ def __init__(self, format_function, *args, **kwargs):
super().__init__(*args, **kwargs)
name = self.get_name()
if self.needs_verbatim:
name = "Verbatim[%s]" % name
name = f"Verbatim[{name}"
if self.default_formats:
op_pattern = "%s[item_]" % name
op_pattern = f"{name}[item_]"
if op_pattern not in self.formats:
operator = self.get_operator_display()
if operator is not None:
form = '%s[{HoldForm[item]},"%s",%d]' % (
format_function,
operator,
self.precedence,
operator_data["operator-precedence"].get(name, self.precedence),
)
self.formats[op_pattern] = form

Expand Down Expand Up @@ -1032,7 +1049,7 @@ def __init__(self, *args, **kwargs):
formatted = "MakeBoxes[Infix[{%s}, %s, %d,%s], form]" % (
replace_items,
operator,
self.precedence,
operator_data["operator-precedence"].get(name, self.precedence),
self.grouping,
)
default_rules = {
Expand Down
1 change: 1 addition & 0 deletions mathics/data/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/doc_latex_data.pcl
/doctest_latex_data.pcl
/op-tables.json
/operator-tables.json
6 changes: 5 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,18 @@ class build_py(setuptools_build_py):
def run(self):
if not os.path.exists("mathics/data/op-tables.json"):
os.system(
"mathics-generate-json-table"
"mathics3-generate-json-table"
" --field=ascii-operator-to-symbol"
" --field=ascii-operator-to-unicode"
" --field=ascii-operator-to-wl-unicode"
" --field=operator-to-ascii"
" --field=operator-to-unicode"
" -o mathics/data/op-tables.json"
)
if not os.path.exists("mathics/data/operator-tables.json"):
os.system(
"mathics3-generate-operator-json-table" " -o operator-tables.json"
)
self.distribution.package_data["mathics"].append("data/op-tables.json")
setuptools_build_py.run(self)

Expand Down

0 comments on commit a3478d2

Please sign in to comment.