forked from M-Labs/artiq
parent
348e058c6f
commit
665e59e064
|
@ -1,2 +1,3 @@
|
||||||
|
from .constness import Constness
|
||||||
from .domination import DominatorTree
|
from .domination import DominatorTree
|
||||||
from .devirtualization import Devirtualization
|
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__),
|
instance_type = types.TInstance("{}.{}".format(typ.__module__, typ.__qualname__),
|
||||||
OrderedDict())
|
OrderedDict())
|
||||||
instance_type.attributes['__objectid__'] = builtins.TInt32()
|
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 = types.TConstructor(instance_type)
|
||||||
constructor_type.attributes['__objectid__'] = builtins.TInt32()
|
constructor_type.attributes['__objectid__'] = builtins.TInt32()
|
||||||
|
|
|
@ -56,6 +56,7 @@ class Module:
|
||||||
escape_validator = validators.EscapeValidator(engine=self.engine)
|
escape_validator = validators.EscapeValidator(engine=self.engine)
|
||||||
iodelay_estimator = transforms.IODelayEstimator(engine=self.engine,
|
iodelay_estimator = transforms.IODelayEstimator(engine=self.engine,
|
||||||
ref_period=ref_period)
|
ref_period=ref_period)
|
||||||
|
constness = analyses.Constness(engine=self.engine)
|
||||||
artiq_ir_generator = transforms.ARTIQIRGenerator(engine=self.engine,
|
artiq_ir_generator = transforms.ARTIQIRGenerator(engine=self.engine,
|
||||||
module_name=src.name,
|
module_name=src.name,
|
||||||
ref_period=ref_period)
|
ref_period=ref_period)
|
||||||
|
@ -71,6 +72,7 @@ class Module:
|
||||||
monomorphism_validator.visit(src.typedtree)
|
monomorphism_validator.visit(src.typedtree)
|
||||||
escape_validator.visit(src.typedtree)
|
escape_validator.visit(src.typedtree)
|
||||||
iodelay_estimator.visit_fixpoint(src.typedtree)
|
iodelay_estimator.visit_fixpoint(src.typedtree)
|
||||||
|
constness.visit(src.typedtree)
|
||||||
devirtualization.visit(src.typedtree)
|
devirtualization.visit(src.typedtree)
|
||||||
self.artiq_ir = artiq_ir_generator.visit(src.typedtree)
|
self.artiq_ir = artiq_ir_generator.visit(src.typedtree)
|
||||||
artiq_ir_generator.annotate_calls(devirtualization)
|
artiq_ir_generator.annotate_calls(devirtualization)
|
||||||
|
|
|
@ -443,6 +443,7 @@ class TInstance(TMono):
|
||||||
assert isinstance(attributes, OrderedDict)
|
assert isinstance(attributes, OrderedDict)
|
||||||
super().__init__(name)
|
super().__init__(name)
|
||||||
self.attributes = attributes
|
self.attributes = attributes
|
||||||
|
self.constant_attributes = set()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "artiq.compiler.types.TInstance({}, {})".format(
|
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