# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import sys

from .argument import Argument
from .ast_group import AstGroup
from .attribute import Attribute
from .callback_function import CallbackFunction
from .callback_interface import CallbackInterface
from .composition_parts import Component
from .composition_parts import DebugInfo
from .composition_parts import Identifier
from .composition_parts import Location
from .constant import Constant
from .constructor import Constructor
from .dictionary import Dictionary
from .dictionary import DictionaryMember
from .enumeration import Enumeration
from .extended_attribute import ExtendedAttribute
from .extended_attribute import ExtendedAttributes
from .idl_type import IdlTypeFactory
from .includes import Includes
from .interface import Interface
from .interface import Iterable
from .interface import Maplike
from .interface import Setlike
from .literal_constant import LiteralConstant
from .namespace import Namespace
from .operation import Operation
from .typedef import Typedef


# TODO(crbug.com/1174969): Remove this once Python2 is obsoleted.
if sys.version_info.major != 2:
    long = int


def load_and_register_idl_definitions(filepaths, register_ir,
                                      create_ref_to_idl_def, idl_type_factory):
    """
    Reads ASTs from |filepaths| and builds IRs from ASTs.

    Args:
        filepaths: Paths to pickle files that store AST nodes.
        register_ir: A callback function that registers the argument as an
            IR.
        create_ref_to_idl_def: A callback function that creates a reference
            to an IDL definition from the given identifier.
        idl_type_factory: All IdlType instances will be created through this
            factory.
    """
    assert callable(register_ir)

    for filepath in filepaths:
        asts = AstGroup.read_from_file(filepath)
        builder = _IRBuilder(
            component=Component(asts.component),
            for_testing=asts.for_testing,
            create_ref_to_idl_def=create_ref_to_idl_def,
            idl_type_factory=idl_type_factory)

        for file_node in asts:
            assert file_node.GetClass() == 'File'
            for top_level_node in file_node.GetChildren():
                register_ir(builder.build_top_level_def(top_level_node))


class _IRBuilder(object):
    def __init__(self, component, for_testing, create_ref_to_idl_def,
                 idl_type_factory):
        """
        Args:
            component: A Component to which the built IRs are associated.
            for_testing: True if the IDL definitions are meant for testing
                purpose only.
            create_ref_to_idl_def: A callback function that creates a reference
                to an IDL definition from the given identifier.
            idl_type_factory: All IdlType instances will be created through this
                factory.
        """
        assert isinstance(component, Component)
        assert isinstance(for_testing, bool)
        assert callable(create_ref_to_idl_def)
        assert isinstance(idl_type_factory, IdlTypeFactory)

        self._component = component
        self._for_testing = for_testing
        self._create_ref_to_idl_def = create_ref_to_idl_def
        self._idl_type_factory = idl_type_factory

    def build_top_level_def(self, node):
        build_functions = {
            'Callback': self._build_callback_function,
            'Dictionary': self._build_dictionary,
            'Enum': self._build_enumeration,
            'Includes': self._build_includes,
            'Interface': self._build_interface,
            'Namespace': self._build_namespace,
            'Typedef': self._build_typedef,
        }
        ir = build_functions[node.GetClass()](node)
        ir.code_generator_info.set_for_testing(self._for_testing)
        return ir

    # Builder functions for top-level definitions

    def _build_interface(self, node):
        if node.GetProperty('CALLBACK'):
            return self._build_callback_interface(node)

        identifier = Identifier(node.GetName())
        child_nodes = list(node.GetChildren())
        inherited = self._take_inheritance(child_nodes)
        stringifier_members = self._take_stringifier(child_nodes)
        iterable = self._take_iterable(child_nodes)
        maplike = self._take_maplike(
            child_nodes, interface_identifier=identifier)
        setlike = self._take_setlike(
            child_nodes, interface_identifier=identifier)
        extended_attributes = self._take_extended_attributes(child_nodes)

        members = [
            self._build_interface_member(
                child, interface_identifier=identifier)
            for child in child_nodes
        ]
        if stringifier_members:
            members.extend(filter(None, stringifier_members))
        attributes = []
        constants = []
        constructors = []
        operations = []
        for member in members:
            if isinstance(member, Attribute.IR):
                attributes.append(member)
            elif isinstance(member, Constant.IR):
                constants.append(member)
            elif isinstance(member, Constructor.IR):
                constructors.append(member)
            elif isinstance(member, Operation.IR):
                operations.append(member)
            else:
                assert False

        named_constructors = self._build_named_constructors(node)

        return Interface.IR(
            identifier=identifier,
            is_partial=bool(node.GetProperty('PARTIAL')),
            is_mixin=bool(node.GetProperty('MIXIN')),
            inherited=inherited,
            attributes=attributes,
            constants=constants,
            constructors=constructors,
            named_constructors=named_constructors,
            operations=operations,
            iterable=iterable,
            maplike=maplike,
            setlike=setlike,
            extended_attributes=extended_attributes,
            component=self._component,
            debug_info=self._build_debug_info(node))

    def _build_namespace(self, node):
        child_nodes = list(node.GetChildren())
        extended_attributes = self._take_extended_attributes(child_nodes)

        members = list(map(self._build_interface_member, child_nodes))
        attributes = []
        constants = []
        operations = []
        for member in members:
            if isinstance(member, Attribute.IR):
                member.is_static = True
                attributes.append(member)
            elif isinstance(member, Constant.IR):
                constants.append(member)
            elif isinstance(member, Operation.IR):
                member.is_static = True
                operations.append(member)
            else:
                assert False

        return Namespace.IR(
            identifier=Identifier(node.GetName()),
            is_partial=bool(node.GetProperty('PARTIAL')),
            attributes=attributes,
            constants=constants,
            operations=operations,
            extended_attributes=extended_attributes,
            component=self._component,
            debug_info=self._build_debug_info(node))

    def _build_interface_member(self,
                                node,
                                fallback_extended_attributes=None,
                                interface_identifier=None):
        def build_attribute(node):
            child_nodes = list(node.GetChildren())
            idl_type = self._take_type(child_nodes)
            extended_attributes = self._take_extended_attributes(
                child_nodes) or fallback_extended_attributes
            assert not child_nodes
            return Attribute.IR(
                identifier=Identifier(node.GetName()),
                idl_type=idl_type,
                is_static=bool(node.GetProperty('STATIC')),
                is_readonly=bool(node.GetProperty('READONLY')),
                does_inherit_getter=bool(node.GetProperty('INHERIT')),
                extended_attributes=extended_attributes,
                component=self._component,
                debug_info=self._build_debug_info(node))

        def build_constant(node):
            child_nodes = list(node.GetChildren())
            value = self._take_constant_value(child_nodes)
            extended_attributes = self._take_extended_attributes(
                child_nodes) or fallback_extended_attributes
            assert len(child_nodes) == 1, child_nodes[0].GetClass()
            # idl_parser doesn't produce a 'Type' node for the type of a
            # constant, hence we need to skip one level.
            idl_type = self._build_type_internal(child_nodes)
            return Constant.IR(
                identifier=Identifier(node.GetName()),
                idl_type=idl_type,
                value=value,
                extended_attributes=extended_attributes,
                component=self._component,
                debug_info=self._build_debug_info(node))

        def build_constructor(node):
            assert isinstance(interface_identifier, Identifier)
            child_nodes = list(node.GetChildren())
            arguments = self._take_arguments(child_nodes)
            extended_attributes = self._take_extended_attributes(
                child_nodes) or fallback_extended_attributes
            assert not child_nodes
            return_type = self._idl_type_factory.reference_type(
                interface_identifier)
            return Constructor.IR(
                identifier=None,
                arguments=arguments,
                return_type=return_type,
                extended_attributes=extended_attributes,
                component=self._component,
                debug_info=self._build_debug_info(node))

        def build_operation(node):
            child_nodes = list(node.GetChildren())
            arguments = self._take_arguments(child_nodes)
            return_type = self._take_type(child_nodes)
            extended_attributes = self._take_extended_attributes(
                child_nodes) or fallback_extended_attributes
            assert not child_nodes
            return Operation.IR(
                identifier=Identifier(node.GetName()),
                arguments=arguments,
                return_type=return_type,
                is_static=bool(node.GetProperty('STATIC')),
                is_getter=bool(node.GetProperty('GETTER')),
                is_setter=bool(node.GetProperty('SETTER')),
                is_deleter=bool(node.GetProperty('DELETER')),
                extended_attributes=extended_attributes,
                component=self._component,
                debug_info=self._build_debug_info(node))

        build_functions = {
            'Attribute': build_attribute,
            'Const': build_constant,
            'Constructor': build_constructor,
            'Operation': build_operation,
        }
        return build_functions[node.GetClass()](node)

    def _build_named_constructors(self, node):
        assert node.GetClass() == 'Interface'
        named_constructors = []

        for child in node.GetChildren():
            if child.GetClass() == 'ExtAttributes':
                interface_ext_attrs = child.GetChildren()
                break
        else:
            return named_constructors

        for ext_attr in interface_ext_attrs:
            if ext_attr.GetName() != 'NamedConstructor':
                continue
            call_node = ext_attr.GetChildren()[0]
            assert call_node.GetClass() == 'Call'
            child_nodes = list(call_node.GetChildren())
            arguments = self._take_arguments(child_nodes)
            return_type = self._idl_type_factory.reference_type(
                Identifier(node.GetName()))
            assert not child_nodes
            named_constructors.append(
                Constructor.IR(
                    identifier=Identifier(call_node.GetName()),
                    arguments=arguments,
                    return_type=return_type,
                    component=self._component,
                    debug_info=self._build_debug_info(node)))

        return named_constructors

    def _build_dictionary(self, node):
        child_nodes = list(node.GetChildren())
        inherited = self._take_inheritance(child_nodes)
        extended_attributes = self._take_extended_attributes(child_nodes)
        own_members = list(map(self._build_dictionary_member, child_nodes))

        return Dictionary.IR(
            identifier=Identifier(node.GetName()),
            is_partial=bool(node.GetProperty('PARTIAL')),
            inherited=inherited,
            own_members=own_members,
            extended_attributes=extended_attributes,
            component=self._component,
            debug_info=self._build_debug_info(node))

    def _build_dictionary_member(self, node):
        assert node.GetClass() == 'Key'

        child_nodes = list(node.GetChildren())
        is_required = bool(node.GetProperty('REQUIRED'))
        idl_type = self._take_type(child_nodes, is_optional=(not is_required))
        default_value = self._take_default_value(child_nodes)
        extended_attributes = self._take_extended_attributes(child_nodes)
        assert not child_nodes

        return DictionaryMember.IR(
            identifier=Identifier(node.GetName()),
            idl_type=idl_type,
            default_value=default_value,
            extended_attributes=extended_attributes,
            component=self._component,
            debug_info=self._build_debug_info(node))

    def _build_callback_interface(self, node):
        assert node.GetProperty('CALLBACK')

        child_nodes = list(node.GetChildren())
        extended_attributes = self._take_extended_attributes(child_nodes)
        members = list(map(self._build_interface_member, child_nodes))
        constants = []
        operations = []
        for member in members:
            if isinstance(member, Constant.IR):
                constants.append(member)
            elif isinstance(member, Operation.IR):
                operations.append(member)
            else:
                assert False

        return CallbackInterface.IR(
            identifier=Identifier(node.GetName()),
            constants=constants,
            operations=operations,
            extended_attributes=extended_attributes,
            component=self._component,
            debug_info=self._build_debug_info(node))

    def _build_callback_function(self, node):
        child_nodes = list(node.GetChildren())
        arguments = self._take_arguments(child_nodes)
        return_type = self._take_type(child_nodes)
        extended_attributes = self._take_extended_attributes(child_nodes)
        assert not child_nodes
        return CallbackFunction.IR(
            identifier=Identifier(node.GetName()),
            arguments=arguments,
            return_type=return_type,
            extended_attributes=extended_attributes,
            component=self._component,
            debug_info=self._build_debug_info(node))

    def _build_enumeration(self, node):
        child_nodes = list(node.GetChildren())
        extended_attributes = self._take_extended_attributes(child_nodes)
        assert all(child.GetClass() == 'EnumItem' for child in child_nodes)
        values = [child.GetName() for child in child_nodes]
        return Enumeration.IR(
            identifier=Identifier(node.GetName()),
            values=values,
            extended_attributes=extended_attributes,
            component=self._component,
            debug_info=self._build_debug_info(node))

    def _build_typedef(self, node):
        child_nodes = list(node.GetChildren())
        idl_type = self._take_type(child_nodes)
        assert not child_nodes

        return Typedef.IR(
            identifier=Identifier(node.GetName()),
            idl_type=idl_type,
            component=self._component,
            debug_info=self._build_debug_info(node))

    def _build_includes(self, node):
        return Includes.IR(
            interface_identifier=Identifier(node.GetName()),
            mixin_identifier=Identifier(node.GetProperty('REFERENCE')),
            component=self._component,
            debug_info=self._build_debug_info(node))

    # Helper functions sorted alphabetically

    def _build_arguments(self, node):
        def build_argument(node, index):
            assert node.GetClass() == 'Argument'
            child_nodes = list(node.GetChildren())
            is_optional = bool(node.GetProperty('OPTIONAL'))
            is_variadic = bool(self._take_is_variadic_argument(child_nodes))
            # The parser may place extended attributes on arguments, but they
            # should be applied to types.
            extended_attributes = self._take_extended_attributes(child_nodes)
            idl_type = self._take_type(
                child_nodes,
                is_optional=is_optional,
                is_variadic=is_variadic,
                extended_attributes=extended_attributes)
            default_value = self._take_default_value(child_nodes)
            assert not child_nodes
            return Argument.IR(
                identifier=Identifier(node.GetName()),
                index=index,
                idl_type=idl_type,
                default_value=default_value)

        assert node.GetClass() == 'Arguments'
        return [
            build_argument(node, i)
            for i, node in enumerate(node.GetChildren())
        ]

    def _build_constant_value(self, node):
        assert node.GetClass() == 'Value'
        return self._build_literal_constant(node)

    def _build_debug_info(self, node):
        return DebugInfo(
            location=Location(
                filepath=node.GetProperty('FILENAME'),
                line_number=node.GetProperty('LINENO'),
                position=node.GetProperty('POSITION')))

    def _build_default_value(self, node):
        assert node.GetClass() == 'Default'
        return self._build_literal_constant(node)

    def _build_extended_attributes(self, node):
        def build_extended_attribute(node):
            key = node.GetName()
            values = node.GetProperty('VALUE', default=None)
            arguments = None
            name = None

            child_nodes = node.GetChildren()
            if child_nodes:
                assert len(child_nodes) == 1
                child = child_nodes[0]
                if child.GetClass() == 'Arguments':
                    arguments = list(
                        map(build_extattr_argument, child.GetChildren()))
                elif child.GetClass() == 'Call':
                    assert len(child.GetChildren()) == 1
                    grand_child = child.GetChildren()[0]
                    assert grand_child.GetClass() == 'Arguments'
                    # ExtendedAttribute is not designed to represent an
                    # operation, especially a complicated argument list.
                    # Discard the arguments.
                    arguments = ()
                    name = child.GetName()

            return ExtendedAttribute(
                key=key, values=values, arguments=arguments, name=name)

        def build_extattr_argument(node):
            assert node.GetClass() == 'Argument'

            child_nodes = node.GetChildren()
            assert len(child_nodes) == 1
            assert child_nodes[0].GetClass() == 'Type'

            type_node = child_nodes[0]
            type_children = type_node.GetChildren()
            assert len(type_children) == 1

            return (type_children[0].GetName(), node.GetName())

        assert node.GetClass() == 'ExtAttributes'
        return ExtendedAttributes(
            list(
                filter(None, map(build_extended_attribute,
                                 node.GetChildren()))))

    def _build_inheritance(self, node):
        assert node.GetClass() == 'Inherit'
        return self._create_ref_to_idl_def(
            Identifier(node.GetName()), self._build_debug_info(node))

    def _build_is_variadic_argument(self, node):
        # idl_parser produces the following tree to indicate an argument is
        # variadic.
        #   Arguments
        #     := [Argument, Argument, ...]
        #   Argument
        #     := [Type, Argument(Name='...')]  # Argument inside Argument
        assert node.GetClass() == 'Argument'
        assert node.GetName() == '...'
        return True

    def _build_iterable(self, node):
        assert node.GetClass() == 'Iterable'
        types = list(map(self._build_type, node.GetChildren()))
        assert len(types) == 1 or len(types) == 2
        if len(types) == 1:  # value iterator
            key_type, value_type = (None, types[0])
            operations = None
        else:  # pair iterator
            key_type, value_type = types
            iter_ops = self._create_iterator_operations(node)
            iter_ops[Identifier('entries')].is_iterator = True
            operations = list(iter_ops.values())
        return Iterable.IR(
            key_type=key_type,
            value_type=value_type,
            operations=operations,
            debug_info=self._build_debug_info(node))

    def _build_literal_constant(self, node):
        assert not node.GetChildren()

        type_token = node.GetProperty('TYPE')
        value_token = node.GetProperty('VALUE')

        debug_info = self._build_debug_info(node)
        factory = self._idl_type_factory

        if type_token == 'NULL':
            idl_type = factory.nullable_type(
                inner_type=factory.simple_type(
                    name='any', debug_info=debug_info),
                debug_info=debug_info)
            assert value_token == 'NULL'
            value = None
            literal = 'null'
        elif type_token == 'boolean':
            idl_type = factory.simple_type(
                name='boolean', debug_info=debug_info)
            assert isinstance(value_token, bool)
            value = value_token
            literal = 'true' if value else 'false'
        elif type_token == 'integer':
            idl_type = factory.simple_type(name='long', debug_info=debug_info)
            assert isinstance(value_token, str)
            value = long(value_token, base=0)
            literal = value_token
        elif type_token == 'float':
            idl_type = factory.simple_type(
                name='double', debug_info=debug_info)
            assert isinstance(value_token, str)
            value = float(value_token)
            literal = value_token
        elif type_token == 'DOMString':
            idl_type = factory.simple_type(
                name='DOMString', debug_info=debug_info)
            assert isinstance(value_token, str)
            value = value_token
            literal = '"{}"'.format(value)
        elif type_token == 'sequence':
            idl_type = factory.sequence_type(
                element_type=factory.simple_type(
                    name='any', debug_info=debug_info),
                debug_info=debug_info)
            assert value_token == '[]'
            value = []
            literal = '[]'
        elif type_token == 'dictionary':
            idl_type = factory.simple_type(
                name='object', debug_info=debug_info)
            assert value_token == '{}'
            value = dict()
            literal = '{}'
        else:
            assert False, "Unknown literal type: {}".format(type_token)

        return LiteralConstant(idl_type=idl_type, value=value, literal=literal)

    def _build_maplike(self, node, interface_identifier):
        assert node.GetClass() == 'Maplike'
        assert isinstance(interface_identifier, Identifier)
        types = list(map(self._build_type, node.GetChildren()))
        assert len(types) == 2
        key_type, value_type = types
        is_readonly = bool(node.GetProperty('READONLY'))
        attributes = [
            self._create_attribute(
                Identifier('size'),
                'unsigned long',
                is_readonly=True,
                node=node),
        ]
        iter_map = self._create_iterator_operations(node)
        iter_map[Identifier('entries')].is_iterator = True
        iter_ops = list(iter_map.values())
        read_ops = [
            self._create_operation(
                Identifier('get'),
                arguments=self._create_arguments([
                    (Identifier('key'), key_type),
                ]),
                return_type=value_type,
                extended_attributes={
                    'CallWith': 'ScriptState',
                    'RaisesException': None,
                    'ImplementedAs': 'getForBinding',
                },
                node=node),
            self._create_operation(
                Identifier('has'),
                arguments=self._create_arguments([
                    (Identifier('key'), key_type),
                ]),
                return_type='boolean',
                extended_attributes={
                    'CallWith': 'ScriptState',
                    'RaisesException': None,
                    'ImplementedAs': 'hasForBinding',
                },
                node=node),
        ]
        write_ops = [
            self._create_operation(
                Identifier('set'),
                arguments=self._create_arguments([
                    (Identifier('key'), key_type),
                    (Identifier('value'), value_type),
                ]),
                return_type=interface_identifier,
                extended_attributes={
                    'CallWith': 'ScriptState',
                    'RaisesException': None,
                    'ImplementedAs': 'setForBinding',
                },
                node=node),
            self._create_operation(
                Identifier('delete'),
                arguments=self._create_arguments([
                    (Identifier('key'), key_type),
                ]),
                return_type='boolean',
                extended_attributes={
                    'CallWith': 'ScriptState',
                    'RaisesException': None,
                    'ImplementedAs': 'deleteForBinding',
                },
                node=node),
            self._create_operation(
                Identifier('clear'),
                extended_attributes={
                    'CallWith': 'ScriptState',
                    'RaisesException': None,
                    'ImplementedAs': 'clearForBinding',
                },
                node=node),
        ]
        for op in write_ops:
            op.is_optionally_defined = True
        if is_readonly:
            operations = iter_ops + read_ops
        else:
            operations = iter_ops + read_ops + write_ops
        return Maplike.IR(
            key_type=key_type,
            value_type=value_type,
            is_readonly=is_readonly,
            attributes=attributes,
            operations=operations,
            debug_info=self._build_debug_info(node))

    def _build_setlike(self, node, interface_identifier):
        assert node.GetClass() == 'Setlike'
        assert isinstance(interface_identifier, Identifier)
        types = list(map(self._build_type, node.GetChildren()))
        assert len(types) == 1
        value_type = types[0]
        is_readonly = bool(node.GetProperty('READONLY'))
        attributes = [
            self._create_attribute(
                Identifier('size'),
                'unsigned long',
                is_readonly=True,
                node=node),
        ]
        iter_map = self._create_iterator_operations(node)
        iter_map[Identifier('values')].is_iterator = True
        iter_ops = list(iter_map.values())
        read_ops = [
            self._create_operation(
                Identifier('has'),
                arguments=self._create_arguments([
                    (Identifier('value'), value_type),
                ]),
                return_type='boolean',
                extended_attributes={
                    'CallWith': 'ScriptState',
                    'RaisesException': None,
                    'ImplementedAs': 'hasForBinding',
                },
                node=node),
        ]
        write_ops = [
            self._create_operation(
                Identifier('add'),
                arguments=self._create_arguments([
                    (Identifier('value'), value_type),
                ]),
                return_type=interface_identifier,
                extended_attributes={
                    'CallWith': 'ScriptState',
                    'RaisesException': None,
                    'ImplementedAs': 'addForBinding',
                },
                node=node),
            self._create_operation(
                Identifier('delete'),
                arguments=self._create_arguments([
                    (Identifier('value'), value_type),
                ]),
                return_type='boolean',
                extended_attributes={
                    'CallWith': 'ScriptState',
                    'RaisesException': None,
                    'ImplementedAs': 'deleteForBinding',
                },
                node=node),
            self._create_operation(
                Identifier('clear'),
                extended_attributes={
                    'CallWith': 'ScriptState',
                    'RaisesException': None,
                    'ImplementedAs': 'clearForBinding',
                },
                node=node),
        ]
        for op in write_ops:
            op.is_optionally_defined = True
        if is_readonly:
            operations = iter_ops + read_ops
        else:
            operations = iter_ops + read_ops + write_ops
        return Setlike.IR(
            value_type=value_type,
            is_readonly=is_readonly,
            attributes=attributes,
            operations=operations,
            debug_info=self._build_debug_info(node))

    def _build_stringifier(self, node):
        # There are three forms of stringifier declaration;
        #   a. [ExtAttrs] stringifier;
        #   b. [ExtAttrs] stringifier DOMString foo();
        #   c. [ExtAttrs] stringifier attribute DOMString bar;
        # and we apply [ExtAttrs] to an operation in cases a and b, or to an
        # attribute in case c.

        assert node.GetClass() == 'Stringifier'
        child_nodes = node.GetChildren()
        extended_attributes = self._take_extended_attributes(child_nodes)
        assert len(child_nodes) <= 1

        member = None
        if len(child_nodes) == 1:
            member = self._build_interface_member(
                child_nodes[0],
                fallback_extended_attributes=extended_attributes)
            extended_attributes = None
        operation = member if isinstance(member, Operation.IR) else None
        attribute = member if isinstance(member, Attribute.IR) else None

        if operation is None:
            return_type = self._idl_type_factory.simple_type(
                name='DOMString', debug_info=self._build_debug_info(node))
            operation = Operation.IR(
                identifier=Identifier(''),
                arguments=[],
                return_type=return_type,
                extended_attributes=extended_attributes,
                component=self._component,
                debug_info=self._build_debug_info(node))
        operation.is_stringifier = True
        if attribute:
            operation.stringifier_attribute = attribute.identifier
            return (operation, attribute)
        else:
            return (operation, )

    def _build_type(self,
                    node,
                    is_optional=False,
                    is_variadic=False,
                    extended_attributes=None):
        assert node.GetClass() == 'Type'
        assert not (is_optional and is_variadic)
        idl_type = self._build_type_internal(
            node.GetChildren(),
            is_optional=is_optional,
            extended_attributes=extended_attributes)
        if node.GetProperty('NULLABLE'):
            idl_type = self._idl_type_factory.nullable_type(
                idl_type,
                is_optional=is_optional,
                debug_info=self._build_debug_info(node))
        if is_variadic:
            idl_type = self._idl_type_factory.variadic_type(
                idl_type, debug_info=self._build_debug_info(node))
        return idl_type

    def _build_type_internal(self,
                             nodes,
                             is_optional=False,
                             extended_attributes=None):
        """
        Args:
            nodes: The child nodes of a 'Type' node.
        """

        def build_frozen_array_type(node, extended_attributes):
            assert len(node.GetChildren()) == 1
            return self._idl_type_factory.frozen_array_type(
                element_type=self._build_type(node.GetChildren()[0]),
                is_optional=is_optional,
                extended_attributes=extended_attributes,
                debug_info=self._build_debug_info(node))

        def build_promise_type(node, extended_attributes):
            assert len(node.GetChildren()) == 1
            return self._idl_type_factory.promise_type(
                result_type=self._build_type(node.GetChildren()[0]),
                is_optional=is_optional,
                extended_attributes=extended_attributes,
                debug_info=self._build_debug_info(node))

        def build_union_type(node, extended_attributes):
            return self._idl_type_factory.union_type(
                member_types=list(map(self._build_type, node.GetChildren())),
                is_optional=is_optional,
                extended_attributes=extended_attributes,
                debug_info=self._build_debug_info(node))

        def build_record_type(node, extended_attributes):
            key_node, value_node = node.GetChildren()
            return self._idl_type_factory.record_type(
                # idl_parser doesn't produce a 'Type' node for the key type,
                # hence we need to skip one level.
                key_type=self._build_type_internal([key_node]),
                value_type=self._build_type(value_node),
                is_optional=is_optional,
                extended_attributes=extended_attributes,
                debug_info=self._build_debug_info(node))

        def build_reference_type(node, extended_attributes):
            return self._idl_type_factory.reference_type(
                Identifier(node.GetName()),
                is_optional=is_optional,
                extended_attributes=extended_attributes,
                debug_info=self._build_debug_info(node))

        def build_sequence_type(node, extended_attributes):
            return self._idl_type_factory.sequence_type(
                element_type=self._build_type(node.GetChildren()[0]),
                is_optional=is_optional,
                extended_attributes=extended_attributes,
                debug_info=self._build_debug_info(node))

        def build_simple_type(node, extended_attributes):
            name = node.GetName()
            if name is None:
                assert node.GetClass() == 'Any'
                name = node.GetClass().lower()
            if node.GetProperty('UNRESTRICTED'):
                name = 'unrestricted {}'.format(name)
            return self._idl_type_factory.simple_type(
                name=name,
                is_optional=is_optional,
                extended_attributes=extended_attributes,
                debug_info=self._build_debug_info(node))

        type_nodes = list(nodes)
        ext_attrs1 = extended_attributes
        ext_attrs2 = self._take_extended_attributes(type_nodes)
        if ext_attrs1 and ext_attrs2:
            extended_attributes = ExtendedAttributes(
                list(ext_attrs1) + list(ext_attrs2))
        else:
            extended_attributes = ext_attrs1 or ext_attrs2
        assert len(type_nodes) == 1
        body_node = type_nodes[0]

        buffer_source_types = set([
            'ArrayBuffer',
            'ArrayBufferView',  # Blink-specific ArrayBufferView definition
            'DataView',
            'Int8Array',
            'Int16Array',
            'Int32Array',
            'Uint8Array',
            'Uint16Array',
            'Uint32Array',
            'Uint8ClampedArray',
            'Float32Array',
            'Float64Array',
        ])
        if body_node.GetName() in buffer_source_types:
            return build_simple_type(
                body_node, extended_attributes=extended_attributes)

        build_functions = {
            'Any': build_simple_type,
            'FrozenArray': build_frozen_array_type,
            'PrimitiveType': build_simple_type,
            'Promise': build_promise_type,
            'Record': build_record_type,
            'Sequence': build_sequence_type,
            'StringType': build_simple_type,
            'Typeref': build_reference_type,
            'UnionType': build_union_type,
        }
        return build_functions[body_node.GetClass()](
            body_node, extended_attributes=extended_attributes)

    def _create_arguments(self, args):
        """
        Constructs a list of new instances of Argument.

        Args:
            args: A list of argument parameters.  Each argument parameter is
                a list of argument identifier, type name in str, and optional
                default value in str.
        """
        assert isinstance(args, (list, tuple))

        arguments = []
        index = 0
        for arg in args:
            assert isinstance(arg, (list, tuple))
            assert len(arg) == 2 or len(arg) == 3

            identifier = arg[0]
            if isinstance(arg[1], str):
                idl_type = self._create_type(
                    arg[1], is_optional=(len(arg) == 3))
            else:
                idl_type = arg[1]

            default_value = None
            if len(arg) == 3:
                default_value = self._create_literal_constant(arg[2])

            arguments.append(
                Argument.IR(
                    identifier,
                    index=index,
                    idl_type=idl_type,
                    default_value=default_value))

            index += 1

        return arguments

    def _create_attribute(self,
                          identifier,
                          idl_type,
                          is_readonly=False,
                          extended_attributes=None,
                          node=None):
        """Constructs a new Attribute.IR from simple parameters."""
        if isinstance(idl_type, str):
            idl_type = self._create_type(idl_type)
        if isinstance(extended_attributes, dict):
            extended_attributes = self._create_extended_attributes(
                extended_attributes)
        debug_info = self._build_debug_info(node) if node else None

        return Attribute.IR(
            identifier,
            idl_type=idl_type,
            is_readonly=is_readonly,
            extended_attributes=extended_attributes,
            component=self._component,
            debug_info=debug_info)

    def _create_extended_attributes(self, key_values):
        """
        Constructs a new ExtendedAttributes from a dict of key and values.
        """
        assert isinstance(key_values, dict)

        return ExtendedAttributes([
            ExtendedAttribute(key=key, values=values)
            for key, values in key_values.items()
        ])

    def _create_iterator_operations(self, node):
        """Constructs a set of iterator operations."""
        return {
            Identifier('forEach'):
            self._create_operation(
                Identifier('forEach'),
                arguments=self._create_arguments([
                    (Identifier('callback'),
                     Identifier('ForEachIteratorCallback')),
                    (Identifier('thisArg'), 'any', 'null'),
                ]),
                extended_attributes={
                    'CallWith': ('ScriptState', 'ThisValue'),
                    'RaisesException': None,
                    'ImplementedAs': 'forEachForBinding',
                },
                node=node),
            Identifier('entries'):
            self._create_operation(
                Identifier('entries'),
                return_type=Identifier('Iterator'),
                extended_attributes={
                    'CallWith': 'ScriptState',
                    'RaisesException': None,
                    'ImplementedAs': 'entriesForBinding',
                },
                node=node),
            Identifier('keys'):
            self._create_operation(
                Identifier('keys'),
                return_type=Identifier('Iterator'),
                extended_attributes={
                    'CallWith': 'ScriptState',
                    'RaisesException': None,
                    'ImplementedAs': 'keysForBinding',
                },
                node=node),
            Identifier('values'):
            self._create_operation(
                Identifier('values'),
                return_type=Identifier('Iterator'),
                extended_attributes={
                    'CallWith': 'ScriptState',
                    'RaisesException': None,
                    'ImplementedAs': 'valuesForBinding',
                },
                node=node),
        }

    def _create_literal_constant(self, token):
        factory = self._idl_type_factory
        if token == 'null':
            return LiteralConstant(
                idl_type=factory.nullable_type(
                    inner_type=factory.simple_type(name='any')),
                value=None,
                literal='null')
        else:
            assert False

    def _create_operation(self,
                          identifier,
                          arguments=None,
                          return_type=None,
                          extended_attributes=None,
                          node=None):
        """Constructs a new Operation.IR from simple parameters."""
        if not return_type:
            return_type = self._create_type('void')
        elif isinstance(return_type, str):
            return_type = self._create_type(return_type)
        if isinstance(extended_attributes, dict):
            extended_attributes = self._create_extended_attributes(
                extended_attributes)
        debug_info = self._build_debug_info(node) if node else None

        return Operation.IR(
            identifier,
            arguments=(arguments or []),
            return_type=return_type,
            extended_attributes=extended_attributes,
            component=self._component,
            debug_info=debug_info)

    def _create_type(self, keyword_or_identifier, **kwargs):
        """Constructs a new IdlType from a type keyword or identifier."""
        name = keyword_or_identifier
        if isinstance(name, Identifier):
            return self._idl_type_factory.reference_type(name, **kwargs)
        elif isinstance(name, str):
            return self._idl_type_factory.simple_type(name, **kwargs)
        else:
            assert False

    def _take_and_build(self, node_class, build_func, node_list, **kwargs):
        """
        Takes a node of |node_class| from |node_list| if any, and then builds
        and returns an IR.  The processed node is removed from |node_list|.
        Returns None if not found.
        """
        for node in node_list:
            if node.GetClass() == node_class:
                node_list.remove(node)
                return build_func(node, **kwargs)
        return None

    def _take_arguments(self, node_list):
        return self._take_and_build('Arguments', self._build_arguments,
                                    node_list)

    def _take_constant_value(self, node_list):
        return self._take_and_build('Value', self._build_constant_value,
                                    node_list)

    def _take_default_value(self, node_list):
        return self._take_and_build('Default', self._build_default_value,
                                    node_list)

    def _take_extended_attributes(self, node_list):
        return self._take_and_build('ExtAttributes',
                                    self._build_extended_attributes, node_list)

    def _take_inheritance(self, node_list):
        return self._take_and_build('Inherit', self._build_inheritance,
                                    node_list)

    def _take_is_variadic_argument(self, node_list):
        return self._take_and_build(
            'Argument', self._build_is_variadic_argument, node_list)

    def _take_iterable(self, node_list):
        return self._take_and_build('Iterable', self._build_iterable,
                                    node_list)

    def _take_maplike(self, node_list, **kwargs):
        return self._take_and_build('Maplike', self._build_maplike, node_list,
                                    **kwargs)

    def _take_setlike(self, node_list, **kwargs):
        return self._take_and_build('Setlike', self._build_setlike, node_list,
                                    **kwargs)

    def _take_stringifier(self, node_list):
        return self._take_and_build('Stringifier', self._build_stringifier,
                                    node_list)

    def _take_type(self, node_list, **kwargs):
        return self._take_and_build('Type', self._build_type, node_list,
                                    **kwargs)
