564 lines
12 KiB
Python
564 lines
12 KiB
Python
# Licensed to the Apache Software Foundation (ASF) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
# to you under the Apache License, Version 2.0 (the
|
|
# "License"); you may not use this file except in compliance
|
|
# with the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing,
|
|
# software distributed under the License is distributed on an
|
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
# KIND, either express or implied. See the License for the
|
|
# specific language governing permissions and limitations
|
|
# under the License.
|
|
# ruff: noqa: F841
|
|
"""
|
|
In this test file, we want to make sure the Python code can construct
|
|
Doc objects, then access and modify their attributes correctly.
|
|
"""
|
|
|
|
import pytest
|
|
from tvm_ffi.access_path import AccessPath
|
|
|
|
import tvm
|
|
from tvm.script.printer.doc import (
|
|
AssertDoc,
|
|
AssignDoc,
|
|
AttrAccessDoc,
|
|
CallDoc,
|
|
ClassDoc,
|
|
CommentDoc,
|
|
DictDoc,
|
|
DocStringDoc,
|
|
ExprStmtDoc,
|
|
ForDoc,
|
|
FunctionDoc,
|
|
IdDoc,
|
|
IfDoc,
|
|
IndexDoc,
|
|
LambdaDoc,
|
|
ListDoc,
|
|
LiteralDoc,
|
|
OperationDoc,
|
|
OperationKind,
|
|
ReturnDoc,
|
|
ScopeDoc,
|
|
SliceDoc,
|
|
StmtBlockDoc,
|
|
TupleDoc,
|
|
WhileDoc,
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"value",
|
|
[None, "test", 0, 1, -2, 0.0, 1.5, -1.3, True, False],
|
|
)
|
|
def test_literal_doc_construction(value):
|
|
doc = LiteralDoc(value)
|
|
|
|
if isinstance(value, float):
|
|
# FloatImm cannot be compared with Python's float directly
|
|
assert float(doc.value) == pytest.approx(value)
|
|
else:
|
|
assert doc.value == value
|
|
|
|
|
|
def test_id_doc():
|
|
doc = IdDoc("name")
|
|
|
|
assert doc.name == "name"
|
|
|
|
|
|
def test_attr_access_doc():
|
|
target = IdDoc("x")
|
|
|
|
doc = AttrAccessDoc(target, "attribute")
|
|
|
|
assert doc.value == target
|
|
assert doc.name == "attribute"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"indices",
|
|
[
|
|
[],
|
|
[LiteralDoc(1)],
|
|
[LiteralDoc(2), IdDoc("x")],
|
|
[SliceDoc(LiteralDoc(1), LiteralDoc(2))],
|
|
[SliceDoc(LiteralDoc(1)), IdDoc("y")],
|
|
],
|
|
)
|
|
def test_index_doc(indices):
|
|
target = IdDoc("x")
|
|
|
|
doc = IndexDoc(target, indices)
|
|
|
|
assert doc.value == target
|
|
assert list(doc.indices) == indices
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"args, kwargs",
|
|
[
|
|
([], {}),
|
|
([LiteralDoc("arg")], {}),
|
|
([LiteralDoc("arg"), IdDoc("x")], {}),
|
|
([], {"x": LiteralDoc("x")}),
|
|
([], {"x": LiteralDoc("x"), "y": LiteralDoc("y")}),
|
|
([LiteralDoc("arg")], {"x": LiteralDoc("x"), "y": LiteralDoc("y")}),
|
|
([LiteralDoc("arg"), IdDoc("x")], {"x": LiteralDoc("x"), "y": LiteralDoc("y")}),
|
|
],
|
|
)
|
|
def test_call_doc(args, kwargs):
|
|
target = IdDoc("x")
|
|
|
|
doc = CallDoc(target, *args, **kwargs)
|
|
|
|
assert doc.callee == target
|
|
assert list(doc.args) == args
|
|
assert dict(zip(doc.kwargs_keys, doc.kwargs_values)) == kwargs
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"operands",
|
|
[
|
|
[],
|
|
[LiteralDoc(1)],
|
|
[LiteralDoc(2), IdDoc("x")],
|
|
[LiteralDoc(2), IdDoc("x"), LiteralDoc("y")],
|
|
],
|
|
)
|
|
def test_operation_doc(operands):
|
|
# Here we just test the contructor and attr visitor of OperationDoc
|
|
# so the choice of OperationKind doesn't matter
|
|
operator = OperationKind.Add
|
|
|
|
doc = OperationDoc(OperationKind.Add, operands)
|
|
|
|
assert doc.kind == operator
|
|
assert list(doc.operands) == operands
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"args",
|
|
[
|
|
[],
|
|
[IdDoc("x")],
|
|
[IdDoc("x"), IdDoc("y")],
|
|
],
|
|
)
|
|
def test_lambda_doc(args):
|
|
body = LiteralDoc(1)
|
|
|
|
doc = LambdaDoc(args, body)
|
|
|
|
assert doc.body == body
|
|
assert list(doc.args) == args
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"elements",
|
|
[
|
|
[],
|
|
[IdDoc("x")],
|
|
[IdDoc("x"), IdDoc("y")],
|
|
],
|
|
)
|
|
def test_tuple_doc(elements):
|
|
doc = TupleDoc(elements)
|
|
|
|
assert list(doc.elements) == elements
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"elements",
|
|
[
|
|
[],
|
|
[IdDoc("x")],
|
|
[IdDoc("x"), IdDoc("y")],
|
|
],
|
|
)
|
|
def test_list_doc(elements):
|
|
doc = ListDoc(elements)
|
|
|
|
assert list(doc.elements) == elements
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"content",
|
|
[
|
|
{},
|
|
{LiteralDoc("k"): IdDoc("v")},
|
|
{LiteralDoc("k"): IdDoc("v"), LiteralDoc("k2"): IdDoc("v2")},
|
|
],
|
|
)
|
|
def test_dict_doc(content):
|
|
doc = DictDoc(content)
|
|
|
|
assert dict(zip(doc.keys, doc.values)) == content
|
|
|
|
|
|
@pytest.mark.parametrize("start", [LiteralDoc(1), None])
|
|
@pytest.mark.parametrize("stop", [LiteralDoc(2), None])
|
|
@pytest.mark.parametrize("step", [LiteralDoc(3), None])
|
|
def test_slice_doc(start, stop, step):
|
|
doc = SliceDoc(start, stop)
|
|
|
|
assert doc.start == start
|
|
assert doc.stop == stop
|
|
|
|
|
|
def test_expr_doc_attr_access():
|
|
target = IdDoc("x")
|
|
attr = "test"
|
|
|
|
doc = target.attr(attr)
|
|
|
|
assert doc.value == target
|
|
assert doc.name == attr
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"indices",
|
|
[
|
|
(),
|
|
LiteralDoc(1),
|
|
SliceDoc(LiteralDoc(1), LiteralDoc(2)),
|
|
(LiteralDoc(1),),
|
|
(LiteralDoc(2), IdDoc("x")),
|
|
(SliceDoc(LiteralDoc(1), LiteralDoc(2)),),
|
|
(SliceDoc(LiteralDoc(1)), IdDoc("y")),
|
|
],
|
|
)
|
|
def test_expr_doc_get_item(indices):
|
|
target = IdDoc("x")
|
|
|
|
doc = target[indices]
|
|
|
|
assert doc.value == target
|
|
if not isinstance(indices, tuple):
|
|
indices = (indices,)
|
|
assert tuple(doc.indices) == indices
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"args, kwargs",
|
|
[
|
|
([], {}),
|
|
([LiteralDoc("arg")], {}),
|
|
([LiteralDoc("arg"), IdDoc("x")], {}),
|
|
([], {"x": LiteralDoc("x")}),
|
|
([], {"x": LiteralDoc("x"), "y": LiteralDoc("y")}),
|
|
([LiteralDoc("arg")], {"x": LiteralDoc("x"), "y": LiteralDoc("y")}),
|
|
([LiteralDoc("arg"), IdDoc("x")], {"x": LiteralDoc("x"), "y": LiteralDoc("y")}),
|
|
],
|
|
)
|
|
def test_expr_doc_call_with(args, kwargs):
|
|
target = IdDoc("x")
|
|
|
|
doc = target.call(*args, **kwargs)
|
|
|
|
assert doc.callee == target
|
|
assert list(doc.args) == args
|
|
assert dict(zip(doc.kwargs_keys, doc.kwargs_values)) == kwargs
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"stmts",
|
|
[
|
|
[],
|
|
[ExprStmtDoc(IdDoc("x"))],
|
|
[ExprStmtDoc(IdDoc("x")), ExprStmtDoc(IdDoc("y"))],
|
|
],
|
|
)
|
|
def test_stmt_block_doc(stmts):
|
|
doc = StmtBlockDoc(stmts)
|
|
|
|
assert list(doc.stmts) == stmts
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"lhs, rhs, annotation",
|
|
[
|
|
(IdDoc("x"), IdDoc("y"), None),
|
|
(IdDoc("x"), None, IdDoc("int")),
|
|
(IdDoc("x"), IdDoc("y"), IdDoc("int")),
|
|
],
|
|
)
|
|
def test_assign_doc(lhs, rhs, annotation):
|
|
doc = AssignDoc(lhs, rhs, annotation)
|
|
|
|
assert doc.lhs == lhs
|
|
assert doc.rhs == rhs
|
|
assert doc.annotation == annotation
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"lhs, rhs, annotation",
|
|
[
|
|
(IdDoc("x"), None, None),
|
|
(TupleDoc([IdDoc("x"), IdDoc("y")]), None, IdDoc("int")),
|
|
(TupleDoc([IdDoc("x"), IdDoc("y")]), IdDoc("u"), IdDoc("int")),
|
|
],
|
|
)
|
|
def test_invalid_assign_doc(lhs, rhs, annotation):
|
|
with pytest.raises(ValueError) as e:
|
|
AssignDoc(lhs, rhs, annotation)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"else_branch",
|
|
[
|
|
[],
|
|
[ExprStmtDoc(IdDoc("x"))],
|
|
[ExprStmtDoc(IdDoc("x")), ExprStmtDoc(IdDoc("y"))],
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"then_branch",
|
|
[
|
|
[],
|
|
[ExprStmtDoc(IdDoc("x"))],
|
|
[ExprStmtDoc(IdDoc("x")), ExprStmtDoc(IdDoc("y"))],
|
|
],
|
|
)
|
|
def test_if_doc(then_branch, else_branch):
|
|
predicate = IdDoc("x")
|
|
|
|
if not then_branch and not else_branch:
|
|
with pytest.raises(ValueError) as e:
|
|
IfDoc(predicate, then_branch, else_branch)
|
|
return
|
|
else:
|
|
doc = IfDoc(predicate, then_branch, else_branch)
|
|
|
|
assert doc.predicate == predicate
|
|
assert list(doc.then_branch) == then_branch
|
|
assert list(doc.else_branch) == else_branch
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"body",
|
|
[
|
|
[],
|
|
[ExprStmtDoc(IdDoc("x"))],
|
|
[ExprStmtDoc(IdDoc("x")), ExprStmtDoc(IdDoc("y"))],
|
|
],
|
|
)
|
|
def test_while_doc(body):
|
|
predicate = IdDoc("x")
|
|
|
|
doc = WhileDoc(predicate, body)
|
|
|
|
assert doc.predicate == predicate
|
|
assert list(doc.body) == body
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"body",
|
|
[
|
|
[],
|
|
[ExprStmtDoc(IdDoc("x"))],
|
|
[ExprStmtDoc(IdDoc("x")), ExprStmtDoc(IdDoc("y"))],
|
|
],
|
|
)
|
|
def test_for_doc(body):
|
|
lhs = IdDoc("x")
|
|
rhs = IdDoc("y")
|
|
|
|
doc = ForDoc(lhs, rhs, body)
|
|
|
|
assert doc.lhs == lhs
|
|
assert doc.rhs == rhs
|
|
assert list(doc.body) == body
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"lhs",
|
|
[
|
|
None,
|
|
IdDoc("x"),
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"body",
|
|
[
|
|
[],
|
|
[ExprStmtDoc(IdDoc("x"))],
|
|
[ExprStmtDoc(IdDoc("x")), ExprStmtDoc(IdDoc("y"))],
|
|
],
|
|
)
|
|
def test_scope_doc(lhs, body):
|
|
rhs = IdDoc("y")
|
|
|
|
doc = ScopeDoc(lhs, rhs, body)
|
|
|
|
assert doc.lhs == lhs
|
|
assert doc.rhs == rhs
|
|
assert list(doc.body) == body
|
|
|
|
|
|
def test_expr_stmt_doc():
|
|
expr = IdDoc("x")
|
|
|
|
doc = ExprStmtDoc(expr)
|
|
|
|
assert doc.expr == expr
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"msg",
|
|
[
|
|
None,
|
|
LiteralDoc("msg"),
|
|
],
|
|
)
|
|
def test_assert_doc(msg):
|
|
test = IdDoc("x")
|
|
|
|
doc = AssertDoc(test, msg)
|
|
|
|
assert doc.test == test
|
|
assert doc.msg == msg
|
|
|
|
|
|
def test_return_doc():
|
|
value = IdDoc("x")
|
|
|
|
doc = ReturnDoc(value)
|
|
|
|
assert doc.value == value
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"args",
|
|
[
|
|
[],
|
|
[AssignDoc(IdDoc("x"), None, IdDoc("int"))],
|
|
[
|
|
AssignDoc(IdDoc("x"), None, IdDoc("int")),
|
|
AssignDoc(IdDoc("y"), LiteralDoc(1), IdDoc("int")),
|
|
],
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"decorators",
|
|
[
|
|
[],
|
|
[IdDoc("test")],
|
|
[IdDoc("test"), IdDoc("test2")],
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"return_type",
|
|
[
|
|
None,
|
|
LiteralDoc(None),
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"body",
|
|
[
|
|
[],
|
|
[ExprStmtDoc(IdDoc("x"))],
|
|
[ExprStmtDoc(IdDoc("x")), ExprStmtDoc(IdDoc("y"))],
|
|
],
|
|
)
|
|
def test_function_doc(args, decorators, return_type, body):
|
|
name = IdDoc("name")
|
|
|
|
doc = FunctionDoc(name, args, decorators, return_type, body)
|
|
|
|
assert doc.name == name
|
|
assert list(doc.args) == args
|
|
assert list(doc.decorators) == decorators
|
|
assert doc.return_type == return_type
|
|
assert list(doc.body) == body
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"decorators",
|
|
[
|
|
[],
|
|
[IdDoc("test")],
|
|
[IdDoc("test"), IdDoc("test2")],
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"body",
|
|
[
|
|
[],
|
|
[ExprStmtDoc(IdDoc("x"))],
|
|
[ExprStmtDoc(IdDoc("x")), ExprStmtDoc(IdDoc("y"))],
|
|
],
|
|
)
|
|
def test_class_doc(decorators, body):
|
|
name = IdDoc("name")
|
|
|
|
doc = ClassDoc(name, decorators, body)
|
|
|
|
assert doc.name == name
|
|
assert list(doc.decorators) == decorators
|
|
assert list(doc.body) == body
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"comment",
|
|
[
|
|
"",
|
|
"test comment 1",
|
|
"test comment 1\ntest comment 1",
|
|
],
|
|
)
|
|
def test_comment_doc(comment):
|
|
doc = CommentDoc(comment)
|
|
assert doc.comment == comment
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"comment",
|
|
[
|
|
"",
|
|
"test comment 1",
|
|
"test comment 1\ntest comment 1",
|
|
],
|
|
)
|
|
def test_doc_string_doc(comment):
|
|
doc = DocStringDoc(comment)
|
|
assert doc.comment == comment
|
|
|
|
|
|
def test_stmt_doc_comment():
|
|
doc = ExprStmtDoc(IdDoc("x"))
|
|
assert doc.comment is None
|
|
|
|
comment = "test comment"
|
|
doc.comment = comment
|
|
# Make sure the previous statement doesn't set attribute
|
|
# as if it's an ordinary Python object (__slots__ enforces this).
|
|
assert not hasattr(doc, "__dict__") or "comment" not in doc.__dict__
|
|
assert doc.comment == comment
|
|
|
|
|
|
def test_doc_source_paths():
|
|
doc = IdDoc("x")
|
|
assert len(doc.source_paths) == 0
|
|
|
|
source_paths = [AccessPath.root(), AccessPath.root().attr("x")]
|
|
|
|
doc.source_paths = source_paths
|
|
# This should triggers the __getattr__ and gets a tvm_ffi.Array
|
|
assert not isinstance(doc.source_paths, list)
|
|
assert list(doc.source_paths) == source_paths
|
|
|
|
doc.source_paths = []
|
|
assert len(doc.source_paths) == 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
tvm.testing.main()
|