forked from M-Labs/artiq
parent
348e058c6f
commit
665e59e064
|
@ -1,2 +1,3 @@
|
|||
from .constness import Constness
|
||||
from .domination import DominatorTree
|
||||
from .devirtualization import Devirtualization
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
"""
|
||||
:class:`Constness` checks that no attribute marked
|
||||
as constant is ever set.
|
||||
"""
|
||||
|
||||
from pythonparser import algorithm, diagnostic
|
||||
from .. import types
|
||||
|
||||
class Constness(algorithm.Visitor):
|
||||
def __init__(self, engine):
|
||||
self.engine = engine
|
||||
self.in_assign = False
|
||||
|
||||
def visit_Assign(self, node):
|
||||
self.visit(node.value)
|
||||
self.in_assign = True
|
||||
self.visit(node.targets)
|
||||
self.in_assign = False
|
||||
|
||||
def visit_AttributeT(self, node):
|
||||
self.generic_visit(node)
|
||||
if self.in_assign:
|
||||
typ = node.value.type.find()
|
||||
if types.is_instance(typ) and node.attr in typ.constant_attributes:
|
||||
diag = diagnostic.Diagnostic("error",
|
||||
"cannot assign to constant attribute '{attr}' of class '{class}'",
|
||||
{"attr": node.attr, "class": typ.name},
|
||||
node.loc)
|
||||
self.engine.process(diag)
|
||||
return
|
|
@ -137,6 +137,9 @@ class ASTSynthesizer:
|
|||
instance_type = types.TInstance("{}.{}".format(typ.__module__, typ.__qualname__),
|
||||
OrderedDict())
|
||||
instance_type.attributes['__objectid__'] = builtins.TInt32()
|
||||
if hasattr(typ, 'kernel_constant_attributes'):
|
||||
assert isinstance(typ.kernel_constant_attributes, set)
|
||||
instance_type.constant_attributes = typ.kernel_constant_attributes
|
||||
|
||||
constructor_type = types.TConstructor(instance_type)
|
||||
constructor_type.attributes['__objectid__'] = builtins.TInt32()
|
||||
|
|
|
@ -56,6 +56,7 @@ class Module:
|
|||
escape_validator = validators.EscapeValidator(engine=self.engine)
|
||||
iodelay_estimator = transforms.IODelayEstimator(engine=self.engine,
|
||||
ref_period=ref_period)
|
||||
constness = analyses.Constness(engine=self.engine)
|
||||
artiq_ir_generator = transforms.ARTIQIRGenerator(engine=self.engine,
|
||||
module_name=src.name,
|
||||
ref_period=ref_period)
|
||||
|
@ -71,6 +72,7 @@ class Module:
|
|||
monomorphism_validator.visit(src.typedtree)
|
||||
escape_validator.visit(src.typedtree)
|
||||
iodelay_estimator.visit_fixpoint(src.typedtree)
|
||||
constness.visit(src.typedtree)
|
||||
devirtualization.visit(src.typedtree)
|
||||
self.artiq_ir = artiq_ir_generator.visit(src.typedtree)
|
||||
artiq_ir_generator.annotate_calls(devirtualization)
|
||||
|
|
|
@ -443,6 +443,7 @@ class TInstance(TMono):
|
|||
assert isinstance(attributes, OrderedDict)
|
||||
super().__init__(name)
|
||||
self.attributes = attributes
|
||||
self.constant_attributes = set()
|
||||
|
||||
def __repr__(self):
|
||||
return "artiq.compiler.types.TInstance({}, {})".format(
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s >%t
|
||||
# RUN: OutputCheck %s --file-to-check=%t
|
||||
|
||||
from artiq.language.core import *
|
||||
from artiq.language.types import *
|
||||
|
||||
class c:
|
||||
kernel_constant_attributes = {'a'}
|
||||
|
||||
def __init__(self):
|
||||
self.a = 1
|
||||
|
||||
i = c()
|
||||
|
||||
@kernel
|
||||
def entrypoint():
|
||||
# CHECK-L: ${LINE:+1}: error: cannot assign to constant attribute 'a' of class 'testbench.c'
|
||||
i.a = 1
|
Loading…
Reference in New Issue