Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 434ad67268eb
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: f7d83e9bdf03
Choose a head ref
  • 2 commits
  • 18 files changed
  • 1 contributor

Commits on Apr 29, 2016

  1. doc: explain RPC return type annotations.

    Fixes #410.
    whitequark committed Apr 29, 2016
    Copy the full SHA
    79c7c2d View commit details
  2. compiler: make kernel_invariant an instance, not class, property.

    Fixes #409.
    whitequark committed Apr 29, 2016
    Copy the full SHA
    f7d83e9 View commit details
41 changes: 37 additions & 4 deletions artiq/compiler/embedding.py
Original file line number Diff line number Diff line change
@@ -55,6 +55,7 @@ def __init__(self, object_map, type_map, value_map, quote_function=None, expande
self.object_map, self.type_map, self.value_map = object_map, type_map, value_map
self.quote_function = quote_function
self.expanded_from = expanded_from
self.diagnostics = []

def finalize(self):
self.source_buffer.source = self.source
@@ -124,6 +125,35 @@ def quote(self, value):

if typ in self.type_map:
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:
if issubclass(typ, BaseException):
if hasattr(typ, 'artiq_builtin'):
@@ -138,16 +168,16 @@ def quote(self, value):
instance_type = types.TInstance("{}.{}".format(typ.__module__, typ.__qualname__),
OrderedDict())
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.attributes['__objectid__'] = builtins.TInt32()
instance_type.constructor = 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):
self.value_map[constructor_type].append((value, loc))
return asttyped.QuoteT(value=value, type=constructor_type,
@@ -801,4 +831,7 @@ def _quote(self, value, loc):
synthesizer = self._synthesizer(loc)
node = synthesizer.quote(value)
synthesizer.finalize()
if len(synthesizer.diagnostics) > 0:
for warning in synthesizer.diagnostics:
self.engine.process(warning)
return node
7 changes: 6 additions & 1 deletion artiq/compiler/testbench/embedding.py
Original file line number Diff line number Diff line change
@@ -3,8 +3,14 @@
from artiq.master.databases import DeviceDB
from artiq.master.worker_db import DeviceManager

import artiq.coredevice.core
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():
if len(sys.argv) > 1 and sys.argv[1] == "+diag":
del sys.argv[1]
@@ -35,7 +41,6 @@ def main():
print(core.comm.get_log())
core.comm.clear_log()
except CompileError as error:
print("\n".join(error.__cause__.diagnostic.render(only_line=True)))
if not diag:
exit(1)

2 changes: 1 addition & 1 deletion artiq/test/lit/embedding/error_attr_absent.py
Original file line number Diff line number Diff line change
@@ -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

from artiq.language.core import *
2 changes: 1 addition & 1 deletion artiq/test/lit/embedding/error_attr_absent_suggest.py
Original file line number Diff line number Diff line change
@@ -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

from artiq.language.core import *
2 changes: 1 addition & 1 deletion artiq/test/lit/embedding/error_attr_conflict.py
Original file line number Diff line number Diff line change
@@ -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

from artiq.language.core import *
2 changes: 1 addition & 1 deletion artiq/test/lit/embedding/error_attr_constant.py
Original file line number Diff line number Diff line change
@@ -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

from artiq.language.core import *
2 changes: 1 addition & 1 deletion artiq/test/lit/embedding/error_attr_unify.py
Original file line number Diff line number Diff line change
@@ -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

from artiq.language.core import *
2 changes: 1 addition & 1 deletion artiq/test/lit/embedding/error_name_absent_suggest.py
Original file line number Diff line number Diff line change
@@ -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

from artiq.language.core import *
2 changes: 1 addition & 1 deletion artiq/test/lit/embedding/error_rpc_annot_return.py
Original file line number Diff line number Diff line change
@@ -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

from artiq.language.core import *
2 changes: 1 addition & 1 deletion artiq/test/lit/embedding/error_syscall_annot.py
Original file line number Diff line number Diff line change
@@ -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

from artiq.language.core import *
2 changes: 1 addition & 1 deletion artiq/test/lit/embedding/error_syscall_annot_return.py
Original file line number Diff line number Diff line change
@@ -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

from artiq.language.core import *
2 changes: 1 addition & 1 deletion artiq/test/lit/embedding/error_syscall_arg.py
Original file line number Diff line number Diff line change
@@ -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

from artiq.language.core import *
2 changes: 1 addition & 1 deletion artiq/test/lit/embedding/error_syscall_default_arg.py
Original file line number Diff line number Diff line change
@@ -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

from artiq.language.core import *
2 changes: 1 addition & 1 deletion artiq/test/lit/embedding/error_syscall_return.py
Original file line number Diff line number Diff line change
@@ -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

from artiq.language.core import *
22 changes: 22 additions & 0 deletions artiq/test/lit/embedding/warning_invariant_1.py
Original file line number Diff line number Diff line change
@@ -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]
22 changes: 22 additions & 0 deletions artiq/test/lit/embedding/warning_invariant_2.py
Original file line number Diff line number Diff line change
@@ -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]
2 changes: 1 addition & 1 deletion artiq/test/lit/escape/error_mutable_attr.py
Original file line number Diff line number Diff line change
@@ -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

from artiq.experiment import *
28 changes: 28 additions & 0 deletions doc/manual/compiler.rst
Original file line number Diff line number Diff line change
@@ -16,6 +16,34 @@ A number of Python features can be used inside a kernel for compilation and exec

For a demonstration of some of these features, see the ``mandelbrot.py`` example.

Remote procedure calls
----------------------

Kernel code can call host functions without any additional ceremony. However, such functions are assumed to return `None`, and if a value other than `None` is returned, an exception is raised. To call a host function returning a value other than `None` its return type must be annotated using the standard Python syntax, e.g.: ::

def return_four() -> TInt32:
return 4

The Python types correspond to ARTIQ type annotations as follows:

+-------------+-------------------------+
| Python | ARTIQ |
+=============+=========================+
| NoneType | TNone |
+-------------+-------------------------+
| bool | TBool |
+-------------+-------------------------+
| int | TInt32, TInt64 |
+-------------+-------------------------+
| float | TFloat |
+-------------+-------------------------+
| str | TStr |
+-------------+-------------------------+
| list of T | TList(T) |
+-------------+-------------------------+
| range | TRange32, TRange64 |
+-------------+-------------------------+

Additional optimizations
------------------------