Skip to content

Commit f52ac9c

Browse files
committed
merge
2 parents ea2a748 + 4be33d2 commit f52ac9c

56 files changed

Lines changed: 10238 additions & 8501 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

mathics/builtin/__init__.py

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
#!/usr/bin/env python3
21
# -*- coding: utf-8 -*-
3-
from mathics.core.expression import ensure_context
42

53
import glob
64
import importlib
75
import re
86
import os.path as osp
97
from mathics.settings import ENABLE_FILES_MODULE
8+
from mathics.version import __version__ # noqa used in loading to check consistency.
109

1110
# Get a list of file in this directory. We'll exclude from the start
1211
# files with leading characters we don't want like __init__ with its leading underscore.
@@ -23,8 +22,6 @@
2322
PatternObject,
2423
)
2524

26-
from mathics.settings import ENABLE_FILES_MODULE
27-
2825
exclude_files = set(("files", "codetables", "base", "importexport", "colors"))
2926
module_names = [
3027
f for f in __py_files__ if re.match("^[a-z0-9]+$", f) if f not in exclude_files
@@ -38,12 +35,20 @@
3835
for module_name in module_names:
3936
try:
4037
module = importlib.import_module("mathics.builtin." + module_name)
41-
except:
42-
# print("XXX", module_name)
38+
except Exception as e:
39+
print(e)
40+
print(f" Not able to load {module_name}. Check your installation.")
41+
print(f" mathics.builtin loads from {__file__[:-11]}")
4342
continue
43+
44+
if __version__ != module.__version__:
45+
print(
46+
f"Version {module.__version__} in the module do not match with {__version__}"
47+
)
48+
4449
modules.append(module)
4550

46-
builtins = []
51+
_builtins = []
4752
builtins_by_module = {}
4853

4954

@@ -75,7 +80,7 @@ def is_builtin(var):
7580
# This set the default context for symbols in mathics.builtins
7681
if not type(instance).context:
7782
type(instance).context = "System`"
78-
builtins.append( (instance.get_name(), instance))
83+
_builtins.append((instance.get_name(), instance))
7984
builtins_by_module[module.__name__].append(instance)
8085

8186

@@ -85,7 +90,6 @@ def is_builtin(var):
8590
mathics_to_python = {} # here we have: name -> string
8691
sympy_to_mathics = {}
8792

88-
box_constructs = {}
8993
pattern_objects = {}
9094
builtins_precedence = {}
9195

@@ -101,20 +105,26 @@ def add_builtins(new_builtins):
101105
mathics_to_sympy[name] = builtin
102106
for sympy_name in builtin.get_sympy_names():
103107
sympy_to_mathics[sympy_name] = builtin
104-
if isinstance(builtin, BoxConstruct):
105-
box_constructs[name] = builtin
106108
if isinstance(builtin, Operator):
107109
builtins_precedence[name] = builtin.precedence
108110
if isinstance(builtin, PatternObject):
109111
pattern_objects[name] = builtin.__class__
110-
builtins.update(dict(new_builtins))
112+
_builtins.update(dict(new_builtins))
111113

112114

113-
new_builtins = builtins
114-
builtins = {}
115+
new_builtins = _builtins
116+
_builtins = {}
115117
add_builtins(new_builtins)
116118

117119

120+
def builtins_dict():
121+
return {
122+
builtin.get_name(): builtin
123+
for modname, builtins in builtins_by_module.items()
124+
for builtin in builtins
125+
}
126+
127+
118128
def get_module_doc(module):
119129
doc = module.__doc__
120130
if doc is not None:
@@ -134,8 +144,8 @@ def get_module_doc(module):
134144

135145
def contribute(definitions):
136146
# let MakeBoxes contribute first
137-
builtins["System`MakeBoxes"].contribute(definitions)
138-
for name, item in builtins.items():
147+
_builtins["System`MakeBoxes"].contribute(definitions)
148+
for name, item in _builtins.items():
139149
if name != "System`MakeBoxes":
140150
item.contribute(definitions)
141151

mathics/builtin/algebra.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
#!/usr/bin/env python3
21
# -*- coding: utf-8 -*-
32
"""
43
Algebraic Manipulation
54
"""
65

6+
from mathics.version import __version__ # noqa used in loading to check consistency.
77

88
from mathics.builtin.base import Builtin
99
from mathics.core.expression import Expression, Integer, Symbol, Atom, Number

mathics/builtin/arithmetic.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#!/usr/bin/env python3
21
# -*- coding: utf-8 -*-
32
# cython: language_level=3
43

@@ -8,7 +7,7 @@
87
Basic arithmetic functions, including complex number arithmetic.
98
"""
109

11-
10+
from mathics.version import __version__ # noqa used in loading to check consistency.
1211
import sympy
1312
import mpmath
1413

mathics/builtin/assignment.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#!/usr/bin/env python3
21
# -*- coding: utf-8 -*-
32

3+
from mathics.version import __version__ # noqa used in loading to check consistency.
44

55
import mathics.builtin
66
from mathics.builtin.base import (
@@ -848,7 +848,7 @@ def _get_usage_string(symbol, evaluation, htmlout=False):
848848
bio = pymathics.get(definition.name)
849849
if bio is None:
850850
bio = builtins.get(definition.name)
851-
851+
852852
if bio is not None:
853853
from mathics.doc.doc import Doc
854854
docstr = bio.builtin.__class__.__doc__
@@ -1768,9 +1768,6 @@ def apply(self, module, evaluation):
17681768
except ImportError as e:
17691769
evaluation.message(self.get_name(), 'notfound', module)
17701770
return SymbolFailed
1771-
except PyMathicsLoadException as e:
1772-
evaluation.message(self.get_name(), 'notmathicslib', module)
1773-
return SymbolFailed
17741771
else:
17751772
# Add Pymathics` to $ContextPath so that when user don't
17761773
# have to qualify Pymathics variables and functions,

mathics/builtin/attributes.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#!/usr/bin/env python3
21
# -*- coding: utf-8 -*-
32

43
r"""
@@ -8,9 +7,9 @@
87
However, you can set any symbol as an attribute, in contrast to \Mathematica.
98
"""
109

10+
from mathics.version import __version__ # noqa used in loading to check consistency.
1111

1212
from mathics.builtin.base import Predefined, Builtin
13-
from mathics.builtin.evaluation import Sequence
1413
from mathics.core.expression import Expression, Symbol, SymbolNull, String
1514
from mathics.builtin.assignment import get_symbol_list
1615

mathics/builtin/base.py

Lines changed: 109 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#!/usr/bin/env python3
21
# -*- coding: utf-8 -*-
32

43
import re
@@ -10,6 +9,8 @@
109
import typing
1110
from typing import Any, cast
1211

12+
from mathics.version import __version__ # noqa used in loading to check consistency.
13+
1314
from mathics.core.definitions import Definition
1415
from mathics.core.parser.util import SystemDefinitions, PyMathicsDefinitions
1516
from mathics.core.rules import Rule, BuiltinRule, Pattern
@@ -27,6 +28,7 @@
2728
)
2829
from mathics.core.numbers import get_precision, PrecisionValueError
2930

31+
3032
def get_option(options, name, evaluation, pop=False, evaluate=True):
3133
# we do not care whether an option X is given as System`X,
3234
# Global`X, or with any prefix from $ContextPath for that
@@ -83,6 +85,7 @@ def __init__(self, *args, **kwargs):
8385

8486
def contribute(self, definitions, is_pymodule=False):
8587
from mathics.core.parser import parse_builtin_rule
88+
8689
# Set the default context
8790
if not self.context:
8891
self.context = "Pymathics`" if is_pymodule else "System`"
@@ -146,9 +149,7 @@ def check_options(options_to_check, evaluation):
146149

147150
for pattern, function in self.get_functions(is_pymodule=is_pymodule):
148151
rules.append(
149-
BuiltinRule(
150-
name, pattern, function, check_options, system=True
151-
)
152+
BuiltinRule(name, pattern, function, check_options, system=True)
152153
)
153154
for pattern, replace in self.rules.items():
154155
if not isinstance(pattern, BaseExpression):
@@ -269,7 +270,7 @@ def contextify_form_name(f):
269270
attributes=attributes,
270271
options=options,
271272
defaultvalues=defaults,
272-
builtin=self
273+
builtin=self,
273274
)
274275
if is_pymodule:
275276
definitions.pymathics[name] = definition
@@ -365,7 +366,7 @@ def get_option_string(self, *params):
365366
return None, s
366367

367368

368-
class InstancableBuiltin(Builtin):
369+
class InstanceableBuiltin(Builtin):
369370
def __new__(cls, *args, **kwargs):
370371
new_kwargs = kwargs.copy()
371372
new_kwargs["expression"] = False
@@ -378,7 +379,7 @@ def __new__(cls, *args, **kwargs):
378379
try:
379380
instance.init(*args, **kwargs)
380381
except TypeError:
381-
# TypeError occurs when unpickling instance, e.g. PatterObject,
382+
# TypeError occurs when unpickling instance, e.g. PatternObject,
382383
# because parameter expr is not given. This should no be a
383384
# problem, as pickled objects need their init-method not
384385
# being called.
@@ -540,7 +541,7 @@ def get_constant(self, precision, evaluation, have_mpmath=False):
540541

541542
sympy_fn = self.to_sympy()
542543
if d is None:
543-
result = self.get_mpmath_function()if have_mpmath else sympy_fn()
544+
result = self.get_mpmath_function() if have_mpmath else sympy_fn()
544545
return MachineReal(result)
545546
else:
546547
return PrecisionReal(sympy_fn.n(d))
@@ -593,11 +594,105 @@ class BoxConstructError(Exception):
593594
pass
594595

595596

596-
class BoxConstruct(Builtin):
597-
def get_option_values(self, leaves, evaluation=None, **options):
598-
default = evaluation.definitions.get_options(self.get_name()).copy()
599-
options = Expression("List", *leaves).get_option_values(evaluation)
600-
default.update(options)
597+
class BoxConstruct(InstanceableBuiltin):
598+
def __new__(cls, *leaves, **kwargs):
599+
instance = super().__new__(cls, *leaves, **kwargs)
600+
instance._leaves = leaves
601+
return instance
602+
603+
def evaluate(self, evaluation):
604+
# THINK about: Should we evaluate the leaves here?
605+
return
606+
607+
def get_head_name(self):
608+
return self.get_name()
609+
610+
def get_lookup_name(self):
611+
return self.get_name()
612+
613+
def get_string_value(self):
614+
return "-@" + self.get_head_name() + "@-"
615+
616+
def same(self, expr):
617+
return expr.same(self)
618+
619+
def is_atom(self):
620+
return False
621+
622+
def do_format(self, evaluation, format):
623+
return self
624+
625+
def format(self, evaluation, fmt):
626+
return self
627+
628+
def get_head(self):
629+
return Symbol(self.get_name())
630+
631+
@property
632+
def head(self):
633+
return self.get_head()
634+
635+
@head.setter
636+
def head(self, value):
637+
raise ValueError("BoxConstruct.head is write protected.")
638+
639+
@property
640+
def leaves(self):
641+
return self._leaves
642+
643+
@leaves.setter
644+
def leaves(self, value):
645+
raise ValueError("BoxConstruct.leaves is write protected.")
646+
647+
# I need to repeat this, because this is not
648+
# an expression...
649+
def has_form(self, heads, *leaf_counts):
650+
"""
651+
leaf_counts:
652+
(,): no leaves allowed
653+
(None,): no constraint on number of leaves
654+
(n, None): leaf count >= n
655+
(n1, n2, ...): leaf count in {n1, n2, ...}
656+
"""
657+
658+
head_name = self.get_name()
659+
if isinstance(heads, (tuple, list, set)):
660+
if head_name not in [ensure_context(h) for h in heads]:
661+
return False
662+
else:
663+
if head_name != ensure_context(heads):
664+
return False
665+
if not leaf_counts:
666+
return False
667+
if leaf_counts and leaf_counts[0] is not None:
668+
count = len(self._leaves)
669+
if count not in leaf_counts:
670+
if (
671+
len(leaf_counts) == 2
672+
and leaf_counts[1] is None # noqa
673+
and count >= leaf_counts[0]
674+
):
675+
return True
676+
else:
677+
return False
678+
return True
679+
680+
def flatten_pattern_sequence(self, evaluation) -> "BoxConstruct":
681+
return self
682+
683+
def get_option_values(self, leaves, **options):
684+
evaluation = options.get("evaluation", None)
685+
if evaluation:
686+
default = evaluation.definitions.get_options(self.get_name()).copy()
687+
options = Expression("List", *leaves).get_option_values(evaluation)
688+
default.update(options)
689+
else:
690+
from mathics.core.parser import parse_builtin_rule
691+
692+
default = {}
693+
for option, value in self.options.items():
694+
option = ensure_context(option)
695+
default[option] = parse_builtin_rule(value)
601696
return default
602697

603698
def boxes_to_text(self, leaves, **options) -> str:
@@ -620,7 +715,7 @@ def __init__(self, name, count, expected):
620715
super().__init__(None, None)
621716

622717

623-
class PatternObject(InstancableBuiltin, Pattern):
718+
class PatternObject(InstanceableBuiltin, Pattern):
624719
needs_verbatim = True
625720

626721
arg_counts: typing.List[int] = []

0 commit comments

Comments
 (0)