compiler: make kernel_invariant an instance, not class, property.

Fixes #409.
This commit is contained in:
whitequark 2016-04-29 13:05:11 +00:00 committed by Sebastien Bourdeauducq
parent e835ae2a2a
commit 88fd5431b5
17 changed files with 100 additions and 18 deletions

View File

@ -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

View File

@ -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)

View File

@ -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 *

View File

@ -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 *

View File

@ -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 *

View File

@ -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 *

View File

@ -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 *

View File

@ -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 *

View File

@ -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 *

View File

@ -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 *

View File

@ -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 *

View File

@ -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 *

View File

@ -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 *

View File

@ -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 *

View File

@ -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]

View File

@ -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]

View File

@ -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 *