#!/usr/bin/env python
#
# Copyright (c) 2014-2016 Apple Inc. All rights reserved.
# Copyright (c) 2014 University of Washington. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.


import logging
import re
import string
from string import Template

from builtins_generator import BuiltinsGenerator
from builtins_templates import BuiltinsGeneratorTemplates as Templates


def get_var_name(function):
    var_name = function.function_name
    if function.is_constructor:
        return var_name[:1].lower() + var_name[1:] + 'Constructor'
    return var_name

log = logging.getLogger('global')

class BuiltinsCombinedHeaderGenerator(BuiltinsGenerator):
    def __init__(self, model):
        BuiltinsGenerator.__init__(self, model)

    def output_filename(self):
        return "%sBuiltins.h" % self.model().framework.setting('namespace')

    def generate_output(self):
        args = {
            'namespace': self.model().framework.setting('namespace'),
            'macroPrefix': self.model().framework.setting('macro_prefix'),
        }

        sections = []
        sections.append(self.generate_license())
        sections.append(Template(Templates.DoNotEditWarning).substitute(args))
        sections.append(Template(Templates.HeaderIncludeGuard).substitute(args))
        sections.append(self.generate_forward_declarations())
        sections.append(Template(Templates.NamespaceTop).substitute(args))
        sections.append("extern const char s_%(namespace)sCombinedCode[];" % args);
        sections.append("extern const unsigned s_%(namespace)sCombinedCodeLength;" % args);
        for object in self.model().objects:
            sections.append(self.generate_section_for_object(object))
        sections.append(self.generate_section_for_code_table_macro())
        sections.append(self.generate_section_for_code_name_macro())
        sections.append(self.generate_section_for_global_private_code_name_macro())
        sections.append(Template(Templates.CombinedHeaderStaticMacros).substitute(args))
        sections.append(Template(Templates.NamespaceBottom).substitute(args))

        return "\n\n".join(sections)

    def generate_forward_declarations(self):
        return """namespace JSC {
class FunctionExecutable;
class VM;

enum class ConstructAbility : uint8_t;
enum class ConstructorKind : uint8_t;
}"""

    def generate_section_for_object(self, object):
        lines = []
        lines.append('/* %s */' % object.object_name)
        lines.extend(self.generate_externs_for_object(object))
        lines.append("")
        lines.extend(self.generate_macros_for_object(object))
        return '\n'.join(lines)

    def generate_externs_for_object(self, object):
        lines = []

        for function in object.functions:
            function_args = {
                'codeName': BuiltinsGenerator.mangledNameForFunction(function) + 'Code',
            }

            lines.append("""extern const char* const s_%(codeName)s;
extern const int s_%(codeName)sLength;
extern const JSC::ConstructAbility s_%(codeName)sConstructAbility;
extern const JSC::ConstructorKind s_%(codeName)sConstructorKind;""" % function_args)

        return lines

    def generate_macros_for_object(self, object):
        args = {
            'macroPrefix': self.model().framework.setting('macro_prefix'),
            'objectMacro': object.object_name.replace('.', '').upper(),
        }

        lines = []
        lines.append("#define %(macroPrefix)s_FOREACH_%(objectMacro)s_BUILTIN_DATA(macro) \\" % args)
        for function in object.functions:
            function_args = {
                'funcName': function.function_name,
                'mangledName': BuiltinsGenerator.mangledNameForFunction(function),
                'paramCount': len(function.parameters),
            }

            lines.append("    macro(%(funcName)s, %(mangledName)s, %(paramCount)d) \\" % function_args)
        return lines

    def generate_section_for_code_table_macro(self):
        args = {
            'macroPrefix': self.model().framework.setting('macro_prefix'),
        }

        lines = []
        lines.append("#define %(macroPrefix)s_FOREACH_BUILTIN_CODE(macro) \\" % args)
        for function in self.model().all_functions():
            function_args = {
                'funcName': function.function_name,
                'overriddenName': function.overridden_name,
                'codeName': BuiltinsGenerator.mangledNameForFunction(function) + 'Code',
            }

            lines.append("    macro(%(codeName)s, %(funcName)s, %(overriddenName)s, s_%(codeName)sLength) \\" % function_args)
        return '\n'.join(lines)

    def generate_section_for_code_name_macro(self):
        args = {
            'macroPrefix': self.model().framework.setting('macro_prefix'),
        }

        internal_function_names = [function.function_name for function in self.model().all_internal_functions()]
        if len(internal_function_names) != len(set(internal_function_names)):
            log.error("There are several internal functions with the same name. Private identifiers may clash.")

        lines = []
        lines.append("#define %(macroPrefix)s_FOREACH_BUILTIN_FUNCTION_NAME(macro) \\" % args)
        unique_names = list(set([function.function_name for function in self.model().all_functions()]))
        unique_names.sort()
        for function_name in unique_names:
            function_args = {
                'funcName': function_name,
            }

            lines.append("    macro(%(funcName)s) \\" % function_args)
        return '\n'.join(lines)

    def generate_section_for_global_private_code_name_macro(self):
        args = {
            'macroPrefix': self.model().framework.setting('macro_prefix'),
        }

        lines = []
        lines.append("#define %(macroPrefix)s_FOREACH_BUILTIN_FUNCTION_PRIVATE_GLOBAL_NAME(macro) \\" % args)
        functions = [function for function in self.model().all_functions() if function.is_global_private]
        functions.sort(key=lambda x: x.function_name)
        for function in functions:
            function_args = {
                'varName': get_var_name(function),
                'funcName': function.function_name,
                'codeName': BuiltinsGenerator.mangledNameForFunction(function),
            }

            lines.append("    macro(%(varName)s, %(funcName)s, %(codeName)s) \\" % function_args)

        return '\n'.join(lines)
