Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion mathics/core/assignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,13 @@ def is_protected(tag: str, definitions: Definitions) -> bool:

def normalize_lhs(lhs, evaluation):
"""
Process the lhs in a way that
Process the lhs in a way that:

* if it is a conditional expression, reduce it to
a shallow conditional expression
( Conditional[Conditional[...],tst] -> Conditional[stripped_lhs, tst])
with `stripped_lhs` the result of strip all the conditions from lhs.

* if ``stripped_lhs`` is not a ``List`` or a ``Part`` expression, evaluate the
elements.

Expand Down
10 changes: 5 additions & 5 deletions mathics/core/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ def __init__(self, name, count, expected):

class Builtin:
"""
A base class for a Built-in function symbols, like List, or
variables, like $SystemID, and Built-in Objects, like
DateTimeObject.
A base class for a Built-in function symbols, like ``List``, or
variables, like ``$SystemID``, and Built-in Objects, like
``DateTimeObject``.

Some of the class variables of the Builtin object are used to
create a definition object for that built-in symbol. In particular,
Expand All @@ -136,11 +136,11 @@ class Builtin:

For example:

```
.. code-block:: python

def eval(x, evaluation):
"F[x_Real]"
return Expression(Symbol("G"), x*2)
```

adds a ``FunctionApplyRule`` to the symbol's definition object that implements
``F[x_]->G[x*2]``.
Expand Down
11 changes: 7 additions & 4 deletions mathics/core/convert/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,13 @@ def to_mathics_list(
elements_conversion_fn: Callable = from_python,
) -> ListExpression:
"""
This is an expression constructor for list that can be used when the elements are not Mathics
objects. For example:
to_mathics_list(1, 2, 3)
to_mathics_list(1, 2, 3, elements_conversion_fn=Integer)
This is an expression constructor for list that can be used when
the elements are not Mathics objects.

For example::

to_mathics_list(1, 2, 3)
to_mathics_list(1, 2, 3, elements_conversion_fn=Integer)
"""
elements_tuple, elements_properties, _ = convert_expression_elements(
elements, elements_conversion_fn
Expand Down
21 changes: 12 additions & 9 deletions mathics/core/evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -541,16 +541,17 @@ def publish(self, tag: str, *args, **kwargs) -> None:
class Message(_Out):
def __init__(self, symbol: Union[Symbol, str], tag: str, text: str) -> None:
"""
A Mathics3 message of some sort. symbol_or_string can either be a symbol or a
string.
A Mathics3 message of some sort. ``symbol`` can either
be a symbol or a string.

Symbol: classifies which predefined or variable this comes from? If there is none
use a string.
tag: a short slug string that indicates the kind of message
``symbol``: classifies which predefined or variable this comes
from? If there is none use a string.

``tag``: a short slug string that indicates the kind of message

In Django we need to use a string for symbol, since we need
something that is JSON serializable and a Mathics3 Symbol is not
like this.
something that is JSON serializable and a Mathics3 Symbol is
not like this.
"""
super(Message, self).__init__()
self.is_message = True # Why do we need this?
Expand Down Expand Up @@ -625,8 +626,10 @@ class Result:
In particular, there are the following fields:

result: the actual result produced.
out: a list of additional output strings. These are warning or error messages. See "form"
for exactly what they are.

out: a list of additional output strings. These are warning or
error messages. See "form" for exactly what they are.

form: is the *format* of the result which tags the kind of result .
Think of this as something like a mime/type. Some formats:

Expand Down
61 changes: 36 additions & 25 deletions mathics/core/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,15 @@ class Expression(BaseElement, NumericOperators, EvalMixin):
function.

positional Arguments:
- head -- The head of the M-Expression
- *elements - optional: the remaining elements
- *literal_values - optional: if this is not None, then all elements
are (Python) literal values and literal_values
contains these literals.

- ``head`` -- The head of the M-Expression
- ``*elements`` - optional: the remaining elements
- ``*literal_values`` - optional: if this is not ``None``, then all elements
are (Python) literal values and ``literal_values`` contains these literals.

Keyword Arguments:
- elements_properties -- properties of the collection of elements

- ``elements_properties`` -- properties of the collection of elements

"""

Expand Down Expand Up @@ -662,35 +663,43 @@ def flatten_with_respect_to_head(
self, head: Symbol, pattern_only=False, callback=None, level=100
) -> "Expression":
"""
Flatten elements in self which have `head` in them.
Flatten elements in ``self`` which have ``head`` in them.

The idea is that in an expression like:

Expression(Plus, 1, Expression(Plus, 2, 3), 4)

when "Plus" is specified as the head, this expression should get changed to:
when "Plus" is specified as the head, this expression should
get changed to::

Expression(Plus, 1, 2, 3, 4)

In other words, all of the Plus operands are collected to together into one operation.
This is more efficiently evaluated. Note that we only flatten Plus functions, not other functions,
whether or not they contain Plus.
In other words, all of the ``Plus`` operands are collected to
together into one operation. This is more efficiently
evaluated. Note that we only flatten ``Plus`` functions, not other
functions, whether or not they contain ``Plus``.

So in::

So in:
Expression(Plus, Times(1, 2, Plus(3, 4)))

the expression is unchanged.

head: head element to be consider flattening on. Only expressions with this will be flattened.
This is always the head element or the next head element of the expression that the
elements are drawn from
``head``: head element to be consider flattening on. Only
expressions with this will be flattened. This is always
the head element or the next head element of the
expression that the elements are drawn from

``callback``: a callback function called each time a element
is flattened.

``level``: maximum depth to flatten. This often isn't used and
seems to have been put in as a potential safety
measure possibly for the future. If you don't want a
limit on flattening pass a negative number.

callback: a callback function called each time a element is flattened.
level: maximum depth to flatten. This often isn't used and seems to have been put in
as a potential safety measure possibly for the future. If you don't want a limit
on flattening pass a negative number.
pattern_only: if True, just apply to elements that are pattern_sequence (see ExpressionPattern.get_wrappings)
``pattern_only``: if ``True``, just apply to elements that are
pattern_sequence (see ``ExpressionPattern.get_wrappings``)
"""
from mathics.core.convert.expression import to_expression_with_specialization

Expand Down Expand Up @@ -1112,7 +1121,7 @@ def has_symbol(self, symbol_name: str) -> bool:
)

def restructure(self, head, elements, evaluation, structure_cache=None, deps=None):
"""Faster equivalent of: Expression(head, *elements)
"""Faster equivalent of: ``Expression(head, *elements)``

The caller guarantees that _all_ elements are either from
self.elements (or its subtrees) or from one of the expression given
Expand Down Expand Up @@ -1645,10 +1654,12 @@ def sort(self, pattern=False):

def do_apply_rules(self, rules, evaluation, level=0, options=None):
"""
for rule in rules:
result = rule.apply(self, evaluation, fully=False)
if result is not None:
return result
.. code-block:: python

for rule in rules:
result = rule.apply(self, evaluation, fully=False)
if result is not None:
return result
"""
from mathics.core.convert.expression import to_expression_with_specialization

Expand Down
8 changes: 5 additions & 3 deletions mathics/core/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ class ListExpression(Expression):
A Mathics3 List is a specialization of Expression where the head is SymbolList.

positional Arguments:
- *elements - optional: the remaining elements

- ``*elements`` - optional: the remaining elements

Keyword Arguments:
- elements_properties -- properties of the collection of elements
- literal_values -- if this is not None, then it is a tuple of Python values

- ``elements_properties`` -- properties of the collection of elements
- ``literal_values`` -- if this is not ``None``, then it is a tuple of Python values
"""

_is_literal: bool
Expand Down
2 changes: 1 addition & 1 deletion mathics/core/load_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ def import_and_load_builtins():

def import_builtin_module(import_name: str, modules: List[ModuleType]):
"""
Imports ``the list of Mathics3 Built-in modules so that inside
Imports the list of Mathics3 Built-in modules so that inside
Mathics3 Builtin Functions, like Plus[], List[] are defined.

List ``module_names`` is updated.
Expand Down
26 changes: 12 additions & 14 deletions mathics/core/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,15 @@

On the other hand, suppose that we define a `FunctionApplyRule` that associates `F[x_]` with the function:

```
...
class MyFunction(Builtin):
...
def eval_f(self, x, evaluation) -> Optional[Expression]:
"F[x_]" # pattern part of FunctionApplyRule
if x>3:
return Expression(SymbolPower, x, Integer2)
return None
```
.. code-block:: python

class MyFunction(Builtin):
...
def eval_f(self, x, evaluation) -> Optional[Expression]:
"F[x_]" # pattern part of FunctionApplyRule
if x>3:
return Expression(SymbolPower, x, Integer2)
return None

Then, if we apply the rule to `F[2]`, the function is evaluated returning `None`. Then, in the evaluation loop, we get the same
effect as if the pattern didn't match with the expression. The loop continues then with the next rule associated with `F`.
Expand Down Expand Up @@ -217,14 +216,13 @@ class Rule(BaseRule):
finishes.

Here is an example of a Rule::
F[x_] -> x^2 (* The same thing as: Rule[x_, x^2] *)

F[x_] -> x^2 (* The same thing as: Rule[x_, x^2] *)

``F[x_]`` is a pattern and ``x^2`` is the replacement term. When
applied to the expression ``G[F[1.], F[a]]`` the result is
``G[1.^2, a^2]``


Note: we want Rules to be serializable so that we can dump and
restore Rules in order to make startup time faster.

Expand Down Expand Up @@ -315,8 +313,8 @@ class FunctionApplyRule(BaseRule):

when applied to the expression ``SetAttributes[F, NumericFunction]``

sets the attribute ``NumericFunction`` in the definition of the symbol ``F`` and
returns Null (``SymbolNull`)`.
sets the attribute ``NumericFunction`` in the definition of the symbol
``F`` and returns Null (``SymbolNull``).

This will cause `Expression.evaluate() to perform an additional
``rewrite_apply_eval()`` step.
Expand Down
3 changes: 2 additions & 1 deletion mathics/core/structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ def slice(self, expr, py_slice):
class UnlinkedStructure(Structure):
"""
UnlinkedStructure produces Expressions that are not linked to "origins" in terms of cache.
This produces the same thing as doing Expression(head, *elements).

This produces the same thing as doing ``Expression(head, *elements)``.
"""

def __init__(self, head):
Expand Down
9 changes: 5 additions & 4 deletions mathics/core/symbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,18 @@
class NumericOperators:
"""
This is a mixin class for Element-like objects that might have numeric values.
It adds or "mixes in" numeric functions for these objects like round_to_float().
It adds or "mixes in" numeric functions for these objects like ``round_to_float()``.

It also adds methods to the class to facilite building
``Expression``s in the Mathics Python code using Python syntax.
``Expression`` s in the Mathics Python code using Python syntax.

So for example, instead of writing in Python:
So for example, instead of writing in Python::

to_expression("Abs", -8)
Expression(SymbolPlus, Integer1, Integer2)

you can instead have:
you can instead have::

abs(Integer(-8))
Integer(1) + Integer(2)
"""
Expand Down