-
-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Correct LHS evaluation in SetDelayed assignment #603
Conversation
…ay from the conditional.
# decide whether doing this this is warranted. | ||
new_list._build_elements_properties() | ||
new_list.value = None | ||
return new_list |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Notice that in Expression.evaluate_elements
, a new expression is returned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for catching! I guess this was a bug fixed then. If this was causing a problem, I am curious as to where it was causing a problem.
catch not known attributes in ClearAttributes and SetAttributes
`mathics.builtin.attributes`: * apply -> eval * Add WMA links add * Class names ordered alphabetically * Hard breaks in docstring removed * Some incorrect references to "leaves" changed to "attributes" `mathics.core.attributes`: * Add short comments above flag value
…andards Update 'attributes' for current standards
…ay from the conditional.
fix a bug that makes that URLSave always fails
improving clarity in Builtin.contribute
Adding comments and tests for Assignment
symbols.py: system_symbols() -> symbol_set(); "systems_symbols" name is too close Symbol( System` to module systemsymbols. Also, we now require symbols as parameters), not strings. systemsymbols.py: more system symbols
It appears this was originally Pattern.create. I suspect due to bad modularity and a lack of understandig Python that an import could be added inside the routine, this static method got moved outside of the class. Later on, the modularity was fixed, but the hack persisted. These kinds of code smells side effects of poor communication.
wehn it gets fixed.
improve `OneIdentity` builtin
Yep, to make this work I had to merge the previous version of the oneidentity pr. This needs a rebase now, and yes, that strategy sound reasonable. |
@@ -122,6 +124,32 @@ def is_protected(tag, defin): | |||
return A_PROTECTED & defin.get_attributes(tag) | |||
|
|||
|
|||
def normalize_lhs(lhs, evaluation): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If seems to me that this function and, more generally, the entire module should be moved to mathics.core
.
Let me explain a little here. The code was originally organized around "builtins" which were put in the mathics.core.builtin
module. In particular a Builtin class definition contained:
- Mathics Pattern matching signature
- eval methods
- low-level routines to support eval methods
- Boxing routines
- high-level format and low-level render routines
- doctests and some pytests
- other miscellaneous things.
I suppose for a toy implementation for a subset of the Mathematica, this might have been fine to start out with.
What I think we are finding is that this is just not scalable or production quality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggested function signature with type annotation:
def normalize_lhs(lhs: Expression, evaluation: Evaluation) -> Tuple(Expression, str):
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, although there are lots of little comments, this style of function is a great improvement over the style that we were left with. Thanks!
a shallow conditional expression | ||
( Conditional[Conditional[...],tst] -> Conditional[uncondlhs, tst]) | ||
with `uncondlhs` the result of strip all the conditions from lhs. | ||
* if `uncondlhs` is not a `List` or a `Part` expression, evaluate the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A small note here. I have been using the RsT tagging inside docstrings like this. So for example:
* if ``uncondlhs`` is not a ``List`` or ``Part`` expression ...
The reason I do this that this is what Sphinx uses by default when told to create system-level documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small thing, as a variable name lhs
is fine, when not a variable symbol, I think caps is better: Process the LHS because it is in fact an acronym like IBM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the name "uncondlhs" feels awkward. Please consider using underscores to separate words, e.g. "uncond_lhs" or the maybe "stripped_lhs".
@@ -538,6 +538,10 @@ def evaluate( | |||
return expr | |||
|
|||
def evaluate_elements(self, evaluation) -> "Expression": | |||
""" | |||
return a new expression with the same head, and the | |||
evaluable elements evaluated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"evaluable" is jarring. Maybe we can just remove this word?
From an old IBM manual:
Depressing the Power On key initiates the power on sequence.
Depressing the Power Off key initiates the power off sequence.
Depressing the Power On key when the power is already on has no effect.
Depressing the Power Off key when the power is already off has no effect.
Similarly trying to evaluation an element where there is nothing to evaluate has no effect, so suspect does not need to be spelled out.
mathics/core/list.py
Outdated
@@ -86,6 +86,10 @@ def __str__(self) -> str: | |||
|
|||
# @timeit | |||
def evaluate_elements(self, evaluation): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggested signature:
def evaluate_elements(self, evaluation: Evaluation) -> Expression:
Yes, I realize this was from before. I am trying to up our game in terms of quality incrementally as we improve things.
test/builtin/test_assignment.py
Outdated
( | ||
"F[x_]:=G[x]; H[F[y_]]^:=Q[y]; ClearAll[F]; {H[G[5]],H[F[5]]}", | ||
"{Q[5], H[F[5]]}", | ||
"The arguments on the LHS are evaluated before the assignment", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to change the failure message to something different than the others above and below. In particular, how is this test different from the others?
@mmatera All very good and much needed. Thanks! The coding style in this new code has been greatly improved over what has come before in the code base (although if it is not too much I am pushing for a tad more). |
Move core-like assignment interals out of builtins and into core. (We may want to split up core more in the future though) Better sort long list of assignment methods alphabetically Some small RstT tagging in a docstring Remove nonexistent word "evaluable" Add yet another type annotation to a signature Make test assert failure messages unique
Changes suggested in PR review
LGTM - merge when satisfied |
Ok, when the ci finishes, let's merge this and then we can continue with the other parts |
This PR follows #602. After fixing OneIdentity, it was possible to fix a little bit the behavior of
Set*
, in a way that in expressions likethe assignment is done to
H[G[x_]]
instead ofH[F[x_]]
, i.e., the argument of the LHS is evaluated before the assignment. Also, more comments on the routines of themathics.builtin.assignment.internals
is provided.