#!/usr/bin/env python3
# Copyright (c) 2017 Google Inc.

# 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
#
#     http://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.
"""Generates language headers from a JSON grammar file"""

import errno
import json
import os.path
import re


def make_path_to_file(f):
    """Makes all ancestor directories to the given file, if they
    don't yet exist.

    Arguments:
        f: The file whose ancestor directories are to be created.
    """
    dir = os.path.dirname(os.path.abspath(f))
    try:
        os.makedirs(dir)
    except OSError as e:
        if e.errno == errno.EEXIST and os.path.isdir(dir):
            pass
        else:
            raise

class ExtInstGrammar:
    """The grammar for an extended instruction set"""

    def __init__(self, name, copyright, instructions, operand_kinds, version = None, revision = None):
       self.name = name
       self.copyright = copyright
       self.instructions = instructions
       self.operand_kinds = operand_kinds
       self.version = version
       self.revision = revision


class LangGenerator:
    """A language-specific generator"""

    def __init__(self):
        self.upper_case_initial = re.compile('^[A-Z]')
        pass

    def comment_prefix(self):
        return ""

    def namespace_prefix(self):
        return ""

    def uses_guards(self):
        return False

    def cpp_guard_preamble(self):
        return ""

    def cpp_guard_postamble(self):
        return ""

    def enum_value(self, prefix, name, value):
        if self.upper_case_initial.match(name):
            use_name = name
        else:
            use_name = '_' + name

        return "    {}{} = {},".format(prefix, use_name, value)

    def generate(self, grammar):
        """Returns a string that is the language-specific header for the given grammar"""

        parts = []
        if grammar.copyright:
            parts.extend(["{}{}".format(self.comment_prefix(), f) for f in grammar.copyright])
        parts.append('')

        guard = 'SPIRV_EXTINST_{}_H_'.format(grammar.name)
        if self.uses_guards:
            parts.append('#ifndef {}'.format(guard))
            parts.append('#define {}'.format(guard))
        parts.append('')

        parts.append(self.cpp_guard_preamble())

        if grammar.version:
            parts.append(self.const_definition(grammar.name, 'Version', grammar.version))

        if grammar.revision is not None:
            parts.append(self.const_definition(grammar.name, 'Revision', grammar.revision))

        parts.append('')

        if grammar.instructions:
            parts.append(self.enum_prefix(grammar.name, 'Instructions'))
            for inst in grammar.instructions:
                parts.append(self.enum_value(grammar.name, inst['opname'], inst['opcode']))
            parts.append(self.enum_end(grammar.name, 'Instructions'))
            parts.append('')

        if grammar.operand_kinds:
            for kind in grammar.operand_kinds:
                parts.append(self.enum_prefix(grammar.name, kind['kind']))
                for e in kind['enumerants']:
                    parts.append(self.enum_value(grammar.name, e['enumerant'], e['value']))
                parts.append(self.enum_end(grammar.name, kind['kind']))
            parts.append('')

        parts.append(self.cpp_guard_postamble())

        if self.uses_guards:
            parts.append('#endif // {}'.format(guard))

        return '\n'.join(parts)


class CLikeGenerator(LangGenerator):
    def uses_guards(self):
        return True

    def comment_prefix(self):
        return "// "

    def const_definition(self, prefix, var, value):
        # Use an anonymous enum.  Don't use a static const int variable because
        # that can bloat binary size.
        return 'enum {0} {1}{2} = {3}, {1}{2}_BitWidthPadding = 0x7fffffff {4};'.format(
               '{', prefix, var, value, '}')

    def enum_prefix(self, prefix, name):
        return 'enum {}{} {}'.format(prefix, name, '{')

    def enum_end(self, prefix, enum):
        return '    {}{}Max = 0x7ffffff\n{};\n'.format(prefix, enum, '}')

    def cpp_guard_preamble(self):
        return '#ifdef __cplusplus\nextern "C" {\n#endif\n'

    def cpp_guard_postamble(self):
        return '#ifdef __cplusplus\n}\n#endif\n'


class CGenerator(CLikeGenerator):
    pass


def main():
    import argparse
    parser = argparse.ArgumentParser(description='Generate language headers from a JSON grammar')

    parser.add_argument('--extinst-grammar', metavar='<path>',
                        type=str, required=True,
                        help='input JSON grammar file for extended instruction set')
    parser.add_argument('--extinst-output-path', metavar='<path>',
                        type=str, required=True,
                        help='Path of the language-specific output file.')
    args = parser.parse_args()

    with open(args.extinst_grammar) as json_file:
        grammar_json = json.loads(json_file.read())
        grammar_name = os.path.splitext(os.path.basename(args.extinst_output_path))[0]
        grammar = ExtInstGrammar(name = grammar_name,
                                 copyright = grammar_json['copyright'],
                                 instructions = grammar_json['instructions'],
                                 operand_kinds = grammar_json['operand_kinds'],
                                 version = grammar_json['version'],
                                 revision = grammar_json['revision'])
        make_path_to_file(args.extinst_output_path)
        with open(args.extinst_output_path, 'w') as f:
            f.write(CGenerator().generate(grammar))


if __name__ == '__main__':
    main()
