Allow dot syntax notation for enumerated immediate operands.
The meta language patterns sometimes need to refer to specific values of enumerated immediate operands. The dot syntax provides a namespaced, typed way of doing that: icmp(intcc.ult, a, x). Add an ast.Enumerator class for representing this kind of AST leaf node. Add value definitions for the intcc and floatcc immediate operand kinds.
This commit is contained in:
@@ -9,7 +9,9 @@ from . import instructions
|
||||
from .typevar import TypeVar
|
||||
|
||||
try:
|
||||
from typing import Union, Tuple, Sequence # noqa
|
||||
from typing import Union, Tuple, Sequence, TYPE_CHECKING # noqa
|
||||
if TYPE_CHECKING:
|
||||
from .operands import ImmediateKind # noqa
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
@@ -404,3 +406,35 @@ class Apply(Expr):
|
||||
args = defs[0].rust_type() + ', ' + args
|
||||
method = self.inst.snake_name()
|
||||
return '{}({})'.format(method, args)
|
||||
|
||||
|
||||
class Enumerator(Expr):
|
||||
"""
|
||||
A value of an enumerated immediate operand.
|
||||
|
||||
Some immediate operand kinds like `intcc` and `floatcc` have an enumerated
|
||||
range of values corresponding to a Rust enum type. An `Enumerator` object
|
||||
is an AST leaf node representing one of the values.
|
||||
|
||||
:param kind: The enumerated `ImmediateKind` containing the value.
|
||||
:param value: The textual IL representation of the value.
|
||||
|
||||
`Enumerator` nodes are not usually created directly. They are created by
|
||||
using the dot syntax on immediate kinds: `intcc.ult`.
|
||||
"""
|
||||
|
||||
def __init__(self, kind, value):
|
||||
# type: (ImmediateKind, str) -> None
|
||||
self.kind = kind
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
# type: () -> str
|
||||
"""
|
||||
Get the Rust expression form of this enumerator.
|
||||
"""
|
||||
return self.kind.rust_enumerator(self.value)
|
||||
|
||||
def __repr__(self):
|
||||
# type: () -> str
|
||||
return '{}.{}'.format(self.kind, self.value)
|
||||
|
||||
@@ -5,8 +5,10 @@ from .types import ValueType
|
||||
from .typevar import TypeVar
|
||||
|
||||
try:
|
||||
from typing import Union
|
||||
from typing import Union, Dict, TYPE_CHECKING # noqa
|
||||
OperandSpec = Union['OperandKind', ValueType, TypeVar]
|
||||
if TYPE_CHECKING:
|
||||
from .ast import Enumerator # noqa
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
@@ -74,15 +76,44 @@ class ImmediateKind(OperandKind):
|
||||
`InstructionData` data structure.
|
||||
"""
|
||||
|
||||
def __init__(self, name, doc, default_member='imm', rust_type=None):
|
||||
# type: (str, str, str, str) -> None
|
||||
def __init__(
|
||||
self, name, doc,
|
||||
default_member='imm',
|
||||
rust_type=None,
|
||||
values=None):
|
||||
# type: (str, str, str, str, Dict[str, str]) -> None
|
||||
super(ImmediateKind, self).__init__(
|
||||
name, doc, default_member, rust_type)
|
||||
self.values = values
|
||||
|
||||
def __repr__(self):
|
||||
# type: () -> str
|
||||
return 'ImmediateKind({})'.format(self.name)
|
||||
|
||||
def __getattr__(self, value):
|
||||
# type: (str) -> Enumerator
|
||||
"""
|
||||
Enumerated immediate kinds allow the use of dot syntax to produce
|
||||
`Enumerator` AST nodes: `icmp.i32(intcc.ult, a, b)`.
|
||||
"""
|
||||
from .ast import Enumerator # noqa
|
||||
if not self.values:
|
||||
raise AssertionError(
|
||||
'{n} is not an enumerated operand kind: {n}.{a}'.format(
|
||||
n=self.name, a=value))
|
||||
if value not in self.values:
|
||||
raise AssertionError(
|
||||
'No such {n} enumerator: {n}.{a}'.format(
|
||||
n=self.name, a=value))
|
||||
return Enumerator(self, value)
|
||||
|
||||
def rust_enumerator(self, value):
|
||||
# type: (str) -> str
|
||||
"""
|
||||
Get the qualified Rust name of the enumerator value `value`.
|
||||
"""
|
||||
return '{}::{}'.format(self.rust_type, self.values[value])
|
||||
|
||||
|
||||
# Instances of entity reference operand types are provided in the
|
||||
# `cretonne.entities` module.
|
||||
|
||||
Reference in New Issue
Block a user