mirror of
https://github.com/python/cpython.git
synced 2025-11-01 06:01:29 +00:00
gh-98831: Support conditional effects; use for LOAD_ATTR (#101333)
This commit is contained in:
parent
c4170c36b0
commit
f5a3d91b6c
6 changed files with 194 additions and 120 deletions
|
|
@ -48,9 +48,6 @@ def to_text(self, dedent: int = 0) -> str:
|
|||
context = self.context
|
||||
if not context:
|
||||
return ""
|
||||
tokens = context.owner.tokens
|
||||
begin = context.begin
|
||||
end = context.end
|
||||
return lx.to_text(self.tokens, dedent)
|
||||
|
||||
@property
|
||||
|
|
@ -74,13 +71,13 @@ class Block(Node):
|
|||
class StackEffect(Node):
|
||||
name: str
|
||||
type: str = "" # Optional `:type`
|
||||
cond: str = "" # Optional `if (cond)`
|
||||
size: str = "" # Optional `[size]`
|
||||
# Note: we can have type or size but not both
|
||||
# TODO: condition (can be combined with type but not size)
|
||||
# Note: size cannot be combined with type or cond
|
||||
|
||||
|
||||
@dataclass
|
||||
class Dimension(Node):
|
||||
class Expression(Node):
|
||||
size: str
|
||||
|
||||
|
||||
|
|
@ -239,31 +236,39 @@ def cache_effect(self) -> CacheEffect | None:
|
|||
|
||||
@contextual
|
||||
def stack_effect(self) -> StackEffect | None:
|
||||
# IDENTIFIER
|
||||
# | IDENTIFIER ':' IDENTIFIER
|
||||
# | IDENTIFIER '[' dimension ']'
|
||||
# TODO: Conditions
|
||||
# IDENTIFIER [':' IDENTIFIER] ['if' '(' expression ')']
|
||||
# | IDENTIFIER '[' expression ']'
|
||||
if tkn := self.expect(lx.IDENTIFIER):
|
||||
type_text = ""
|
||||
if self.expect(lx.COLON):
|
||||
typ = self.require(lx.IDENTIFIER)
|
||||
return StackEffect(tkn.text, typ.text)
|
||||
elif self.expect(lx.LBRACKET):
|
||||
if not (dim := self.dimension()):
|
||||
raise self.make_syntax_error("Expected dimension")
|
||||
type_text = self.require(lx.IDENTIFIER).text.strip()
|
||||
cond_text = ""
|
||||
if self.expect(lx.IF):
|
||||
self.require(lx.LPAREN)
|
||||
if not (cond := self.expression()):
|
||||
raise self.make_syntax_error("Expected condition")
|
||||
self.require(lx.RPAREN)
|
||||
cond_text = cond.text.strip()
|
||||
size_text = ""
|
||||
if self.expect(lx.LBRACKET):
|
||||
if type_text or cond_text:
|
||||
raise self.make_syntax_error("Unexpected [")
|
||||
if not (size := self.expression()):
|
||||
raise self.make_syntax_error("Expected expression")
|
||||
self.require(lx.RBRACKET)
|
||||
return StackEffect(tkn.text, "PyObject **", dim.text.strip())
|
||||
else:
|
||||
return StackEffect(tkn.text)
|
||||
type_text = "PyObject **"
|
||||
size_text = size.text.strip()
|
||||
return StackEffect(tkn.text, type_text, cond_text, size_text)
|
||||
|
||||
@contextual
|
||||
def dimension(self) -> Dimension | None:
|
||||
def expression(self) -> Expression | None:
|
||||
tokens: list[lx.Token] = []
|
||||
while (tkn := self.peek()) and tkn.kind != lx.RBRACKET:
|
||||
while (tkn := self.peek()) and tkn.kind not in (lx.RBRACKET, lx.RPAREN):
|
||||
tokens.append(tkn)
|
||||
self.next()
|
||||
if not tokens:
|
||||
return None
|
||||
return Dimension(lx.to_text(tokens).strip())
|
||||
return Expression(lx.to_text(tokens).strip())
|
||||
|
||||
@contextual
|
||||
def super_def(self) -> Super | None:
|
||||
|
|
@ -366,7 +371,7 @@ def members(self) -> list[str] | None:
|
|||
return None
|
||||
|
||||
@contextual
|
||||
def block(self) -> Block:
|
||||
def block(self) -> Block | None:
|
||||
if self.c_blob():
|
||||
return Block()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue