Skip to content

Commit

Permalink
split no-meaning operators, add infix precedence
Browse files Browse the repository at this point in the history
Operators without Built-in Meanings is now a "Guide section" with
parts for postfix, prefix and infix operators and operators that
require additional Mathics3 module loading.

The precedence for infix operators is not set properly.
  • Loading branch information
rocky committed Nov 26, 2024
1 parent 405b4df commit 7fa3fa1
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 134 deletions.
134 changes: 0 additions & 134 deletions mathics/builtin/no_meaning.py

This file was deleted.

10 changes: 10 additions & 0 deletions mathics/builtin/no_meaning/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
"""
Operators without Built-in Meanings
Not all operators recognized by the Mathics3 are associated with functions that have built‐in meanings.
You can use these operators as a way to build up your own notation within Mathics3.
"""

# This tells documentation how to sort this module
sort_order = "mathics.builtin.operators-without-built-in-meanings"
54 changes: 54 additions & 0 deletions mathics/builtin/no_meaning/infix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""
Infix Operators without Built-in Meanings
"""

from sys import modules

import mathics.core.parser.operators
from mathics.core.builtin import NoMeaningInfixOperator
from mathics.core.parser.operators import OPERATOR_DATA


def add_no_meaning_builtins(
affix: str, format_function_name: str, operator_base_class, builtin_module
):
operator_key = f"no-meaning-{affix}-operators"
for operator_name, operator_tuple in OPERATOR_DATA[operator_key].items():
# Create the Mathics3 Builtin class...
operator_string = operator_tuple[0]
generated_operator_class = type(
operator_name,
(operator_base_class,),
{
"__doc__": operator_base_class.__doc_pattern__.format(
operator_name=operator_name, operator_string=operator_string
),
"operator": operator_string,
"summary_text": f"""{operator_name} {affix} operator "{operator_string}" (no pre-set meaning attached)""",
"formats": {
(
("InputForm", "OutputForm", "StandardForm"),
f"{operator_name}[args__]",
): (('%s[{args}, "%s"]' % (format_function_name, operator_string)))
},
},
)

# FIXME: Right now, precedence for infix operators is listed in
# JSON only for infix operators. Extend table generation in the same way
# for prefix and postfix, and then extend the code below to
# assign operator precedences for prefix and postfix operators.
if affix == "infix":
mathics.core.parser.operators.flat_binary_ops[
operator_name
] = operator_tuple[1]

# Put the newly-created Builtin class inside this module.
setattr(builtin_module, operator_name, generated_operator_class)


def add_no_meaning_infix_operators():
add_no_meaning_builtins("infix", "Infix", NoMeaningInfixOperator, modules[__name__])


add_no_meaning_infix_operators()
87 changes: 87 additions & 0 deletions mathics/builtin/no_meaning/infix_extra.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""
Infix Operators that require Additional Mathics3 Modules
Some Infix operators require loading Mathics3 Modules before the operators is used in a special way.
Right now, this happens for directed and undirected edges of a network graph. Before issuing 'LoadModule["pymathics.graph"]', \
the operators here have no meaning and can be user defined like other operators that have no pre-set meaning.
"""

from mathics.core.attributes import A_NO_ATTRIBUTES
from mathics.core.builtin import InfixOperator


class DirectedEdge(InfixOperator):
"""
<url>
:WML link:
https://reference.wolfram.com/language/ref/DirectedEdge.html</url>
<dl>
<dt>'DirectedEdge[$x$, $y$, ...]'
<dd>displays $x$ → $y$ → ...
Directed edges are typically used in network graphs. In Mathics3, \
network graphs are supported through a Mathics3 module.
Issue 'LoadModule["pymathics.graph"]' after 'pip' installing Python package \
'pymathics-graph'.
</dl>
>> DirectedEdge[x, y, z]
= x → y → z
>> a \\[DirectedEdge] b
= a → b
"""

formats = {
(("InputForm", "OutputForm", "StandardForm"), "DirectedEdge[args__]"): (
'Infix[{args}, "→"]'
),
}

attributes = A_NO_ATTRIBUTES
default_formats = False # Don't use any default format rules. Instead, see belo.

operator = "→"
summary_text = 'DirectedEdge infix operator "→"'


class UndirectedEdge(InfixOperator):
"""
<url>
:WML link:
https://reference.wolfram.com/language/ref/UndirectedEdge.html</url>
<dl>
<dt>'UndrectedEdge[$x$, $y$, ...]'
<dd>displays $x$ ↔ $y$ ↔ ...
Undirected edges are typically used in network graphs. In Mathics3, \
network graphs are supported through a Mathics3 module.
Issue 'LoadModule["pymathics.graph"]' after 'pip' installing Python package \
'pymathics-graph'.
</dl>
>> UndirectedEdge[x, y, z]
= x ↔ y ↔ z
>> a \\[UndirectedEdge] b
= a ↔ b
"""

formats = {
(("InputForm", "OutputForm", "StandardForm"), "UndirectedEdge[args__]"): (
'Infix[{args}, "↔"]'
),
}

attributes = A_NO_ATTRIBUTES
default_formats = False # Don't use any default format rules. Instead, see belo.

operator = "↔"
summary_text = 'UndirectedEdge infix operator "↔"'
56 changes: 56 additions & 0 deletions mathics/builtin/no_meaning/postfix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""
Postfix Operators without Built-in Meanings
"""

from sys import modules

import mathics.core.parser.operators
from mathics.core.builtin import NoMeaningPostfixOperator
from mathics.core.parser.operators import OPERATOR_DATA


def add_no_meaning_builtins(
affix: str, format_function_name: str, operator_base_class, builtin_module
):
operator_key = f"no-meaning-{affix}-operators"
for operator_name, operator_tuple in OPERATOR_DATA[operator_key].items():
# Create the Mathics3 Builtin class...
operator_string = operator_tuple[0]
generated_operator_class = type(
operator_name,
(operator_base_class,),
{
"__doc__": operator_base_class.__doc_pattern__.format(
operator_name=operator_name, operator_string=operator_string
),
"operator": operator_string,
"summary_text": f"""{operator_name} {affix} operator "{operator_string}" (no pre-set meaning attached)""",
"formats": {
(
("InputForm", "OutputForm", "StandardForm"),
f"{operator_name}[args__]",
): (('%s[{args}, "%s"]' % (format_function_name, operator_string)))
},
},
)

# FIXME: Right now, precedence for infix operators is listed in
# JSON only for infix operators. Extend table generation in the same way
# for prefix and postfix, and then extend the code below to
# assign operator precedences for prefix and postfix operators.
if affix == "infix":
mathics.core.parser.operators.flat_binary_ops[
operator_name
] = operator_tuple[1]

# Put the newly-created Builtin class inside this module.
setattr(builtin_module, operator_name, generated_operator_class)


def add_no_meaning_postfix_operators():
add_no_meaning_builtins(
"postfix", "Postfix", NoMeaningPostfixOperator, modules[__name__]
)


add_no_meaning_postfix_operators()
Loading

0 comments on commit 7fa3fa1

Please sign in to comment.