Skip to content

Commit 2678bb0

Browse files
author
whitequark
committedJul 7, 2016
embedding: reimplement 373578b properly.
The core of the problem that 373578b was attempting to solve is that diagnostics sometimes should be chained; one way of chaining is the loc.expanded_from feature, which handles macro-like expansion, but another is providing context. Before this commit, context was provided using an ad-hoc override of a diagnostic engine, which did not work in cases where diagnostic engine was not threaded through the call stack. This commit uses the newly added pythonparser context feature to elegantly handle the problem.
1 parent 6a1706b commit 2678bb0

File tree

2 files changed

+48
-43
lines changed

2 files changed

+48
-43
lines changed
 

Diff for: ‎artiq/compiler/embedding.py

+29-43
Original file line numberDiff line numberDiff line change
@@ -425,24 +425,18 @@ def _compute_value_type(self, object_value, object_type, object_loc, attr_name,
425425
attr_value_type = builtins.TList(builtins.TInt64())
426426

427427
if attr_value_type is None:
428-
# Slow path. We don't know what exactly is the attribute value,
429-
# so we quote it only for the error message that may possibly result.
430-
ast = self.quote(attr_value, object_loc.loc)
431-
432-
def proxy_diagnostic(diag):
433-
note = diagnostic.Diagnostic("note",
434-
"while inferring a type for an attribute '{attr}' of a host object",
435-
{"attr": attr_name},
436-
loc)
437-
diag.notes.append(note)
438-
439-
self.engine.process(diag)
428+
note = diagnostic.Diagnostic("note",
429+
"while inferring a type for an attribute '{attr}' of a host object",
430+
{"attr": attr_name},
431+
loc)
440432

441-
proxy_engine = diagnostic.Engine()
442-
proxy_engine.process = proxy_diagnostic
443-
Inferencer(engine=proxy_engine).visit(ast)
444-
IntMonomorphizer(engine=proxy_engine).visit(ast)
445-
attr_value_type = ast.type
433+
with self.engine.context(note):
434+
# Slow path. We don't know what exactly is the attribute value,
435+
# so we quote it only for the error message that may possibly result.
436+
ast = self.quote(attr_value, object_loc.expanded_from)
437+
Inferencer(engine=self.engine).visit(ast)
438+
IntMonomorphizer(engine=self.engine).visit(ast)
439+
attr_value_type = ast.type
446440

447441
return attributes, attr_value_type
448442

@@ -716,32 +710,24 @@ def _type_of_param(self, function, loc, param, is_syscall):
716710
notes=self._call_site_note(loc, is_syscall))
717711
self.engine.process(diag)
718712
elif param.default is not inspect.Parameter.empty:
719-
# Try and infer the type from the default value.
720-
# This is tricky, because the default value might not have
721-
# a well-defined type in APython.
722-
# In this case, we bail out, but mention why we do it.
723-
ast = self._quote(param.default, None)
724-
725-
def proxy_diagnostic(diag):
726-
note = diagnostic.Diagnostic("note",
727-
"expanded from here while trying to infer a type for an"
728-
" unannotated optional argument '{argument}' from its default value",
729-
{"argument": param.name},
730-
self._function_loc(function))
731-
diag.notes.append(note)
732-
733-
note = self._call_site_note(loc, is_syscall)
734-
if note:
735-
diag.notes += note
736-
737-
self.engine.process(diag)
738-
739-
proxy_engine = diagnostic.Engine()
740-
proxy_engine.process = proxy_diagnostic
741-
Inferencer(engine=proxy_engine).visit(ast)
742-
IntMonomorphizer(engine=proxy_engine).visit(ast)
743-
744-
return ast.type
713+
notes = []
714+
notes.append(diagnostic.Diagnostic("note",
715+
"expanded from here while trying to infer a type for an"
716+
" unannotated optional argument '{argument}' from its default value",
717+
{"argument": param.name},
718+
self._function_loc(function)))
719+
if loc is not None:
720+
notes.append(self._call_site_note(loc, is_syscall))
721+
722+
with self.engine.context(*notes):
723+
# Try and infer the type from the default value.
724+
# This is tricky, because the default value might not have
725+
# a well-defined type in APython.
726+
# In this case, we bail out, but mention why we do it.
727+
ast = self._quote(param.default, None)
728+
Inferencer(engine=self.engine).visit(ast)
729+
IntMonomorphizer(engine=self.engine).visit(ast)
730+
return ast.type
745731
else:
746732
# Let the rest of the program decide.
747733
return types.TVar()

Diff for: ‎artiq/test/lit/embedding/error_host_only.py

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# RUN: %python -m artiq.compiler.testbench.embedding +diag %s 2>%t
2+
# RUN: OutputCheck %s --file-to-check=%t
3+
4+
from artiq.language.core import *
5+
from artiq.language.types import *
6+
7+
class foo:
8+
# CHECK-L: ${LINE:+2}: fatal: this function cannot be called as an RPC
9+
@host_only
10+
def pause(self):
11+
pass
12+
13+
x = foo()
14+
15+
@kernel
16+
def entrypoint():
17+
# CHECK-L: ${LINE:+2}: note: in function called remotely here
18+
# CHECK-L: ${LINE:+1}: note: while inferring a type for an attribute 'pause' of a host object
19+
x.pause()

0 commit comments

Comments
 (0)
Please sign in to comment.