Skip to content

Commit 5a9782f

Browse files
committed
merge
2 parents a9f6631 + 4be33d2 commit 5a9782f

Some content is hidden

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

56 files changed

+10236
-8503
lines changed

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
@@ -26,6 +27,7 @@
2627
)
2728
from mathics.core.numbers import get_precision, PrecisionValueError
2829

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

8385
def contribute(self, definitions, is_pymodule=False):
8486
from mathics.core.parser import parse_builtin_rule
87+
8588
# Set the default context
8689
if not self.context:
8790
self.context = "Pymathics`" if is_pymodule else "System`"
@@ -145,9 +148,7 @@ def check_options(options_to_check, evaluation):
145148

146149
for pattern, function in self.get_functions(is_pymodule=is_pymodule):
147150
rules.append(
148-
BuiltinRule(
149-
name, pattern, function, check_options, system=True
150-
)
151+
BuiltinRule(name, pattern, function, check_options, system=True)
151152
)
152153
for pattern, replace in self.rules.items():
153154
if not isinstance(pattern, BaseExpression):
@@ -268,7 +269,7 @@ def contextify_form_name(f):
268269
attributes=attributes,
269270
options=options,
270271
defaultvalues=defaults,
271-
builtin=self
272+
builtin=self,
272273
)
273274
if is_pymodule:
274275
definitions.pymathics[name] = definition
@@ -364,7 +365,7 @@ def get_option_string(self, *params):
364365
return None, s
365366

366367

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

540541
sympy_fn = self.to_sympy()
541542
if d is None:
542-
result = self.get_mpmath_function()if have_mpmath else sympy_fn()
543+
result = self.get_mpmath_function() if have_mpmath else sympy_fn()
543544
return MachineReal(result)
544545
else:
545546
return PrecisionReal(sympy_fn.n(d))
@@ -592,11 +593,105 @@ class BoxConstructError(Exception):
592593
pass
593594

594595

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

602697
def boxes_to_text(self, leaves, **options) -> str:
@@ -619,7 +714,7 @@ def __init__(self, name, count, expected):
619714
super().__init__(None, None)
620715

621716

622-
class PatternObject(InstancableBuiltin, Pattern):
717+
class PatternObject(InstanceableBuiltin, Pattern):
623718
needs_verbatim = True
624719

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

0 commit comments

Comments
 (0)