Skip to content
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

Merged
merged 36 commits into from
Nov 15, 2022
Merged

Conversation

mmatera
Copy link
Contributor

@mmatera mmatera commented Nov 10, 2022

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 like

F[x_]:=G[x]

H[F[x_]]:= x^2

the assignment is done to H[G[x_]] instead of H[F[x_]], i.e., the argument of the LHS is evaluated before the assignment. Also, more comments on the routines of the mathics.builtin.assignment.internals is provided.

# decide whether doing this this is warranted.
new_list._build_elements_properties()
new_list.value = None
return new_list
Copy link
Contributor Author

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.

Copy link
Member

@rocky rocky Nov 13, 2022

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.

mmatera and others added 18 commits November 10, 2022 18:24
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
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.
@rocky
Copy link
Member

rocky commented Nov 13, 2022

@mmatera I believe we are getting conflicts because this brange duplicates commits in other branches and assumed that the other branches weren't going to change before commit.

If this follows #602 I think a better strategy is to base the branch off of #602 and create the PR to go back into #602.

@mmatera
Copy link
Contributor Author

mmatera commented Nov 13, 2022

@mmatera I believe we are getting conflicts because this brange duplicates commits in other branches and assumed that the other branches weren't going to change before commit.

If this follows #602 I think a better strategy is to base the branch off of #602 and create the PR to go back into #602.

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):
Copy link
Member

@rocky rocky Nov 13, 2022

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.

Copy link
Member

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):

Copy link
Member

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
Copy link
Member

@rocky rocky Nov 13, 2022

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.

Copy link
Member

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.

Copy link
Member

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.
Copy link
Member

@rocky rocky Nov 13, 2022

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.

@@ -86,6 +86,10 @@ def __str__(self) -> str:

# @timeit
def evaluate_elements(self, evaluation):
Copy link
Member

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.

(
"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",
Copy link
Member

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?

@rocky
Copy link
Member

rocky commented Nov 13, 2022

@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).

@rocky rocky changed the title Fix set eval Correct LHS evaluation in Set assignment Nov 13, 2022
@rocky rocky changed the title Correct LHS evaluation in Set assignment Correct LHS evaluation in Set, SetDelayed assignment Nov 13, 2022
@rocky rocky changed the title Correct LHS evaluation in Set, SetDelayed assignment Correct LHS evaluation in SetDelayed assignment Nov 13, 2022
rocky and others added 3 commits November 14, 2022 22:18
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
@rocky
Copy link
Member

rocky commented Nov 15, 2022

LGTM - merge when satisfied

@mmatera
Copy link
Contributor Author

mmatera commented Nov 15, 2022

Ok, when the ci finishes, let's merge this and then we can continue with the other parts

@mmatera mmatera merged commit 2ffdf02 into master Nov 15, 2022
@mmatera mmatera deleted the fix_set_eval branch November 15, 2022 04:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants