Skip to content

Commit

Permalink
Auto generate ast expression nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
Glyphack committed Feb 20, 2025
1 parent b385c7d commit fd8c7cd
Show file tree
Hide file tree
Showing 5 changed files with 837 additions and 701 deletions.
36 changes: 29 additions & 7 deletions crates/ruff_python_ast/ast.toml
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,6 @@ anynode_is_label = "expression"
rustdoc = "/// See also [expr](https://docs.python.org/3/library/ast.html#ast.expr)"

[Expr.nodes]
ExprBoolOp = {}
ExprNamed = {}
ExprBinOp = {}
ExprUnaryOp = {}
ExprLambda = {}
ExprIf = {}
ExprDict = {}
ExprSet = {}
ExprListComp = {}
ExprSetComp = {}
Expand All @@ -113,6 +106,35 @@ ExprList = {}
ExprTuple = {}
ExprSlice = {}
ExprIpyEscapeCommand = {}
ExprBoolOp = { fields = [
{ name = "op", type = "BoolOp" },
{ name = "values", type = "Expr", seq = true }
]}
ExprNamed = { fields = [
{ name = "target", type = "Expr" },
{ name = "value", type = "Expr" }
]}
ExprBinOp = { fields = [
{ name = "left", type = "Expr" },
{ name = "op", type = "Operator" },
{ name = "right", type = "Expr" }
]}
ExprUnaryOp = { fields = [
{ name = "op", type = "UnaryOp" },
{ name = "operand", type = "Expr" }
]}
ExprLambda = { fields = [
{ name = "parameters", type = "Parameters", optional = true },
{ name = "body", type = "Expr" }
]}
ExprIf = { fields = [
{ name = "test", type = "Expr" },
{ name = "body", type = "Expr" },
{ name = "orelse", type = "Expr" }
]}
ExprDict = { fields = [
{ name = "items", type = "DictItem", seq = true },
]}

[ExceptHandler]
rustdoc = "/// See also [excepthandler](https://docs.python.org/3/library/ast.html#ast.excepthandler)"
Expand Down
64 changes: 64 additions & 0 deletions crates/ruff_python_ast/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,30 @@ class Node:
name: str
variant: str
ty: str
fields: list[Field] | None

def __init__(self, group: Group, node_name: str, node: dict[str, Any]) -> None:
self.name = node_name
self.variant = node.get("variant", node_name.removeprefix(group.name))
self.ty = f"crate::{node_name}"
self.fields = None
fields = node.get("fields")
if fields is not None:
self.fields = [Field(f) for f in fields]


@dataclass
class Field:
name: str
ty: str
seq: bool
optional: bool

def __init__(self, field: dict[str, Any]) -> None:
self.name = field["name"]
self.ty = field["type"]
self.seq = field.get("seq", False)
self.optional = field.get("optional", False)


# ------------------------------------------------------------------------------
Expand Down Expand Up @@ -547,6 +566,50 @@ def write_nodekind(out: list[str], ast: Ast) -> None:
""")


# ------------------------------------------------------------------------------
# NodeKind


def write_node(out: list[str], ast: Ast) -> None:
write_node_list = [
"ExprBoolOp",
"ExprNamed",
"ExprBinOp",
"ExprUnaryOp",
"ExprLambda",
"ExprIf",
"ExprDict",
]
group_names = [group.name for group in ast.groups]
node_names = [node.name for node in ast.all_nodes]
for group in ast.groups:
for node in group.nodes:
if node.name not in write_node_list:
continue
if node.fields is not None:
out.append("#[derive(Clone, Debug, PartialEq)]")
name = node.name
out.append(f"pub struct {name} {{")
out.append("pub range: ruff_text_size::TextRange,")
for field in node.fields:
field_str = f"pub {field.name}: "
inner = f"crate::{field.ty}"
if field.ty in node_names or (
field.ty in group_names and (field.seq is False)
):
inner = f"Box<{inner}>"

if field.seq:
field_str += f"Vec<{inner}>,"
elif field.optional:
field_str += f"Option<{inner}>,"
else:
field_str += f"{inner},"
out.append(field_str)
out.append("}")
out.append("")


# ------------------------------------------------------------------------------
# Format and write output

Expand All @@ -558,6 +621,7 @@ def generate(ast: Ast) -> list[str]:
write_ref_enum(out, ast)
write_anynoderef(out, ast)
write_nodekind(out, ast)
write_node(out, ast)
return out


Expand Down
Loading

0 comments on commit fd8c7cd

Please sign in to comment.