forked from M-Labs/artiq
compiler: make kernel_invariant an instance, not class, property.
Fixes #409.
This commit is contained in:
parent
79c7c2dd45
commit
f7d83e9bdf
|
@ -55,6 +55,7 @@ class ASTSynthesizer:
|
||||||
self.object_map, self.type_map, self.value_map = object_map, type_map, value_map
|
self.object_map, self.type_map, self.value_map = object_map, type_map, value_map
|
||||||
self.quote_function = quote_function
|
self.quote_function = quote_function
|
||||||
self.expanded_from = expanded_from
|
self.expanded_from = expanded_from
|
||||||
|
self.diagnostics = []
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
self.source_buffer.source = self.source
|
self.source_buffer.source = self.source
|
||||||
|
@ -124,6 +125,35 @@ class ASTSynthesizer:
|
||||||
|
|
||||||
if typ in self.type_map:
|
if typ in self.type_map:
|
||||||
instance_type, constructor_type = self.type_map[typ]
|
instance_type, constructor_type = self.type_map[typ]
|
||||||
|
|
||||||
|
if hasattr(value, 'kernel_invariants') and \
|
||||||
|
value.kernel_invariants != instance_type.constant_attributes:
|
||||||
|
attr_diff = value.kernel_invariants.difference(
|
||||||
|
instance_type.constant_attributes)
|
||||||
|
if len(attr_diff) > 0:
|
||||||
|
diag = diagnostic.Diagnostic("warning",
|
||||||
|
"object {value} of type {typ} declares attribute(s) {attrs} as "
|
||||||
|
"kernel invariant, but other objects of the same type do not; "
|
||||||
|
"the invariant annotation on this object will be ignored",
|
||||||
|
{"value": repr(value),
|
||||||
|
"typ": types.TypePrinter().name(instance_type, max_depth=0),
|
||||||
|
"attrs": ", ".join(["'{}'".format(attr) for attr in attr_diff])},
|
||||||
|
loc)
|
||||||
|
self.diagnostics.append(diag)
|
||||||
|
attr_diff = instance_type.constant_attributes.difference(
|
||||||
|
value.kernel_invariants)
|
||||||
|
if len(attr_diff) > 0:
|
||||||
|
diag = diagnostic.Diagnostic("warning",
|
||||||
|
"object {value} of type {typ} does not declare attribute(s) {attrs} as "
|
||||||
|
"kernel invariant, but other objects of the same type do; "
|
||||||
|
"the invariant annotation on other objects will be ignored",
|
||||||
|
{"value": repr(value),
|
||||||
|
"typ": types.TypePrinter().name(instance_type, max_depth=0),
|
||||||
|
"attrs": ", ".join(["'{}'".format(attr) for attr in attr_diff])},
|
||||||
|
loc)
|
||||||
|
self.diagnostics.append(diag)
|
||||||
|
value.kernel_invariants = value.kernel_invariants.intersection(
|
||||||
|
instance_type.constant_attributes)
|
||||||
else:
|
else:
|
||||||
if issubclass(typ, BaseException):
|
if issubclass(typ, BaseException):
|
||||||
if hasattr(typ, 'artiq_builtin'):
|
if hasattr(typ, 'artiq_builtin'):
|
||||||
|
@ -138,16 +168,16 @@ 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_invariants'):
|
|
||||||
assert isinstance(typ.kernel_invariants, set)
|
|
||||||
instance_type.constant_attributes = typ.kernel_invariants
|
|
||||||
|
|
||||||
constructor_type = types.TConstructor(instance_type)
|
constructor_type = types.TConstructor(instance_type)
|
||||||
constructor_type.attributes['__objectid__'] = builtins.TInt32()
|
constructor_type.attributes['__objectid__'] = builtins.TInt32()
|
||||||
instance_type.constructor = constructor_type
|
instance_type.constructor = constructor_type
|
||||||
|
|
||||||
self.type_map[typ] = instance_type, constructor_type
|
self.type_map[typ] = instance_type, constructor_type
|
||||||
|
|
||||||
|
if hasattr(value, 'kernel_invariants'):
|
||||||
|
assert isinstance(value.kernel_invariants, set)
|
||||||
|
instance_type.constant_attributes = value.kernel_invariants
|
||||||
|
|
||||||
if isinstance(value, type):
|
if isinstance(value, type):
|
||||||
self.value_map[constructor_type].append((value, loc))
|
self.value_map[constructor_type].append((value, loc))
|
||||||
return asttyped.QuoteT(value=value, type=constructor_type,
|
return asttyped.QuoteT(value=value, type=constructor_type,
|
||||||
|
@ -801,4 +831,7 @@ class Stitcher:
|
||||||
synthesizer = self._synthesizer(loc)
|
synthesizer = self._synthesizer(loc)
|
||||||
node = synthesizer.quote(value)
|
node = synthesizer.quote(value)
|
||||||
synthesizer.finalize()
|
synthesizer.finalize()
|
||||||
|
if len(synthesizer.diagnostics) > 0:
|
||||||
|
for warning in synthesizer.diagnostics:
|
||||||
|
self.engine.process(warning)
|
||||||
return node
|
return node
|
||||||
|
|
|
@ -3,8 +3,14 @@ import sys, os
|
||||||
from artiq.master.databases import DeviceDB
|
from artiq.master.databases import DeviceDB
|
||||||
from artiq.master.worker_db import DeviceManager
|
from artiq.master.worker_db import DeviceManager
|
||||||
|
|
||||||
|
import artiq.coredevice.core
|
||||||
from artiq.coredevice.core import Core, CompileError
|
from artiq.coredevice.core import Core, CompileError
|
||||||
|
|
||||||
|
def _render_diagnostic(diagnostic, colored):
|
||||||
|
return "\n".join(diagnostic.render(only_line=True))
|
||||||
|
|
||||||
|
artiq.coredevice.core._render_diagnostic = _render_diagnostic
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv) > 1 and sys.argv[1] == "+diag":
|
if len(sys.argv) > 1 and sys.argv[1] == "+diag":
|
||||||
del sys.argv[1]
|
del sys.argv[1]
|
||||||
|
@ -35,7 +41,6 @@ def main():
|
||||||
print(core.comm.get_log())
|
print(core.comm.get_log())
|
||||||
core.comm.clear_log()
|
core.comm.clear_log()
|
||||||
except CompileError as error:
|
except CompileError as error:
|
||||||
print("\n".join(error.__cause__.diagnostic.render(only_line=True)))
|
|
||||||
if not diag:
|
if not diag:
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s >%t
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
# RUN: OutputCheck %s --file-to-check=%t
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
from artiq.language.core import *
|
from artiq.language.core import *
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s >%t
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
# RUN: OutputCheck %s --file-to-check=%t
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
from artiq.language.core import *
|
from artiq.language.core import *
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s >%t
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
# RUN: OutputCheck %s --file-to-check=%t
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
from artiq.language.core import *
|
from artiq.language.core import *
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s >%t
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
# RUN: OutputCheck %s --file-to-check=%t
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
from artiq.language.core import *
|
from artiq.language.core import *
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s >%t
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
# RUN: OutputCheck %s --file-to-check=%t
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
from artiq.language.core import *
|
from artiq.language.core import *
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s >%t
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
# RUN: OutputCheck %s --file-to-check=%t
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
from artiq.language.core import *
|
from artiq.language.core import *
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s >%t
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
# RUN: OutputCheck %s --file-to-check=%t
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
from artiq.language.core import *
|
from artiq.language.core import *
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s >%t
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
# RUN: OutputCheck %s --file-to-check=%t
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
from artiq.language.core import *
|
from artiq.language.core import *
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s >%t
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
# RUN: OutputCheck %s --file-to-check=%t
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
from artiq.language.core import *
|
from artiq.language.core import *
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s >%t
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
# RUN: OutputCheck %s --file-to-check=%t
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
from artiq.language.core import *
|
from artiq.language.core import *
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s >%t
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
# RUN: OutputCheck %s --file-to-check=%t
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
from artiq.language.core import *
|
from artiq.language.core import *
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s >%t
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
# RUN: OutputCheck %s --file-to-check=%t
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
from artiq.language.core import *
|
from artiq.language.core import *
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
|
from artiq.language.core import *
|
||||||
|
from artiq.language.types import *
|
||||||
|
|
||||||
|
class c:
|
||||||
|
a = b = 0
|
||||||
|
def __init__(self, invariants):
|
||||||
|
self.kernel_invariants = invariants
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<testbench.c object>"
|
||||||
|
|
||||||
|
i1 = c({'a'})
|
||||||
|
i2 = c({'a', 'b'})
|
||||||
|
|
||||||
|
@kernel
|
||||||
|
def entrypoint():
|
||||||
|
# CHECK-L: <synthesized>:1: warning: object <testbench.c object> of type <instance testbench.c> declares attribute(s) 'b' as kernel invariant, but other objects of the same type do not; the invariant annotation on this object will be ignored
|
||||||
|
# CHECK-L: ${LINE:+1}: note: expanded from here
|
||||||
|
[i1, i2]
|
|
@ -0,0 +1,22 @@
|
||||||
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
|
from artiq.language.core import *
|
||||||
|
from artiq.language.types import *
|
||||||
|
|
||||||
|
class c:
|
||||||
|
a = b = 0
|
||||||
|
def __init__(self, invariants):
|
||||||
|
self.kernel_invariants = invariants
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<testbench.c object>"
|
||||||
|
|
||||||
|
i1 = c({'a', 'b'})
|
||||||
|
i2 = c({'a'})
|
||||||
|
|
||||||
|
@kernel
|
||||||
|
def entrypoint():
|
||||||
|
# CHECK-L: <synthesized>:1: warning: object <testbench.c object> of type <instance testbench.c> does not declare attribute(s) 'b' as kernel invariant, but other objects of the same type do; the invariant annotation on other objects will be ignored
|
||||||
|
# CHECK-L: ${LINE:+1}: note: expanded from here
|
||||||
|
[i1, i2]
|
|
@ -1,4 +1,4 @@
|
||||||
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s >%t
|
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
|
||||||
# RUN: OutputCheck %s --file-to-check=%t
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
from artiq.experiment import *
|
from artiq.experiment import *
|
||||||
|
|
Loading…
Reference in New Issue