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

"""Utility functions for reading and manipulating Emboss IR."""

import operator

from compiler.util import ir_data


_FIXED_SIZE_ATTRIBUTE = "fixed_size_in_bits"


def get_attribute(attribute_list, name):
  """Finds name in attribute_list and returns a AttributeValue or None."""
  attribute_value = None
  for attr in attribute_list:
    if attr.name.text == name and not attr.is_default:
      assert attribute_value is None, 'Duplicate attribute "{}".'.format(name)
      attribute_value = attr.value
  return attribute_value


def get_boolean_attribute(attribute_list, name, default_value=None):
  """Returns the boolean value of an attribute, if any, or default_value.

  Arguments:
      attribute_list: A list of attributes to search.
      name: The name of the desired attribute.
      default_value: A value to return if name is not found in attribute_list,
          or the attribute does not have a boolean value.

  Returns:
      The boolean value of the requested attribute, or default_value if the
      requested attribute is not found or has a non-boolean value.
  """
  attribute_value = get_attribute(attribute_list, name)
  if (not attribute_value or
      not attribute_value.expression.HasField("boolean_constant")):
    return default_value
  return attribute_value.expression.boolean_constant.value


def get_integer_attribute(attribute_list, name, default_value=None):
  """Returns the integer value of an attribute, if any, or default_value.

  Arguments:
      attribute_list: A list of attributes to search.
      name: The name of the desired attribute.
      default_value: A value to return if name is not found in attribute_list,
          or the attribute does not have an integer value.

  Returns:
      The integer value of the requested attribute, or default_value if the
      requested attribute is not found or has a non-integer value.
  """
  attribute_value = get_attribute(attribute_list, name)
  if (not attribute_value or
      attribute_value.expression.type.WhichOneof("type") != "integer" or
      not is_constant(attribute_value.expression)):
    return default_value
  return constant_value(attribute_value.expression)


def is_constant(expression, bindings=None):
  return constant_value(expression, bindings) is not None


def is_constant_type(expression_type):
  """Returns True if expression_type is inhabited by a single value."""
  return (expression_type.integer.modulus == "infinity" or
          expression_type.boolean.HasField("value") or
          expression_type.enumeration.HasField("value"))


def constant_value(expression, bindings=None):
  """Evaluates expression with the given bindings."""
  if expression.WhichOneof("expression") == "constant":
    return int(expression.constant.value)
  elif expression.WhichOneof("expression") == "constant_reference":
    # We can't look up the constant reference without the IR, but by the time
    # constant_value is called, the actual values should have been propagated to
    # the type information.
    if expression.type.WhichOneof("type") == "integer":
      assert expression.type.integer.modulus == "infinity"
      return int(expression.type.integer.modular_value)
    elif expression.type.WhichOneof("type") == "boolean":
      assert expression.type.boolean.HasField("value")
      return expression.type.boolean.value
    elif expression.type.WhichOneof("type") == "enumeration":
      assert expression.type.enumeration.HasField("value")
      return int(expression.type.enumeration.value)
    else:
      assert False, "Unexpected expression type {}".format(
          expression.type.WhichOneof("type"))
  elif expression.WhichOneof("expression") == "function":
    return _constant_value_of_function(expression.function, bindings)
  elif expression.WhichOneof("expression") == "field_reference":
    return None
  elif expression.WhichOneof("expression") == "boolean_constant":
    return expression.boolean_constant.value
  elif expression.WhichOneof("expression") == "builtin_reference":
    name = expression.builtin_reference.canonical_name.object_path[0]
    if bindings and name in bindings:
      return bindings[name]
    else:
      return None
  elif expression.WhichOneof("expression") is None:
    return None
  else:
    assert False, "Unexpected expression kind {}".format(
        expression.WhichOneof("expression"))


