# Copyright 2019 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.

"""Emboss front end.

This is an internal tool, normally called by the "embossc" driver, rather than
directly by a user.  It parses a .emb file and its dependencies, and prints an
intermediate representation of the parse trees and symbol tables to stdout, or
prints various bits of debug info, depending on which flags are passed.
"""

from __future__ import print_function

import argparse
import os
from os import path
import sys

from compiler.front_end import glue
from compiler.front_end import module_ir
from compiler.util import error


def _parse_command_line(argv):
  """Parses the given command-line arguments."""
  parser = argparse.ArgumentParser(description="Emboss compiler front end.",
                                   prog=argv[0])
  parser.add_argument("input_file",
                      type=str,
                      nargs=1,
                      help=".emb file to compile.")
  parser.add_argument("--debug-show-tokenization",
                      action="store_true",
                      help="Show the tokenization of the main input file.")
  parser.add_argument("--debug-show-parse-tree",
                      action="store_true",
                      help="Show the parse tree of the main input file.")
  parser.add_argument("--debug-show-module-ir",
                      action="store_true",
                      help="Show the module-level IR of the main input file "
                           "before symbol resolution.")
  parser.add_argument("--debug-show-full-ir",
                      action="store_true",
                      help="Show the final IR of the main input file.")
  parser.add_argument("--debug-show-used-productions",
                      action="store_true",
                      help="Show all of the grammar productions used in "
                           "parsing the main input file.")
  parser.add_argument("--debug-show-unused-productions",
                      action="store_true",
                      help="Show all of the grammar productions not used in "
                           "parsing the main input file.")
  parser.add_argument("--output-ir-to-stdout",
                      action="store_true",
                      help="Dump serialized IR to stdout.")
  parser.add_argument("--output-file",
                      type=str,
                      help="Write serialized IR to file.")
  parser.add_argument("--no-debug-show-header-lines",
                      dest="debug_show_header_lines",
                      action="store_false",
                      help="Print header lines before output if true.")
  parser.add_argument("--color-output",
                      default="if_tty",
                      choices=["always", "never", "if_tty", "auto"],
                      help="Print error messages using color.  'auto' is a "
                           "synonym for 'if_tty'.")
  parser.add_argument("--import-dir", "-I",
                      dest="import_dirs",
                      action="append",
                      default=["."],
                      help="A directory to use when searching for imported "
                           "embs.  If no import_dirs are specified, the "
                           "current directory will be used.")
  return parser.parse_args(argv[1:])


def _show_errors(errors, debug_info, flags):
  """Prints errors with source code snippets."""
  source_codes = {}
  for source_file in debug_info.modules:
    source_codes[source_file] = debug_info.modules[source_file].source_code
  use_color = (flags.color_output == "always" or
               (flags.color_output in ("auto", "if_tty") and
                os.isatty(sys.stderr.fileno())))
  print(error.format_errors(errors, source_codes, use_color), file=sys.stderr)


def _find_in_dirs_and_read(import_dirs):
  """Returns a function which will search import_dirs for a file."""

  def _find_and_read(file_name):
    """Searches import_dirs for file_name and returns the contents."""
    errors = []
    # *All* source files, including the one specified on the command line, will
    # be searched for in the import_dirs.  This may be surprising, especially if
    # the current directory is *not* an import_dir.
    # TODO(bolms): Determine if this is really the desired behavior.
    for import_dir in import_dirs:
      full_name = path.join(import_dir, file_name)
      try:
        with open(full_name) as f:
          # As written, this follows the typical compiler convention of checking
          # the include/import directories in the order specified by the user,
          # and always reading the first matching file, even if other files
          # might match in later directories.  This lets files shadow other
          # files, which can be useful in some cases (to override things), but
          # can also cause accidental shadowing, which can be tricky to fix.
          #
          # TODO(bolms): Check if any other files with the same name are in the
          # import path, and give a warning or error?
          return f.read(), None
      except IOError as e:
        errors.append(str(e))
    return None, errors + ["import path " + ":".join(import_dirs)]

  return _find_and_read


def main(flags):
  ir, debug_info, errors = glue.parse_emboss_file(
      flags.input_file[0], _find_in_dirs_and_read(flags.import_dirs))
  if errors:
    _show_errors(errors, debug_info, flags)
    return 1
  main_module_debug_info = debug_info.modules[flags.input_file[0]]
  if flags.debug_show_tokenization:
    if flags.debug_show_header_lines:
      print("Tokenization:")
    print(main_module_debug_info.format_tokenization())
  if flags.debug_show_parse_tree:
    if flags.debug_show_header_lines:
      print("Parse Tree:")
    print(main_module_debug_info.format_parse_tree())
  if flags.debug_show_module_ir:
    if flags.debug_show_header_lines:
      print("Module IR:")
    print(main_module_debug_info.format_module_ir())
  if flags.debug_show_full_ir:
    if flags.debug_show_header_lines:
      print("Full IR:")
    print(str(ir))
  if flags.debug_show_used_productions:
    if flags.debug_show_header_lines:
      print("Used Productions:")
    print(glue.format_production_set(main_module_debug_info.used_productions))
  if flags.debug_show_unused_productions:
    if flags.debug_show_header_lines:
      print("Unused Productions:")
    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())
  if flags.output_file:
    with open(flags.output_file, "w") as f:
      f.write(ir.to_json())
  return 0


if __name__ == "__main__":
  sys.exit(main(_parse_command_line(sys.argv)))
