Skip to content

Warning

This page is under construction. The content may be incomplete or incorrect. Submit an issue on GitHub if you need help or want to contribute.

Dialects that brings in common Python data types

This page provides a reference for dialects that bring in semantics for common Python data types.

Note

While it is worth noting that using Python semantics can be very convenient, it is also important to remember that the Python semantics are not designed for compilation. Therefore, it is important to be aware of the limitations of using Python semantics in a compilation context especially when it comes to data types. An example of this is the list data type in Python which is a dynamic mutable array. When the low-level code is not expecting a dynamic mutable array, it can lead to extra complexity for compilation. An immutable array or a fixed-size array can be a better choice in such cases (see ilist dialect).

References

Tuple

kirin.dialects.py.tuple

The tuple dialect for Python.

This dialect provides a way to work with Python tuples in the IR, including:

  • The New statement class.
  • The lowering pass for the tuple statement.
  • The concrete implementation of the tuple statement.
  • The type inference implementation of the tuple addition with py.binop.Add.
  • The constant propagation implementation of the tuple statement.
  • The Julia emitter for the tuple statement.

This dialect maps ast.Tuple nodes to the New statement.

dialect module-attribute

dialect = Dialect('py.tuple')

Concrete dataclass

Concrete()

Bases: MethodTable

new

new(
    interp: interp.Interpreter,
    frame: interp.Frame,
    stmt: New,
)
Source code in src/kirin/dialects/py/tuple.py
45
46
47
@interp.impl(New)
def new(self, interp: interp.Interpreter, frame: interp.Frame, stmt: New):
    return (frame.get_values(stmt.args),)

ConstPropTable dataclass

ConstPropTable()

Bases: MethodTable

new_tuple

new_tuple(
    _: const.Propagate, frame: const.Frame, stmt: New
) -> interp.StatementResult[const.Result]
Source code in src/kirin/dialects/py/tuple.py
77
78
79
80
81
82
83
84
@interp.impl(New)
def new_tuple(
    self,
    _: const.Propagate,
    frame: const.Frame,
    stmt: New,
) -> interp.StatementResult[const.Result]:
    return (const.PartialTuple(tuple(x for x in frame.get_values(stmt.args))),)

JuliaTable dataclass

JuliaTable()

Bases: MethodTable

emit_NewTuple

emit_NewTuple(
    emit: EmitJulia, frame: EmitStrFrame, stmt: New
)
Source code in src/kirin/dialects/py/tuple.py
103
104
105
106
107
108
109
@interp.impl(New)
def emit_NewTuple(self, emit: EmitJulia, frame: EmitStrFrame, stmt: New):
    return (
        emit.write_assign(
            frame, stmt.result, "(" + ", ".join(frame.get_values(stmt.args)) + ")"
        ),
    )

Lowering

Bases: FromPythonAST

lower_Tuple

lower_Tuple(
    state: lowering.LoweringState, node: ast.Tuple
) -> lowering.Result
Source code in src/kirin/dialects/py/tuple.py
90
91
92
93
94
95
96
97
def lower_Tuple(
    self, state: lowering.LoweringState, node: ast.Tuple
) -> lowering.Result:
    return lowering.Result(
        state.append_stmt(
            stmt=New(tuple(state.visit(elem).expect_one() for elem in node.elts))
        )
    )

New kirin-statement

New(values: tuple[ir.SSAValue, ...])

Bases: Statement

Source code in src/kirin/dialects/py/tuple.py
32
33
34
35
36
37
38
39
def __init__(self, values: tuple[ir.SSAValue, ...]) -> None:
    result_type = types.Generic(tuple, *tuple(value.type for value in values))
    super().__init__(
        args=values,
        result_types=[
            result_type,
        ],
    )

result kirin-result

result: ResultValue = result()

traits class-attribute instance-attribute

traits = frozenset({Pure(), FromPythonCall()})

TypeInfer dataclass

TypeInfer()

Bases: MethodTable

add

add(interp, frame: interp.Frame[types.TypeAttribute], stmt)
Source code in src/kirin/dialects/py/tuple.py
64
65
66
67
68
69
70
71
@interp.impl(Add, types.PyClass(tuple), types.PyClass(tuple))
def add(self, interp, frame: interp.Frame[types.TypeAttribute], stmt):
    lhs = frame.get(stmt.lhs)
    rhs = frame.get(stmt.rhs)
    if isinstance(lhs, types.Generic) and isinstance(rhs, types.Generic):
        return (types.Generic(tuple, *(lhs.vars + rhs.vars)),)
    else:
        return (types.PyClass(tuple),)  # no type param, so unknown

eltype_tuple

eltype_tuple(interp, frame: interp.Frame, stmt: ElType)
Source code in src/kirin/dialects/py/tuple.py
53
54
55
56
57
58
59
60
61
62
@interp.impl(ElType, types.PyClass(tuple))
def eltype_tuple(self, interp, frame: interp.Frame, stmt: ElType):
    tuple_type = frame.get(stmt.container)
    if isinstance(tuple_type, types.Generic):
        ret = tuple_type.vars[0]
        for var in tuple_type.vars[1:]:
            ret = ret.join(var)
        return (ret,)
    else:
        return (types.Any,)

List

kirin.dialects.py.list

The list dialect for Python.

This module contains the dialect for list semantics in Python, including:

  • The New and Append statement classes.
  • The lowering pass for list operations.
  • The concrete implementation of list operations.
  • The type inference implementation of list operations.

This dialect maps list(), ast.List and append() calls to the New and Append statements.