diff --git a/edg/core/Generator.py b/edg/core/Generator.py index 42a7135ef..b1a0d6bf2 100644 --- a/edg/core/Generator.py +++ b/edg/core/Generator.py @@ -142,7 +142,16 @@ def _generated_def_to_proto( self._generator_param_values[param] = param._from_lit( generate_values_map[ref_map[param].SerializeToString()] ) - self.generate() + try: + self.generate() + except Exception as e: + params_list_str = ", ".join( + f"{self._name_of_child(param, self, allow_unknown=True)}={self._generator_param_values[param]!r}" + for param in self._generator_params_list + ) + raise RuntimeError( + f"Generator {self.__class__.__name__} with parameters {{{params_list_str}}} raised exception: {e!r}" + ) from e elif self._generator is not None: # legacy generator style fn_args = [ arg_param._from_lit(generate_values_map[ref_map[arg_param].SerializeToString()]) diff --git a/edg/core/test_generator_error.py b/edg/core/test_generator_error.py index da5f5d4c3..6bba73595 100644 --- a/edg/core/test_generator_error.py +++ b/edg/core/test_generator_error.py @@ -6,6 +6,26 @@ from .HdlUserExceptions import BlockDefinitionError +class GeneratorErrorTop(DesignTop): + @override + def contents(self) -> None: + super().contents() + self.generator = self.Block(GeneratorRaises(42, "bad")) + + +class GeneratorRaises(GeneratorBlock): + def __init__(self, param: IntLike, str_param: StringLike) -> None: + super().__init__() + self.param = self.ArgParameter(param) + self.str_param = self.ArgParameter(str_param) + self.generator_param(self.param, self.str_param) + + @override + def generate(self) -> None: + super().generate() + raise ValueError + + class BadGeneratorTestCase(unittest.TestCase): # These are internal classes to avoid this error case being auto-discovered in a library @@ -29,3 +49,9 @@ def generate(self) -> None: def test_non_arg_generator(self) -> None: with self.assertRaises(BlockDefinitionError): self.InvalidNonArgGeneratorBlock()._elaborated_def_to_proto() + + def test_generator_raises(self) -> None: + with self.assertRaises(CompilerCheckError): + ScalaCompiler.compile(GeneratorErrorTop) + # TODO: inspect the exception, note that it is consumed by the Scala compiler + # and not summarized in the CompilerCheckError