#!/usr/bin/env python3
# Generate YAML spec.
#
# (c) Mit authors 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 yaml import dump

from code_util import Code, copyright_banner, unrestrict
from action import Action
from spec import (
    Instruction, Registers, MitErrorCode, Instructions, ExtraInstructions
)


GENERATOR_PROGRAM = 'gen-yaml-spec'
PURPOSE = 'Mit virtual machine specification.'
COPYRIGHT_YEARS = '1994-2020'

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

# Write YAML description.
# TODO: When we have PyYAML 5.1, use sort_keys=False
def action_spec(a):
    assert isinstance(a, Action)
    spec = {}
    if a.effect is not None:
        spec['args'] = [item.name for item in a.effect.args.items]
        spec['results'] = [item.name for item in a.effect.results.items]
    return spec

def extra_instruction_spec(i, code):
    spec = {
        'code': code,
        'action': action_spec(i),
    }
    return spec

def instruction_spec(i, opcode):
    assert isinstance(i, Instruction)
    spec = {
        'opcode': opcode,
        'action': action_spec(i.action),
    }
    if i.terminal is not None:
        spec['terminal'] = action_spec(i.terminal)
    return spec

print(dump({
    'ErrorCode': {e.name: e.value for e in MitErrorCode},
    'Registers': [r.name for r in Registers],
    'Instructions': {
        i.name: instruction_spec(i.action, i.opcode)
        for i in Instructions
    },
    'ExtraInstructions': {
        i.name: extra_instruction_spec(i.action, i.opcode)
        for i in ExtraInstructions
    },
}), end='')
