-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Turn literal
and literal_hash
into functions
#3071
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
Changes from 1 commit
f3e18d3
48decc1
286348a
3f25101
9611e6e
3c37478
36c9c0f
04b2c3c
4e363d3
8c3941f
f81d941
9be2951
80d2d9b
8b63d02
859dbf3
f239978
dd44288
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing 10000
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2502,68 +2502,175 @@ def check_arg_names(names: List[Optional[str]], nodes: List[T], fail: Callable[[ | |
# of an index expression, or the operands of an operator expression). | ||
|
||
|
||
def literal_hash(e: Expression) -> Optional[Key]: | ||
def literal(e: Expression) -> int: | ||
if isinstance(e, ComparisonExpr): | ||
return min(literal(o) for o in e.operands) | ||
|
||
elif isinstance(e, OpExpr): | ||
return min(literal(e.left), literal(e.right)) | ||
|
||
elif isinstance(e, (MemberExpr, UnaryExpr, StarExpr)): | ||
return literal(e.expr) | ||
|
||
elif isinstance(e, IndexExpr): | ||
if literal(e.index) == LITERAL_YES: | ||
return literal(e.base) | ||
|
||
elif isinstance(e, NameExpr): | ||
return LITERAL_TYPE | ||
|
||
if isinstance(e, (IntExpr, FloatExpr, ComplexExpr, StrExpr, BytesExpr, UnicodeExpr)): | ||
return LITERAL_YES | ||
|
||
if literal_hash(e): | ||
return LITERAL_YES | ||
|
||
return LITERAL_NO | ||
|
||
|
||
def literal_hash(e: Expression) -> Optional[Key]: | ||
return e.accept(hasher) | ||
|
||
|
||
class Hasher(ExpressionVisitor[Optional[Key]]): | ||
def visit_int_expr(self, e: IntExpr) -> Key: | ||
return ('Literal', e.value) | ||
|
||
elif isinstance(e, StarExpr): | ||
def visit_str_expr(self, e: StrExpr) -> Key: | ||
return ('Literal', e.value) | ||
|
||
def visit_bytes_expr(self, e: BytesExpr) -> Key: | ||
return ('Literal', e.value) | ||
|
||
def visit_unicode_expr(self, e: UnicodeExpr) -> Key: | ||
return ('Literal', e.value) | ||
|
||
def visit_float_expr(self, e: FloatExpr) -> Key: | ||
return ('Literal', e.value) | ||
|
||
def visit_complex_expr(self, e: ComplexExpr) -> Key: | ||
return ('Literal', e.value) | ||
|
||
def visit_star_expr(self, e: StarExpr) -> Key: | ||
return ('Star', literal_hash(e.expr)) | ||
|
||
elif isinstance(e, NameExpr): | ||
def visit_name_expr(self, e: NameExpr) -> Key: | ||
return ('Var', e.name) | ||
|
||
elif isinstance(e, MemberExpr): | ||
def visit_member_expr(self, e: MemberExpr) -> Key: | ||
return ('Member', literal_hash(e.expr), e.name) | ||
|
||
elif isinstance(e, IndexExpr): | ||
if literal(e.index) == LITERAL_YES: | ||
return ('Index', literal_hash(e.base), literal_hash(e.index)) | ||
|
||
elif isinstance(e, UnaryExpr): | ||
return ('Unary', e.op, literal_hash(e.expr)) | ||
|
||
elif isinstance(e, OpExpr): | ||
def visit_op_expr(self, e: OpExpr) -> Key: | ||
return ('Binary', e.op, literal_hash(e.left), literal_hash(e.right)) | ||
|
||
elif isinstance(e, ComparisonExpr): | ||
def visit_comparison_expr(self, e: ComparisonExpr) -> Key: | ||
rest = tuple(e.operators) # type: Any | ||
rest += tuple(literal_hash(o) for o in e.operands) | ||
return ('Comparison',) + rest | ||
|
||
elif isinstance(e, (ListExpr, TupleExpr, SetExpr)): | ||
name = {ListExpr: 'List', TupleExpr: 'Tuple', SetExpr: 'Set'}[type(e)] # type: Any | ||
def visit_unary_expr(self, e: UnaryExpr) -> Key: | ||
return ('Unary', e.op, literal_hash(e.expr)) | ||
|
||
def seq_expr(self, e: Union[ListExpr, TupleExpr, SetExpr], name: str) -> Optional[Key]: | ||
if all(literal(x) == LITERAL_YES for x in e.items): | ||
return (name,) + tuple(literal_hash(x) for x in e.items) | ||
rest = tuple(literal_hash(x) for x in e.items) # type: Any | ||
return (name,) + rest | ||
return None | ||
|
||
def visit_list_expr(self, e: ListExpr) -> Optional[Key]: | ||
return self.seq_expr(e, 'List') | ||
|
||
elif isinstance(e, DictExpr): | ||
def visit_dict_expr(self, e: DictExpr) -> Optional[Key]: | ||
if all(a and literal(a) == literal(b) == LITERAL_YES for a, b in e.items): | ||
rest = tuple((literal_hash(a), literal_hash(b)) for a, b in e.items) | ||
rest = tuple((literal_hash(a), literal_hash(b)) for a, b in e.items) # type: Any | ||
return ('Dict',) + rest | ||
return None | ||
|
||
return None | ||
def visit_tuple_expr(self, e: TupleExpr) -> Optional[Key]: | ||
return self.seq_expr(e, 'Tuple') | ||
|
||
def visit_set_expr(self, e: SetExpr) -> Optional[Key]: | ||
return self.seq_expr(e, 'Set') | ||
|
||
def literal(e: Expression) -> int: | ||
if isinstance(e, ComparisonExpr): | ||
return min(literal(o) for o in e.operands) | ||
def visit_index_expr(self, e: IndexExpr) -> Optional[Key]: | ||
if literal(e.index) == LITERAL_YES: | ||
return ('Index', literal_hash(e.base), literal_hash(e.index)) | ||
return None | ||
|
||
elif isinstance(e, OpExpr): | ||
return min(literal(e.left), literal(e.right)) | ||
def visit_call_expr(self, e: CallExpr) -> None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe you can have a single method definition and then create a bunch of aliases. Example (not tried): def visit_non_literal(self, e: Node) -> None:
return None
visit_call_expr = visit_non_literal
visit_slice_expr = visit_non_literal
... This would reduce some of the verbosity. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This result in |
||
return None | ||
|
||
elif isinstance(e, (MemberExpr, UnaryExpr, StarExpr)): | ||
return literal(e.expr) | ||
def visit_slice_expr(self, e: SliceExpr) -> None: | ||
return None | ||
|
||
elif isinstance(e, IndexExpr): | ||
if literal(e.index) == LITERAL_YES: | ||
return literal(e.base) | ||
def visit_cast_expr(self, e: CastExpr) -> None: | ||
return None | ||
|
||
elif isinstance(e, NameExpr): | ||
return LITERAL_TYPE | ||
def visit_conditional_expr(self, e: ConditionalExpr) -> None: | ||
return None | ||
|
||
if isinstance(e, (IntExpr, FloatExpr, ComplexExpr, StrExpr, BytesExpr, UnicodeExpr)): | ||
return LITERAL_YES | ||
def visit_ellipsis(self, e: EllipsisExpr) -> None: | ||
return None | ||
|
||
if literal_hash(e): | ||
return LITERAL_YES | ||
def visit_yield_from_expr(self, e: YieldFromExpr) -> None: | ||
return None | ||
|
||
return LITERAL_NO | ||
def visit_yield_expr(self, e: YieldExpr) -> None: | ||
return None | ||
|
||
def visit_reveal_type_expr(self, e: RevealTypeExpr) -> None: | ||
return None | ||
|
||
def visit_super_expr(self, e: SuperExpr) -> None: | ||
return None | ||
|
||
def visit_type_application(self, e: TypeApplication) -> None: | ||
return None | ||
|
||
def visit_lambda_expr(self, e: LambdaExpr) -> None: | ||
return None | ||
|
||
def visit_list_comprehension(self, e: ListComprehension) -> None: | ||
return None | ||
|
||
def visit_set_comprehension(self, e: SetComprehension) -> None: | ||
return None | ||
|
||
def visit_dictionary_comprehension(self, e: DictionaryComprehension) -> None: | ||
return None | ||
|
||
def visit_generator_expr(self, e: GeneratorExpr) -> None: | ||
return None | ||
|
||
def visit_backquote_expr(self, e: BackquoteExpr) -> None: | ||
return None | ||
|
||
def visit_type_var_expr(self, e: TypeVarExpr) -> None: | ||
return None | ||
|
||
def visit_type_alias_expr(self, e: TypeAliasExpr) -> None: | ||
return None | ||
|
||
def visit_namedtuple_expr(self, e: NamedTupleExpr) -> None: | ||
return None | ||
|
||
def visit_enum_call_expr(self, e: EnumCallExpr) -> None: | ||
return None | ||
|
||
def visit_typeddict_expr(self, e: TypedDictExpr) -> None: | ||
return None | ||
|
||
def visit_newtype_expr(self, e: NewTypeExpr) -> None: | ||
return None | ||
|
||
def visit__promote_expr(self, e: PromoteExpr) -> None: | ||
return None | ||
|
||
def visit_await_expr(self, e: AwaitExpr) -> None: | ||
return None | ||
|
||
def visit_temp_node(self, e: TempNode) -> None: | ||
return None | ||
|
||
|
||
hasher = Hasher() |
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.
Add else where we return
LITERAL_NO
. Otherwise, it looks like we can returnLITERAL_YES
because of theif literal_hash(e):
check.