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

GH-123391: Code generators: Track stack and locals in if statements. #123397

Closed
wants to merge 16 commits into from

Conversation

markshannon
Copy link
Member

@markshannon markshannon commented Aug 27, 2024

This PR adds little functionality, but it will enable us to do much more effective stack spilling in the future.

I've deliberately left the spilling functionality for a later PR to make this PR easier to review.

This PR:

  • Adds a new Storage class which combines the state of the stack and the local variables within a micro-op.
  • Adds copying and merging functionality to that class, and the underlying stack and locals, to support tracking state across divergent flow.
  • Splits and merges the storage in if statements.

The resulting generated code is basically the same as we have now.

To simplify parsing, the code generator also enforces PEP 7 rules for braces.
Most of the changes in bytecodes.c are a result of this change.

Copy link
Member

@picnixz picnixz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some nitpicks.

Comment on lines +426 to +427
f"Locals not defined in stack order. "
f"Expected '{out.name}' is defined before '{undefined}'"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
f"Locals not defined in stack order. "
f"Expected '{out.name}' is defined before '{undefined}'"
f"Locals not defined in stack order. "
f"Expected {out.name!r} to be defined before {undefined!r}"

break
undefined = ""
for out in self.outputs:
if out.defined:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the first out.defined holds, then we don't really have anything "before" (unless this case is not possible?)

self.emit(next(tkn_iter))
lparen = next(tkn_iter)
self.emit(lparen)
assert(lparen.kind == "LPAREN")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert(lparen.kind == "LPAREN")
assert lparen.kind == "LPAREN"

self.emit(next(tkn_iter))
lparen = next(tkn_iter)
self.emit(lparen)
assert(lparen.kind == "LPAREN")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert(lparen.kind == "LPAREN")
assert lparen.kind == "LPAREN"

self.out.emit(next(tkn_iter))
lparen = next(tkn_iter)
self.emit(lparen)
assert(lparen.kind == "LPAREN")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert(lparen.kind == "LPAREN")
assert lparen.kind == "LPAREN"

Comment on lines +111 to +115
raise analysis_error(
f"Locals not defined in stack order. "
f"Expected '{out.name}' is defined before '{undefined}'",
tkn
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
raise analysis_error(
f"Locals not defined in stack order. "
f"Expected '{out.name}' is defined before '{undefined}'",
tkn
)
raise analysis_error(
f"Locals not defined in stack order. "
f"Expected {out.name!r} to be defined before {undefined!r}",
tkn
)

other.top_offset = self.top_offset.copy()
other.base_offset = self.base_offset.copy()
other.variables = [var.copy() for var in self.variables]
other.defined = set(self.defined)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
other.defined = set(self.defined)
other.defined = self.defined.copy()

self.out.emit(next(tkn_iter))
lparen = next(tkn_iter)
self.emit(lparen)
assert(lparen.kind == "LPAREN")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert(lparen.kind == "LPAREN")
assert lparen.kind == "LPAREN"

self.run_cases_test(input, output)


def test_pep7_condition(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe test the else branch as well?

@markshannon
Copy link
Member Author

Replaced by #124392

@picnixz Thanks for review. I've ported your suggestion to the replacement PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants