Define AST nodes and instruction transformations.
Enable syntax: iadd(x, y) which creates an Apply node. Enable syntax: z << iadd(x, y) which creates a Def node. Add an XForm class which represents source and destination patterns as RTL lists.
This commit is contained in:
122
meta/cretonne/ast.py
Normal file
122
meta/cretonne/ast.py
Normal file
@@ -0,0 +1,122 @@
|
||||
"""
|
||||
Abstract syntax trees.
|
||||
|
||||
This module defines classes that can be used to create abstract syntax trees
|
||||
for patern matching an rewriting of cretonne instructions.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
|
||||
class Def(object):
|
||||
"""
|
||||
An AST definition associates a set of variables with the values produced by
|
||||
an expression.
|
||||
|
||||
Example:
|
||||
|
||||
>>> from .base import iadd_cout, iconst
|
||||
>>> x = Var('x')
|
||||
>>> y = Var('y')
|
||||
>>> x << iconst(4)
|
||||
(Var(x),) << Apply(iconst, (4,))
|
||||
>>> (x, y) << iadd_cout(4, 5)
|
||||
(Var(x), Var(y)) << Apply(iadd_cout, (4, 5))
|
||||
|
||||
The `<<` operator is used to create variable definitions.
|
||||
|
||||
:param defs: Single variable or tuple of variables to be defined.
|
||||
:param expr: Expression generating the values.
|
||||
"""
|
||||
|
||||
def __init__(self, defs, expr):
|
||||
if not isinstance(defs, tuple):
|
||||
defs = (defs,)
|
||||
assert isinstance(expr, Expr)
|
||||
self.defs = defs
|
||||
self.expr = expr
|
||||
|
||||
def __repr__(self):
|
||||
return "{} << {!r}".format(self.defs, self.expr)
|
||||
|
||||
def __str__(self):
|
||||
if len(self.defs) == 1:
|
||||
return "{!s} << {!s}".format(self.defs[0], self.expr)
|
||||
else:
|
||||
return "({}) << {!s}".format(", ".join(self.defs), self.expr)
|
||||
|
||||
|
||||
class Expr(object):
|
||||
"""
|
||||
An AST expression.
|
||||
"""
|
||||
|
||||
def __rlshift__(self, other):
|
||||
"""
|
||||
Define variables using `var << expr` or `(v1, v2) << expr`.
|
||||
"""
|
||||
return Def(other, self)
|
||||
|
||||
|
||||
class Var(Expr):
|
||||
"""
|
||||
A free variable.
|
||||
"""
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
# Bitmask of contexts where this variable is defined.
|
||||
# See XForm._rewrite_defs().
|
||||
self.defctx = 0
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def __repr__(self):
|
||||
s = self.name
|
||||
if self.defctx:
|
||||
s += ", d={:02b}".format(self.defctx)
|
||||
return "Var({})".format(s)
|
||||
|
||||
|
||||
class Apply(Expr):
|
||||
"""
|
||||
Apply an instruction to arguments.
|
||||
|
||||
An `Apply` AST expression is created by using function call syntax on
|
||||
instructions. This applies to both bound and unbound polymorphic
|
||||
instructions:
|
||||
|
||||
>>> from .base import jump, iadd
|
||||
>>> jump('next', ())
|
||||
Apply(jump, ('next', ()))
|
||||
>>> iadd.i32('x', 'y')
|
||||
Apply(iadd.i32, ('x', 'y'))
|
||||
|
||||
:param inst: The instruction being applied, an `Instruction` or
|
||||
`BoundInstruction` instance.
|
||||
:param args: Tuple of arguments.
|
||||
"""
|
||||
|
||||
def __init__(self, inst, args):
|
||||
from . import BoundInstruction
|
||||
if isinstance(inst, BoundInstruction):
|
||||
self.inst = inst.inst
|
||||
self.typevars = inst.typevars
|
||||
else:
|
||||
self.inst = inst
|
||||
self.typevars = ()
|
||||
self.args = args
|
||||
assert len(self.inst.ins) == len(args)
|
||||
|
||||
def instname(self):
|
||||
i = self.inst.name
|
||||
for t in self.typevars:
|
||||
i += '.{}'.format(t)
|
||||
return i
|
||||
|
||||
def __repr__(self):
|
||||
return "Apply({}, {})".format(self.instname(), self.args)
|
||||
|
||||
def __str__(self):
|
||||
args = ', '.join(map(str, self.args))
|
||||
return '{}({})'.format(self.instname(), args)
|
||||
Reference in New Issue
Block a user