Split out an `IrDataSerializer` class In preparation for reworking `ir_data` move json serialazition to it's own class. For now this is simply a wrapper. All `to_json` call sites are updated. Part of #118.
diff --git a/compiler/back_end/cpp/emboss_codegen_cpp.py b/compiler/back_end/cpp/emboss_codegen_cpp.py index 0a70f41..6da9f7d 100644 --- a/compiler/back_end/cpp/emboss_codegen_cpp.py +++ b/compiler/back_end/cpp/emboss_codegen_cpp.py
@@ -27,6 +27,7 @@ from compiler.back_end.cpp import header_generator from compiler.util import error from compiler.util import ir_data +from compiler.util import ir_data_utils def _parse_command_line(argv): @@ -82,9 +83,9 @@ def main(flags): if flags.input_file: with open(flags.input_file) as f: - ir = ir_data.EmbossIr.from_json(f.read()) + ir = ir_data_utils.IrDataSerializer.from_json(ir_data.EmbossIr, f.read()) else: - ir = ir_data.EmbossIr.from_json(sys.stdin.read()) + ir = ir_data_utils.IrDataSerializer.from_json(ir_data.EmbossIr, sys.stdin.read()) config = header_generator.Config(include_enum_traits=flags.cc_enum_traits) header, errors = generate_headers_and_log_errors(ir, flags.color_output, config) if errors:
diff --git a/compiler/front_end/emboss_front_end.py b/compiler/front_end/emboss_front_end.py index 6232a40..1e30ded 100644 --- a/compiler/front_end/emboss_front_end.py +++ b/compiler/front_end/emboss_front_end.py
@@ -30,6 +30,7 @@ from compiler.front_end import glue from compiler.front_end import module_ir from compiler.util import error +from compiler.util import ir_data_utils def _parse_command_line(argv): @@ -178,10 +179,10 @@ print(glue.format_production_set( set(module_ir.PRODUCTIONS) - main_module_debug_info.used_productions)) if flags.output_ir_to_stdout: - print(ir.to_json()) + print(ir_data_utils.IrDataSerializer(ir).to_json()) if flags.output_file: with open(flags.output_file, "w") as f: - f.write(ir.to_json()) + f.write(ir_data_utils.IrDataSerializer(ir).to_json()) return 0
diff --git a/compiler/front_end/glue.py b/compiler/front_end/glue.py index a1b0706..7724da9 100644 --- a/compiler/front_end/glue.py +++ b/compiler/front_end/glue.py
@@ -34,6 +34,7 @@ from compiler.front_end import write_inference from compiler.util import error from compiler.util import ir_data +from compiler.util import ir_data_utils from compiler.util import parser_types from compiler.util import resources @@ -111,7 +112,7 @@ def format_module_ir(self): """Renders self.ir in a human-readable format.""" - return self.ir.to_json(indent=2) + return ir_data_utils.IrDataSerializer(self.ir).to_json(indent=2) def format_production_set(productions):
diff --git a/compiler/front_end/glue_test.py b/compiler/front_end/glue_test.py index a2b61ad..10613d7 100644 --- a/compiler/front_end/glue_test.py +++ b/compiler/front_end/glue_test.py
@@ -20,6 +20,7 @@ from compiler.front_end import glue from compiler.util import error from compiler.util import ir_data +from compiler.util import ir_data_utils from compiler.util import parser_types from compiler.util import test_util @@ -33,7 +34,7 @@ _ROOT_PACKAGE, _SPAN_SE_LOG_FILE_PATH).decode(encoding="UTF-8") _SPAN_SE_LOG_FILE_READER = test_util.dict_file_reader( {_SPAN_SE_LOG_FILE_PATH: _SPAN_SE_LOG_FILE_EMB}) -_SPAN_SE_LOG_FILE_IR = ir_data.Module.from_json( +_SPAN_SE_LOG_FILE_IR = ir_data_utils.IrDataSerializer.from_json(ir_data.Module, pkgutil.get_data( _ROOT_PACKAGE, _GOLDEN_PATH + "span_se_log_file_status.ir.txt" @@ -155,7 +156,7 @@ self.assertEqual(_SPAN_SE_LOG_FILE_PARSE_TREE_TEXT.strip(), debug_info.format_parse_tree().strip()) self.assertEqual(_SPAN_SE_LOG_FILE_IR, debug_info.ir) - self.assertEqual(_SPAN_SE_LOG_FILE_IR.to_json(indent=2), + self.assertEqual(ir_data_utils.IrDataSerializer(_SPAN_SE_LOG_FILE_IR).to_json(indent=2), debug_info.format_module_ir()) def test_parse_emboss_file(self):
diff --git a/compiler/front_end/module_ir_test.py b/compiler/front_end/module_ir_test.py index 1f4233d..57d5f4c 100644 --- a/compiler/front_end/module_ir_test.py +++ b/compiler/front_end/module_ir_test.py
@@ -24,6 +24,7 @@ from compiler.front_end import parser from compiler.front_end import tokenizer from compiler.util import ir_data +from compiler.util import ir_data_utils from compiler.util import test_util _TESTDATA_PATH = "testdata.golden" @@ -31,7 +32,7 @@ _TESTDATA_PATH, "span_se_log_file_status.emb").decode(encoding="UTF-8") _MINIMAL_SAMPLE = parser.parse_module( tokenizer.tokenize(_MINIMAL_SOURCE, "")[0]).parse_tree -_MINIMAL_SAMPLE_IR = ir_data.Module.from_json( +_MINIMAL_SAMPLE_IR = ir_data_utils.IrDataSerializer.from_json(ir_data.Module, pkgutil.get_data(_TESTDATA_PATH, "span_se_log_file_status.ir.txt").decode( encoding="UTF-8") ) @@ -3978,7 +3979,7 @@ name, emb, ir_text = case.split("---") name = name.strip() try: - ir = ir_data.Module.from_json(ir_text) + ir = ir_data_utils.IrDataSerializer.from_json(ir_data.Module, ir_text) except Exception: print(name) raise @@ -4152,10 +4153,11 @@ def test_case(self): ir = module_ir.build_ir(test.parse_tree) is_superset, error_message = test_util.proto_is_superset(ir, test.ir) + self.assertTrue( is_superset, - error_message + "\n" + ir.to_json(indent=2) + "\n" + - test.ir.to_json(indent=2)) + error_message + "\n" + ir_data_utils.IrDataSerializer(ir).to_json(indent=2) + "\n" + + ir_data_utils.IrDataSerializer(test.ir).to_json(indent=2)) return test_case
diff --git a/compiler/front_end/type_check_test.py b/compiler/front_end/type_check_test.py index 6906738..d308fed 100644 --- a/compiler/front_end/type_check_test.py +++ b/compiler/front_end/type_check_test.py
@@ -18,6 +18,7 @@ from compiler.front_end import glue from compiler.front_end import type_check from compiler.util import error +from compiler.util import ir_data_utils from compiler.util import test_util @@ -44,7 +45,7 @@ " 0 [+1] UInt x\n" " 1 [+true] UInt:8[] y\n") self.assertEqual([], error.filter_errors(type_check.annotate_types(ir)), - ir.to_json(indent=2)) + ir_data_utils.IrDataSerializer(ir).to_json(indent=2)) expression = ir.module[0].type[0].structure.field[1].location.size self.assertEqual(expression.type.WhichOneof("type"), "boolean")
diff --git a/compiler/util/BUILD b/compiler/util/BUILD index bbc2ec0..5946dcb 100644 --- a/compiler/util/BUILD +++ b/compiler/util/BUILD
@@ -25,6 +25,7 @@ name = "ir_data", srcs = [ "ir_data.py", + "ir_data_utils.py", ], )
diff --git a/compiler/util/ir_data_utils.py b/compiler/util/ir_data_utils.py new file mode 100644 index 0000000..63b55b7 --- /dev/null +++ b/compiler/util/ir_data_utils.py
@@ -0,0 +1,31 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from compiler.util import ir_data + +class IrDataSerializer: + """Provides methods for serializing IR data objects""" + + def __init__(self, ir: ir_data.Message): + assert ir is not None + self.ir = ir + + def to_json(self, *args, **kwargs): + """Converts the IR data class to a JSON string""" + return self.ir.to_json(*args, **kwargs) + + @staticmethod + def from_json(data_cls: type[ir_data.Message], data): + """Constructs an IR data class from the given JSON string""" + return data_cls.from_json(data)
diff --git a/compiler/util/ir_util_test.py b/compiler/util/ir_util_test.py index 1afed9c..b92ffb9 100644 --- a/compiler/util/ir_util_test.py +++ b/compiler/util/ir_util_test.py
@@ -17,6 +17,7 @@ import unittest from compiler.util import expression_parser from compiler.util import ir_data +from compiler.util import ir_data_utils from compiler.util import ir_util @@ -410,7 +411,7 @@ "bob") def test_find_object(self): - ir = ir_data.EmbossIr.from_json( + ir = ir_data_utils.IrDataSerializer.from_json(ir_data.EmbossIr, """{ "module": [ { @@ -564,7 +565,7 @@ object_path=["Foo", "Bar"])))) def test_get_base_type(self): - array_type_ir = ir_data.Type.from_json( + array_type_ir = ir_data_utils.IrDataSerializer.from_json(ir_data.Type, """{ "array_type": { "element_count": { "constant": { "value": "20" } }, @@ -590,7 +591,7 @@ self.assertEqual(base_type_ir, ir_util.get_base_type(base_type_ir)) def test_size_of_type_in_bits(self): - ir = ir_data.EmbossIr.from_json( + ir = ir_data_utils.IrDataSerializer.from_json(ir_data.EmbossIr, """{ "module": [{ "type": [{ @@ -638,7 +639,7 @@ }] }""") - fixed_size_type = ir_data.Type.from_json( + fixed_size_type = ir_data_utils.IrDataSerializer.from_json(ir_data.Type, """{ "atomic_type": { "reference": { @@ -648,7 +649,7 @@ }""") self.assertEqual(8, ir_util.fixed_size_of_type_in_bits(fixed_size_type, ir)) - explicit_size_type = ir_data.Type.from_json( + explicit_size_type = ir_data_utils.IrDataSerializer.from_json(ir_data.Type, """{ "atomic_type": { "reference": { @@ -665,7 +666,7 @@ self.assertEqual(32, ir_util.fixed_size_of_type_in_bits(explicit_size_type, ir)) - fixed_size_array = ir_data.Type.from_json( + fixed_size_array = ir_data_utils.IrDataSerializer.from_json(ir_data.Type, """{ "array_type": { "base_type": { @@ -686,7 +687,7 @@ self.assertEqual(40, ir_util.fixed_size_of_type_in_bits(fixed_size_array, ir)) - fixed_size_2d_array = ir_data.Type.from_json( + fixed_size_2d_array = ir_data_utils.IrDataSerializer.from_json(ir_data.Type, """{ "array_type": { "base_type": { @@ -720,7 +721,7 @@ self.assertEqual( 80, ir_util.fixed_size_of_type_in_bits(fixed_size_2d_array, ir)) - automatic_size_array = ir_data.Type.from_json( + automatic_size_array = ir_data_utils.IrDataSerializer.from_json(ir_data.Type, """{ "array_type": { "base_type": { @@ -749,7 +750,7 @@ self.assertIsNone( ir_util.fixed_size_of_type_in_bits(automatic_size_array, ir)) - variable_size_type = ir_data.Type.from_json( + variable_size_type = ir_data_utils.IrDataSerializer.from_json(ir_data.Type, """{ "atomic_type": { "reference": { @@ -760,7 +761,7 @@ self.assertIsNone( ir_util.fixed_size_of_type_in_bits(variable_size_type, ir)) - no_size_type = ir_data.Type.from_json( + no_size_type = ir_data_utils.IrDataSerializer.from_json(ir_data.Type, """{ "atomic_type": { "reference": {
diff --git a/compiler/util/traverse_ir_test.py b/compiler/util/traverse_ir_test.py index 64da8f6..ff54d63 100644 --- a/compiler/util/traverse_ir_test.py +++ b/compiler/util/traverse_ir_test.py
@@ -19,9 +19,10 @@ import unittest from compiler.util import ir_data +from compiler.util import ir_data_utils from compiler.util import traverse_ir -_EXAMPLE_IR = ir_data.EmbossIr.from_json("""{ +_EXAMPLE_IR = ir_data_utils.IrDataSerializer.from_json(ir_data.EmbossIr, """{ "module": [ { "type": [