def _constant_value_of_function(function, bindings):
  """Returns the constant value of evaluating `function`, or None."""
  values = [constant_value(arg, bindings) for arg in function.args]
  # Expressions like `$is_statically_sized && 1 <= $static_size_in_bits <= 64`
  # should return False, not None, if `$is_statically_sized` is false, even
  # though `$static_size_in_bits` is unknown.
  #
  # The easiest way to allow this is to use a three-way logic chart for each;
  # specifically:
  #
  # AND:      True     False    Unknown
  #         +--------------------------
  # True    | True     False    Unknown
  # False   | False    False    False
  # Unknown | Unknown  False    Unknown
  #
  # OR:       True     False    Unknown
  #         +--------------------------
  # True    | True     True     True
  # False   | True     False    Unknown
  # Unknown | True     Unknown  Unknown
  #
  # This raises the question of just how many constant-from-nonconstant
  # expressions Emboss should support.  There are, after all, a vast number of
  # constant expression patterns built from non-constant subexpressions, such as
  # `0 * X` or `X == X` or `3 * X == X + X + X`.  I (bolms@) am not implementing
  # any further special cases because I do not see any practical use for them.
  if function.function == ir_data.FunctionMapping.UNKNOWN:
    return None
  if function.function == ir_data.FunctionMapping.AND:
    if any(value is False for value in values):
      return False
    elif any(value is None for value in values):
      return None
    else:
      return True
  elif function.function == ir_data.FunctionMapping.OR:
    if any(value is True for value in values):
      return True
    elif any(value is None for value in values):
      return None
    else:
      return False
  elif function.function == ir_data.FunctionMapping.CHOICE:
    if values[0] is None:
      return None
    else:
      return values[1] if values[0] else values[2]
  # Other than the logical operators and choice operator, the result of any
  # function on an unknown value is, itself, considered unknown.
  if any(value is None for value in values):
    return None
  functions = {
      ir_data.FunctionMapping.ADDITION: operator.add,
      ir_data.FunctionMapping.SUBTRACTION: operator.sub,
      ir_data.FunctionMapping.MULTIPLICATION: operator.mul,
      ir_data.FunctionMapping.EQUALITY: operator.eq,
      ir_data.FunctionMapping.INEQUALITY: operator.ne,
      ir_data.FunctionMapping.LESS: operator.lt,
      ir_data.FunctionMapping.LESS_OR_EQUAL: operator.le,
      ir_data.FunctionMapping.GREATER: operator.gt,
      ir_data.FunctionMapping.GREATER_OR_EQUAL: operator.ge,
      # Python's max([1, 2]) == 2; max(1, 2) == 2; max([1]) == 1; but max(1)
      # throws a TypeError ("'int' object is not iterable").
      ir_data.FunctionMapping.MAXIMUM: lambda *x: max(x),
  }
  return functions[function.function](*values)


def _hashable_form_of_name(name):
  return (name.module_file,) + tuple(name.object_path)


def hashable_form_of_reference(reference):
  """Returns a representation of reference that can be used as a dict key.

  Arguments:
    reference: An ir_data.Reference or ir_data.NameDefinition.

  Returns:
    A tuple of the module_file and object_path.
  """
  return _hashable_form_of_name(reference.canonical_name)


def hashable_form_of_field_reference(field_reference):
  """Returns a representation of field_reference that can be used as a dict key.

  Arguments:
    field_reference: An ir_data.FieldReference

  Returns:
    A tuple of tuples of the module_files and object_paths.
  """
  return tuple(_hashable_form_of_name(reference.canonical_name)
               for reference in field_reference.path)


def is_array(type_ir):
  """Returns true if type_ir is an array type."""
  return type_ir.HasField("array_type")


def _find_path_in_structure_field(path, field):
  if not path:
    return field
  return None


def _find_path_in_structure(path, type_definition):
  for field in type_definition.structure.field:
    if field.name.name.text == path[0]:
      return _find_path_in_structure_field(path[1:], field)
  return None


def _find_path_in_enumeration(path, type_definition):
  if len(path) != 1:
    return None
  for value in type_definition.enumeration.value:
    if value.name.name.text == path[0]:
      return value
  return None


def _find_path_in_parameters(path, type_definition):
  if len(path) > 1:
    return None
  for parameter in type_definition.runtime_parameter:
    if parameter.name.name.text == path[0]:
      return parameter
  return None


