forked from M-Labs/artiq
embedding: reimplement 373578bc
properly.
The core of the problem that 373578bc
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.
This commit is contained in:
parent
373578bc02
commit
5a79fcf9ba
|
@ -556,24 +556,18 @@ class StitchingInferencer(Inferencer):
|
||||||
attr_value_type = builtins.TList(builtins.TInt64())
|
attr_value_type = builtins.TList(builtins.TInt64())
|
||||||
|
|
||||||
if attr_value_type is None:
|
if attr_value_type is None:
|
||||||
# Slow path. We don't know what exactly is the attribute value,
|
note = diagnostic.Diagnostic("note",
|
||||||
# so we quote it only for the error message that may possibly result.
|
"while inferring a type for an attribute '{attr}' of a host object",
|
||||||
ast = self.quote(attr_value, loc)
|
{"attr": attr_name},
|
||||||
|
loc)
|
||||||
|
|
||||||
def proxy_diagnostic(diag):
|
with self.engine.context(note):
|
||||||
note = diagnostic.Diagnostic("note",
|
# Slow path. We don't know what exactly is the attribute value,
|
||||||
"while inferring a type for an attribute '{attr}' of a host object",
|
# so we quote it only for the error message that may possibly result.
|
||||||
{"attr": attr_name},
|
ast = self.quote(attr_value, object_loc.expanded_from)
|
||||||
loc)
|
Inferencer(engine=self.engine).visit(ast)
|
||||||
diag.notes.append(note)
|
IntMonomorphizer(engine=self.engine).visit(ast)
|
||||||
|
attr_value_type = ast.type
|
||||||
self.engine.process(diag)
|
|
||||||
|
|
||||||
proxy_engine = diagnostic.Engine()
|
|
||||||
proxy_engine.process = proxy_diagnostic
|
|
||||||
Inferencer(engine=proxy_engine).visit(ast)
|
|
||||||
IntMonomorphizer(engine=proxy_engine).visit(ast)
|
|
||||||
attr_value_type = ast.type
|
|
||||||
|
|
||||||
return attributes, attr_value_type
|
return attributes, attr_value_type
|
||||||
|
|
||||||
|
@ -840,32 +834,24 @@ class Stitcher:
|
||||||
notes=self._call_site_note(loc, is_syscall))
|
notes=self._call_site_note(loc, is_syscall))
|
||||||
self.engine.process(diag)
|
self.engine.process(diag)
|
||||||
elif param.default is not inspect.Parameter.empty:
|
elif param.default is not inspect.Parameter.empty:
|
||||||
# Try and infer the type from the default value.
|
notes = []
|
||||||
# This is tricky, because the default value might not have
|
notes.append(diagnostic.Diagnostic("note",
|
||||||
# a well-defined type in APython.
|
"expanded from here while trying to infer a type for an"
|
||||||
# In this case, we bail out, but mention why we do it.
|
" unannotated optional argument '{argument}' from its default value",
|
||||||
ast = self._quote(param.default, None)
|
{"argument": param.name},
|
||||||
|
self._function_loc(function)))
|
||||||
|
if loc is not None:
|
||||||
|
notes.append(self._call_site_note(loc, is_syscall))
|
||||||
|
|
||||||
def proxy_diagnostic(diag):
|
with self.engine.context(*notes):
|
||||||
note = diagnostic.Diagnostic("note",
|
# Try and infer the type from the default value.
|
||||||
"expanded from here while trying to infer a type for an"
|
# This is tricky, because the default value might not have
|
||||||
" unannotated optional argument '{argument}' from its default value",
|
# a well-defined type in APython.
|
||||||
{"argument": param.name},
|
# In this case, we bail out, but mention why we do it.
|
||||||
self._function_loc(function))
|
ast = self._quote(param.default, None)
|
||||||
diag.notes.append(note)
|
Inferencer(engine=self.engine).visit(ast)
|
||||||
|
IntMonomorphizer(engine=self.engine).visit(ast)
|
||||||
note = self._call_site_note(loc, is_syscall)
|
return ast.type
|
||||||
if note:
|
|
||||||
diag.notes += note
|
|
||||||
|
|
||||||
self.engine.process(diag)
|
|
||||||
|
|
||||||
proxy_engine = diagnostic.Engine()
|
|
||||||
proxy_engine.process = proxy_diagnostic
|
|
||||||
Inferencer(engine=proxy_engine).visit(ast)
|
|
||||||
IntMonomorphizer(engine=proxy_engine).visit(ast)
|
|
||||||
|
|
||||||
return ast.type
|
|
||||||
else:
|
else:
|
||||||
# Let the rest of the program decide.
|
# Let the rest of the program decide.
|
||||||
return types.TVar()
|
return types.TVar()
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
# 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 foo:
|
||||||
|
# CHECK-L: ${LINE:+2}: fatal: this function cannot be called as an RPC
|
||||||
|
@host_only
|
||||||
|
def pause(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
x = foo()
|
||||||
|
|
||||||
|
@kernel
|
||||||
|
def entrypoint():
|
||||||
|
# CHECK-L: ${LINE:+2}: note: in function called remotely here
|
||||||
|
# CHECK-L: ${LINE:+1}: note: while inferring a type for an attribute 'pause' of a host object
|
||||||
|
x.pause()
|
Loading…
Reference in New Issue