forked from M-Labs/artiq
compiler: don't require exceptions to inherit ARTIQException.
This commit is contained in:
parent
f9e90d90fa
commit
8aa34ee952
|
@ -85,7 +85,6 @@ class TException(types.TMono):
|
|||
# * Message, which can contain substitutions {0}, {1} and {2} (str).
|
||||
# * Three 64-bit integers, parameterizing the message (int(width=64)).
|
||||
|
||||
|
||||
# Keep this in sync with the function ARTIQIRGenerator.alloc_exn.
|
||||
attributes = OrderedDict([
|
||||
("__name__", TStr()),
|
||||
|
@ -99,8 +98,9 @@ class TException(types.TMono):
|
|||
("__param2__", TInt(types.TValue(64))),
|
||||
])
|
||||
|
||||
def __init__(self, name="Exception"):
|
||||
def __init__(self, name="Exception", id=0):
|
||||
super().__init__(name)
|
||||
self.id = id
|
||||
|
||||
def fn_bool():
|
||||
return types.TConstructor(TBool())
|
||||
|
|
|
@ -42,10 +42,10 @@ class ObjectMap:
|
|||
self.forward_map.values()))
|
||||
|
||||
class ASTSynthesizer:
|
||||
def __init__(self, type_map, value_map, quote_function=None, expanded_from=None):
|
||||
def __init__(self, object_map, type_map, value_map, quote_function=None, expanded_from=None):
|
||||
self.source = ""
|
||||
self.source_buffer = source.Buffer(self.source, "<synthesized>")
|
||||
self.type_map, self.value_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.expanded_from = expanded_from
|
||||
|
||||
|
@ -119,14 +119,16 @@ class ASTSynthesizer:
|
|||
|
||||
if typ in self.type_map:
|
||||
instance_type, constructor_type = self.type_map[typ]
|
||||
else:
|
||||
if issubclass(typ, BaseException):
|
||||
instance_type = builtins.TException("{}.{}".format(typ.__module__, typ.__qualname__),
|
||||
id=self.object_map.store(typ))
|
||||
constructor_type = types.TExceptionConstructor(instance_type)
|
||||
else:
|
||||
instance_type = types.TInstance("{}.{}".format(typ.__module__, typ.__qualname__),
|
||||
OrderedDict())
|
||||
instance_type.attributes['__objectid__'] = builtins.TInt32()
|
||||
|
||||
if issubclass(typ, BaseException):
|
||||
constructor_type = types.TExceptionConstructor(instance_type)
|
||||
else:
|
||||
constructor_type = types.TConstructor(instance_type)
|
||||
constructor_type.attributes['__objectid__'] = builtins.TInt32()
|
||||
instance_type.constructor = constructor_type
|
||||
|
@ -522,6 +524,7 @@ class Stitcher:
|
|||
|
||||
def _synthesizer(self, expanded_from=None):
|
||||
return ASTSynthesizer(expanded_from=expanded_from,
|
||||
object_map=self.object_map,
|
||||
type_map=self.type_map,
|
||||
value_map=self.value_map,
|
||||
quote_function=self._quote_function)
|
||||
|
|
|
@ -999,7 +999,7 @@ class Inferencer(algorithm.Visitor):
|
|||
{"typeb": printer.name(typeb)},
|
||||
locb)
|
||||
]
|
||||
self._unify(node.name_type, builtins.TException(node.filter.type.name),
|
||||
self._unify(node.name_type, node.filter.type.instance,
|
||||
node.name_loc, node.filter.loc, makenotes)
|
||||
|
||||
def _type_from_arguments(self, node, ret):
|
||||
|
|
|
@ -1155,7 +1155,8 @@ class LLVMIRGenerator:
|
|||
self.llty_of_type(ir.TExceptionTypeInfo()), None)
|
||||
else:
|
||||
llclauseexnname = self.llconst_of_const(
|
||||
ir.Constant(typ.name, ir.TExceptionTypeInfo()))
|
||||
ir.Constant("{}:{}".format(typ.id, typ.name),
|
||||
ir.TExceptionTypeInfo()))
|
||||
lllandingpad.add_clause(ll.CatchClause(llclauseexnname))
|
||||
|
||||
if typ is None:
|
||||
|
|
|
@ -5,6 +5,7 @@ from enum import Enum
|
|||
from fractions import Fraction
|
||||
|
||||
from artiq.language import core as core_language
|
||||
from artiq.coredevice import exceptions
|
||||
from artiq import __version__ as software_version
|
||||
|
||||
|
||||
|
@ -447,26 +448,31 @@ class CommGeneric:
|
|||
self._write_bytes(return_tags)
|
||||
self._send_rpc_value(bytearray(return_tags), result, result, service)
|
||||
self._write_flush()
|
||||
except core_language.ARTIQException as exn:
|
||||
except Exception as exn:
|
||||
logger.debug("rpc service: %d %r ! %r", service_id, arguments, exn)
|
||||
|
||||
self._write_header(_H2DMsgType.RPC_EXCEPTION)
|
||||
|
||||
if hasattr(exn, 'artiq_exception'):
|
||||
exn = exn.artiq_exception
|
||||
self._write_string(exn.name)
|
||||
self._write_string(exn.message)
|
||||
for index in range(3):
|
||||
self._write_int64(exn.param[index])
|
||||
|
||||
self._write_string(exn.filename)
|
||||
self._write_int32(exn.line)
|
||||
self._write_int32(exn.column)
|
||||
self._write_string(exn.function)
|
||||
|
||||
self._write_flush()
|
||||
except Exception as exn:
|
||||
logger.debug("rpc service: %d %r ! %r", service_id, arguments, exn)
|
||||
|
||||
self._write_header(_H2DMsgType.RPC_EXCEPTION)
|
||||
self._write_string(type(exn).__name__)
|
||||
filename, line, column, function = exn.traceback[-1]
|
||||
self._write_string(filename)
|
||||
self._write_int32(line)
|
||||
self._write_int32(column)
|
||||
self._write_string(function)
|
||||
else:
|
||||
exn_type = type(exn)
|
||||
if exn_type in (ZeroDivisionError, ValueError, IndexError):
|
||||
self._write_string("0:{}".format(exn_type.__name__))
|
||||
else:
|
||||
exn_id = object_map.store(exn_type)
|
||||
self._write_string("{}:{}.{}".format(exn_id,
|
||||
exn_type.__module__, exn_type.__qualname__))
|
||||
self._write_string(str(exn))
|
||||
for index in range(3):
|
||||
self._write_int64(0)
|
||||
|
@ -479,7 +485,7 @@ class CommGeneric:
|
|||
|
||||
self._write_flush()
|
||||
|
||||
def _serve_exception(self, symbolizer):
|
||||
def _serve_exception(self, object_map, symbolizer):
|
||||
name = self._read_string()
|
||||
message = self._read_string()
|
||||
params = [self._read_int64() for _ in range(3)]
|
||||
|
@ -493,7 +499,17 @@ class CommGeneric:
|
|||
|
||||
traceback = list(reversed(symbolizer(backtrace))) + \
|
||||
[(filename, line, column, function, None)]
|
||||
raise core_language.ARTIQException(name, message, params, traceback)
|
||||
exception = core_language.ARTIQException(name, message, params, traceback)
|
||||
|
||||
if hasattr(exceptions, exception.name):
|
||||
python_exn_type = getattr(exceptions, exception.name)
|
||||
else:
|
||||
assert exception.id != 0
|
||||
python_exn_type = object_map.retrieve(exception.id)
|
||||
|
||||
python_exn = python_exn_type(message)
|
||||
python_exn.artiq_exception = exception
|
||||
raise python_exn
|
||||
|
||||
def serve(self, object_map, symbolizer):
|
||||
while True:
|
||||
|
@ -501,7 +517,7 @@ class CommGeneric:
|
|||
if self._read_type == _D2HMsgType.RPC_REQUEST:
|
||||
self._serve_rpc(object_map)
|
||||
elif self._read_type == _D2HMsgType.KERNEL_EXCEPTION:
|
||||
self._serve_exception(symbolizer)
|
||||
self._serve_exception(object_map, symbolizer)
|
||||
else:
|
||||
self._read_expect(_D2HMsgType.KERNEL_FINISHED)
|
||||
return
|
||||
|
|
|
@ -1,39 +1,31 @@
|
|||
import builtins
|
||||
from artiq.language.core import ARTIQException
|
||||
|
||||
|
||||
class ZeroDivisionError(ARTIQException):
|
||||
"""Python's :class:`ZeroDivisionError`, mirrored in ARTIQ."""
|
||||
ZeroDivisionError = builtins.ZeroDivisionError
|
||||
ValueError = builtins.ValueError
|
||||
IndexError = builtins.IndexError
|
||||
|
||||
|
||||
class ValueError(ARTIQException):
|
||||
"""Python's :class:`ValueError`, mirrored in ARTIQ."""
|
||||
|
||||
|
||||
class IndexError(ARTIQException):
|
||||
"""Python's :class:`IndexError`, mirrored in ARTIQ."""
|
||||
|
||||
|
||||
class InternalError(ARTIQException):
|
||||
class InternalError(Exception):
|
||||
"""Raised when the runtime encounters an internal error condition."""
|
||||
|
||||
|
||||
class RTIOUnderflow(ARTIQException):
|
||||
class RTIOUnderflow(Exception):
|
||||
"""Raised when the CPU fails to submit a RTIO event early enough
|
||||
(with respect to the event's timestamp).
|
||||
|
||||
The offending event is discarded and the RTIO core keeps operating.
|
||||
"""
|
||||
|
||||
|
||||
class RTIOSequenceError(ARTIQException):
|
||||
class RTIOSequenceError(Exception):
|
||||
"""Raised when an event is submitted on a given channel with a timestamp
|
||||
not larger than the previous one.
|
||||
|
||||
The offending event is discarded and the RTIO core keeps operating.
|
||||
"""
|
||||
|
||||
|
||||
class RTIOCollisionError(ARTIQException):
|
||||
class RTIOCollisionError(Exception):
|
||||
"""Raised when an event is submitted on a given channel with the same
|
||||
coarse timestamp as the previous one but with a different fine timestamp.
|
||||
|
||||
|
@ -44,8 +36,7 @@ class RTIOCollisionError(ARTIQException):
|
|||
The offending event is discarded and the RTIO core keeps operating.
|
||||
"""
|
||||
|
||||
|
||||
class RTIOOverflow(ARTIQException):
|
||||
class RTIOOverflow(Exception):
|
||||
"""Raised when at least one event could not be registered into the RTIO
|
||||
input FIFO because it was full (CPU not reading fast enough).
|
||||
|
||||
|
@ -54,8 +45,7 @@ class RTIOOverflow(ARTIQException):
|
|||
the exception is caught, and events will be partially retrieved.
|
||||
"""
|
||||
|
||||
|
||||
class DDSBatchError(ARTIQException):
|
||||
class DDSBatchError(Exception):
|
||||
"""Raised when attempting to start a DDS batch while already in a batch,
|
||||
or when too many commands are batched.
|
||||
"""
|
||||
|
|
|
@ -131,6 +131,10 @@ def run(with_file=False):
|
|||
except CompileError as error:
|
||||
print(error.render_string(colored=True), file=sys.stderr)
|
||||
return
|
||||
except Exception as exn:
|
||||
if hasattr(exn, 'artiq_exception'):
|
||||
print(exn.artiq_exception, file=sys.stderr)
|
||||
raise exn
|
||||
finally:
|
||||
device_mgr.close_devices()
|
||||
|
||||
|
|
|
@ -365,41 +365,20 @@ class TerminationRequested(Exception):
|
|||
pass
|
||||
|
||||
|
||||
class ARTIQException(Exception):
|
||||
"""Base class for exceptions raised or passed through the core device."""
|
||||
|
||||
# Try and create an instance of the specific class, if one exists.
|
||||
def __new__(cls, name, message, params, traceback):
|
||||
def find_subclass(cls):
|
||||
if cls.__name__ == name:
|
||||
return cls
|
||||
else:
|
||||
for subclass in cls.__subclasses__():
|
||||
cls = find_subclass(subclass)
|
||||
if cls is not None:
|
||||
return cls
|
||||
|
||||
more_specific_cls = find_subclass(cls)
|
||||
if more_specific_cls is None:
|
||||
more_specific_cls = cls
|
||||
|
||||
exn = Exception.__new__(more_specific_cls)
|
||||
exn.__init__(name, message, params, traceback)
|
||||
return exn
|
||||
class ARTIQException:
|
||||
"""Information about an exception raised or passed through the core device."""
|
||||
|
||||
def __init__(self, name, message, params, traceback):
|
||||
Exception.__init__(self, name, message, *params)
|
||||
self.name, self.message, self.params = name, message, params
|
||||
if ':' in name:
|
||||
exn_id, self.name = name.split(':', 2)
|
||||
self.id = host_int(exn_id)
|
||||
else:
|
||||
self.id, self.name = 0, name
|
||||
self.message, self.params = message, params
|
||||
self.traceback = list(traceback)
|
||||
|
||||
def __str__(self):
|
||||
lines = []
|
||||
|
||||
if type(self).__name__ == self.name:
|
||||
lines.append(self.message.format(*self.params))
|
||||
else:
|
||||
lines.append("({}) {}".format(self.name, self.message.format(*self.params)))
|
||||
|
||||
lines.append("Core Device Traceback (most recent call last):")
|
||||
for (filename, line, column, function, address) in self.traceback:
|
||||
stub_globals = {"__name__": filename, "__loader__": source_loader}
|
||||
|
@ -426,4 +405,6 @@ class ARTIQException(Exception):
|
|||
lines.append(" {}".format(source_line.strip() if source_line else "<unknown>"))
|
||||
lines.append(" {}^".format(" " * (column - indentation)))
|
||||
|
||||
lines.append("{}({}): {}".format(self.name, self.id,
|
||||
self.message.format(*self.params)))
|
||||
return "\n".join(lines)
|
||||
|
|
Loading…
Reference in New Issue