1# Copyright 2019 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""Emboss C++ code generator. 16 17This is a driver program that reads IR, feeds it to header_generator, and prints 18the result. 19""" 20 21from __future__ import print_function 22 23import argparse 24import os 25import sys 26 27from compiler.back_end.cpp import header_generator 28from compiler.util import error 29from compiler.util import ir_data 30from compiler.util import ir_data_utils 31 32 33def _parse_command_line(argv): 34 """Parses the given command-line arguments.""" 35 parser = argparse.ArgumentParser(description="Emboss compiler C++ back end.", 36 prog=argv[0]) 37 parser.add_argument("--input-file", 38 type=str, 39 help=".emb.ir file to compile.") 40 parser.add_argument("--output-file", 41 type=str, 42 help="Write header to file. If not specified, write " + 43 "header to stdout.") 44 parser.add_argument("--color-output", 45 default="if_tty", 46 choices=["always", "never", "if_tty", "auto"], 47 help="Print error messages using color. 'auto' is a " 48 "synonym for 'if_tty'.") 49 parser.add_argument("--cc-enum-traits", 50 action=argparse.BooleanOptionalAction, 51 default=True, 52 help="""Controls generation of EnumTraits by the C++ 53 backend""") 54 return parser.parse_args(argv[1:]) 55 56 57def _show_errors(errors, ir, color_output): 58 """Prints errors with source code snippets.""" 59 source_codes = {} 60 for module in ir.module: 61 source_codes[module.source_file_name] = module.source_text 62 use_color = (color_output == "always" or 63 (color_output in ("auto", "if_tty") and 64 os.isatty(sys.stderr.fileno()))) 65 print(error.format_errors(errors, source_codes, use_color), file=sys.stderr) 66 67def generate_headers_and_log_errors(ir, color_output, config: header_generator.Config): 68 """Generates a C++ header and logs any errors. 69 70 Arguments: 71 ir: EmbossIr of the module. 72 color_output: "always", "never", "if_tty", "auto" 73 config: Header generation configuration. 74 75 Returns: 76 A tuple of (header, errors) 77 """ 78 header, errors = header_generator.generate_header(ir, config) 79 if errors: 80 _show_errors(errors, ir, color_output) 81 return (header, errors) 82 83def main(flags): 84 if flags.input_file: 85 with open(flags.input_file) as f: 86 ir = ir_data_utils.IrDataSerializer.from_json(ir_data.EmbossIr, f.read()) 87 else: 88 ir = ir_data_utils.IrDataSerializer.from_json(ir_data.EmbossIr, sys.stdin.read()) 89 config = header_generator.Config(include_enum_traits=flags.cc_enum_traits) 90 header, errors = generate_headers_and_log_errors(ir, flags.color_output, config) 91 if errors: 92 return 1 93 if flags.output_file: 94 with open(flags.output_file, "w") as f: 95 f.write(header) 96 else: 97 print(header) 98 return 0 99 100 101if __name__ == '__main__': 102 sys.exit(main(_parse_command_line(sys.argv))) 103