This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git


The following commit(s) were added to refs/heads/main by this push:
     new 0176f438cd [Script] Make transpiler call helper keywords explicit 
(#20448)
0176f438cd is described below

commit 0176f438cdd09978db0a82ece9bdfb070b544b6f
Author: Tianqi Chen <[email protected]>
AuthorDate: Fri Sep 25 09:58:00 2026 -0400

    [Script] Make transpiler call helper keywords explicit (#20448)
    
    The transpiler call helpers currently mix builder arguments and
    source-location metadata in variadic keyword dictionaries. Make the
    builder keyword mapping optional and explicit, with dedicated
    keyword-only parameters for `span`, `name_span`, and `value_span`.
    
    Update callers to separate builder arguments from source ranges while
    preserving their evaluation order and leaving caller-owned mappings
    unchanged. This is a readability cleanup.
---
 python/tvm/script/parser/transpile.py | 70 +++++++++++++++++++++++++----------
 1 file changed, 50 insertions(+), 20 deletions(-)

diff --git a/python/tvm/script/parser/transpile.py 
b/python/tvm/script/parser/transpile.py
index e955549005..fbe3eb141a 100644
--- a/python/tvm/script/parser/transpile.py
+++ b/python/tvm/script/parser/transpile.py
@@ -287,33 +287,60 @@ class IRBuilderTranspiler(ast.NodeTransformer):
         )
 
     def _call(
-        self, namespace: str, member: str, args: list[ast.expr], node: 
ast.AST, **keywords: ast.expr
+        self,
+        namespace: str,
+        member: str,
+        args: list[ast.expr],
+        node: ast.AST,
+        *,
+        keywords: Mapping[str, ast.expr] | None = None,
+        span: ast.expr | None = None,
+        name_span: ast.expr | None = None,
+        value_span: ast.expr | None = None,
     ) -> ast.Call:
         """Build a generated operation with its source range and named 
arguments."""
-        if not self.module.track_span:
-            keywords.pop("span", None)
-            keywords.pop("name_span", None)
-            keywords.pop("value_span", None)
+        arguments = [ast.keyword(key, value) for key, value in 
keywords.items()] if keywords else []
+        if self.module.track_span:
+            if span is not None:
+                arguments.append(ast.keyword("span", span))
+            if name_span is not None:
+                arguments.append(ast.keyword("name_span", name_span))
+            if value_span is not None:
+                arguments.append(ast.keyword("value_span", value_span))
         return ast.copy_location(
             ast.Call(
                 ast.Attribute(ast.Name(namespace, ast.Load()), member, 
ast.Load()),
                 args,
-                [ast.keyword(key, value) for key, value in keywords.items()],
+                arguments,
             ),
             node,
         )
 
     def _call_dialect(
-        self, member: str, args: list[ast.expr], node: ast.AST, **keywords: 
ast.expr
+        self,
+        member: str,
+        args: list[ast.expr],
+        node: ast.AST,
+        *,
+        keywords: Mapping[str, ast.expr] | None = None,
+        span: ast.expr | None = None,
+        name_span: ast.expr | None = None,
+        value_span: ast.expr | None = None,
     ) -> ast.Call:
-        return self._call(
+        # Dialect calls evaluate their span, name span, builder arguments, 
then value span.
+        call = self._call(
             self.function.dialect_prefix,
             member,
             args,
             node,
-            span=self.module.make_span_expr(node),
-            **keywords,
+            span=self.module.make_span_expr(node) if span is None else span,
+            name_span=name_span,
         )
+        if keywords:
+            call.keywords.extend(ast.keyword(key, value) for key, value in 
keywords.items())
+        if self.module.track_span and value_span is not None:
+            call.keywords.append(ast.keyword("value_span", value_span))
+        return call
 
     def _attach_span(self, value: ast.expr, node: ast.AST) -> ast.expr:
         if (
@@ -974,7 +1001,7 @@ class IRBuilderTranspiler(ast.NodeTransformer):
                     [value],
                     statement,
                     name_span=self.module.make_span_expr(target),
-                    **keywords,
+                    keywords=keywords,
                 )
             elif kind == "module_alias" and not frame_value:
                 # -------------------- Pattern --------------------
@@ -1014,18 +1041,19 @@ class IRBuilderTranspiler(ast.NodeTransformer):
                 # Builder:
                 #     y = X.bind_(value, name="y", span=target_span, 
value_span=rhs_span)
                 # -------------------------------------------------
-                if value_span is not None:
-                    keywords["value_span"] = value_span
                 value = (
                     self._call_dialect(
                         "bind_",
                         [value],
                         statement,
                         name_span=self.module.make_span_expr(target),
-                        **keywords,
+                        keywords=keywords,
+                        value_span=value_span,
                     )
                     if frame_value
-                    else self._call_dialect("bind_", [value], target, 
**keywords)
+                    else self._call_dialect(
+                        "bind_", [value], target, keywords=keywords, 
value_span=value_span
+                    )
                 )
             if frame_value:
                 # Binding an entered frame originates at the source as-target;
@@ -1136,9 +1164,11 @@ class IRBuilderTranspiler(ast.NodeTransformer):
                         "setitem_",
                         [],
                         node,
-                        value=self._rewrite_assignment_value(node.value, 
ordinary=ordinary),
-                        target=self.visit(target.value),
-                        key=self._rewrite_index(target.slice),
+                        keywords={
+                            "value": 
self._rewrite_assignment_value(node.value, ordinary=ordinary),
+                            "target": self.visit(target.value),
+                            "key": self._rewrite_index(target.slice),
+                        },
                         span=self.module.make_span_expr(node),
                     )
                 ),
@@ -1464,7 +1494,7 @@ class IRBuilderTranspiler(ast.NodeTransformer):
             )
         else:
             self._raise_error(node.target, "Loop targets must be names or a 
flat tuple of names")
-        context = self._call_dialect("for_", [iterable], node, names=names)
+        context = self._call_dialect("for_", [iterable], node, 
keywords={"names": names})
         # The generated iteration check originates at the source iterable, not
         # the final body line. Its native frame span still covers the whole 
loop.
         ast.copy_location(context, node.iter)
@@ -1838,7 +1868,7 @@ class IRBuilderTranspiler(ast.NodeTransformer):
                         "resolve_type_var_",
                         [ast.Constant(parameter.name)],
                         parameter,
-                        dtype=ast.Constant(dtype),
+                        keywords={"dtype": ast.Constant(dtype)},
                     ),
                     parameter,
                 )

Reply via email to