def _find_path_in_type_definition(path, type_definition):
  """Finds the object with the given path in the given type_definition."""
  if not path:
    return type_definition
  obj = _find_path_in_parameters(path, type_definition)
  if obj:
    return obj
  if type_definition.HasField("structure"):
    obj = _find_path_in_structure(path, type_definition)
  elif type_definition.HasField("enumeration"):
    obj = _find_path_in_enumeration(path, type_definition)
  if obj:
    return obj
  else:
    return _find_path_in_type_list(path, type_definition.subtype)


def _find_path_in_type_list(path, type_list):
  for type_definition in type_list:
    if type_definition.name.name.text == path[0]:
      return _find_path_in_type_definition(path[1:], type_definition)
  return None


def _find_path_in_module(path, module_ir):
  if not path:
    return module_ir
  return _find_path_in_type_list(path, module_ir.type)


def find_object_or_none(name, ir):
  """Finds the object with the given canonical name, if it exists.."""
  if (isinstance(name, ir_data.Reference) or
      isinstance(name, ir_data.NameDefinition)):
    path = _hashable_form_of_name(name.canonical_name)
  elif isinstance(name, ir_data.CanonicalName):
    path = _hashable_form_of_name(name)
  else:
    path = name

  for module in ir.module:
    if module.source_file_name == path[0]:
      return _find_path_in_module(path[1:], module)

  return None


def find_object(name, ir):
  """Finds the IR of the type, field, or value with the given canonical name."""
  result = find_object_or_none(name, ir)
  assert result is not None, "Bad reference {}".format(name)
  return result


def find_parent_object(name, ir):
  """Finds the parent object of the object with the given canonical name."""
  if (isinstance(name, ir_data.Reference) or
      isinstance(name, ir_data.NameDefinition)):
    path = _hashable_form_of_name(name.canonical_name)
  elif isinstance(name, ir_data.CanonicalName):
    path = _hashable_form_of_name(name)
  else:
    path = name
  return find_object(path[:-1], ir)


def get_base_type(type_ir):
  """Returns the base type of the given type.

  Arguments:
    type_ir: IR of a type reference.

  Returns:
    If type_ir corresponds to an atomic type (like "UInt"), returns type_ir.  If
    type_ir corresponds to an array type (like "UInt:8[12]" or "Square[8][8]"),
    returns the type after stripping off the array types ("UInt" or "Square").
  """
  while type_ir.HasField("array_type"):
    type_ir = type_ir.array_type.base_type
  assert type_ir.HasField("atomic_type"), (
      "Unknown kind of type {}".format(type_ir))
  return type_ir


def fixed_size_of_type_in_bits(type_ir, ir):
  """Returns the fixed, known size for the given type, in bits, or None.

  Arguments:
    type_ir: The IR of a type.
    ir: A complete IR, used to resolve references to types.

  Returns:
    size if the size of the type can be determined, otherwise None.
  """
  array_multiplier = 1
  while type_ir.HasField("array_type"):
    if type_ir.array_type.WhichOneof("size") == "automatic":
      return None
    else:
      assert type_ir.array_type.WhichOneof("size") == "element_count", (
          'Expected array size to be "automatic" or "element_count".')
    element_count = type_ir.array_type.element_count
    if not is_constant(element_count):
      return None
    else:
      array_multiplier *= constant_value(element_count)
    assert not type_ir.HasField("size_in_bits"), (
        "TODO(bolms): implement explicitly-sized arrays")
    type_ir = type_ir.array_type.base_type
  assert type_ir.HasField("atomic_type"), "Unexpected type!"
  if type_ir.HasField("size_in_bits"):
    size = constant_value(type_ir.size_in_bits)
  else:
    type_definition = find_object(type_ir.atomic_type.reference, ir)
    size_attr = get_attribute(type_definition.attribute, _FIXED_SIZE_ATTRIBUTE)
    if not size_attr:
      return None
    size = constant_value(size_attr.expression)
  return size * array_multiplier


def field_is_virtual(field_ir):
  """Returns true if the field is virtual."""
  # TODO(bolms): Should there be a more explicit indicator that a field is
  # virtual?
  return not field_ir.HasField("location")


def field_is_read_only(field_ir):
  """Returns true if the field is read-only."""
  # For now, all virtual fields are read-only, and no non-virtual fields are
  # read-only.
  return field_ir.write_method.read_only
