#!/usr/bin/env python3
# Generate trap code enums.
#
# (c) Mit authors 2018-2020
#
# The package is distributed under the MIT/X11 License.
#
# THIS PROGRAM IS PROVIDED AS IS, WITH NO WARRANTY. USE IS AT THE USER’S
# RISK.

from code_util import Code, copyright_banner
import stack
stack.TYPE_SIZE_UNKNOWN = 0

import traps


def enum_to_python(enum, value_extractor=lambda x: f"{x.value:#x}"):
    '''
    Convert an Enum to Python code; return a Code.
     - enum - an Enum subclass.
     - value_extractor - a function that takes an element `x` of `enum` and
       return an str. Defaults to `x.value` formatted as hex.
    '''
    class_name = enum.__name__
    code = Code("'''", enum.__doc__, "'''")
    for member in enum:
        code.append(f'{member.name} = {value_extractor(member)}')
    return Code(
        '@unique',
        f'class {class_name}(IntEnum):',
        code,
    )


code = Code()
GENERATOR_PROGRAM = 'gen-trap-enums'
PURPOSE = 'Trap code enumerations.'
COPYRIGHT_YEARS = '2018-2019'

code = copyright_banner(GENERATOR_PROGRAM, PURPOSE, COPYRIGHT_YEARS, comment='#')

code.append('''
from enum import Enum, IntEnum, unique
from .autonumber import AutoNumber
''')
code.append('')
code.append('')

lib_code = Code(
    "'''",
    traps.LibInstructions.__doc__,
    "'''",
    '''\
        def __init__(self, library, opcode):
            self.library = library
            self.opcode = opcode

        def __int__(self):
            return self.opcode
    ''',
)
lib_code.append('')
for lib in traps.LibInstructions:
    lib_code.append(f'{lib.name} = ({lib.library.__name__}, {lib.opcode:#x})')
    code.extend(enum_to_python(lib.library, lambda i: f"{i.opcode:#x}"))
    code.append('')
code.append('''\
    @unique
    class LibInstructions(Enum):
''')
code.append(lib_code)

print(code)
