#!/usr/bin/env python

from dsl import ops, gen_compiler, gen_disassembler, gen_vm

GLACIER_OPS = [
    ops.GlacierVMHeaderOp(
        "struct_def",
        [
            ops.GlacierVMArg("type_id", ops.GlacierVMArgType.BIT_32),
            ops.GlacierVMEnumeratedArg("member_id", ops.GlacierVMArgType.BIT_8),
        ],
    ),
    ops.GlacierVMOp(
        "function_def",
        [
            ops.GlacierVMArg("function_id", ops.GlacierVMArgType.BIT_64),
            ops.GlacierVMArg("num_args", ops.GlacierVMArgType.BIT_8),
        ],
    ),
    ops.GlacierVMOp("set_var", [ops.GlacierVMArg("variable_id", ops.GlacierVMArgType.BIT_8)]),
    ops.GlacierVMOp("get_var", [ops.GlacierVMArg("variable_id", ops.GlacierVMArgType.BIT_8)]),
    ops.GlacierVMOp("call_func", [ops.GlacierVMArg("function_id", ops.GlacierVMArgType.BIT_64)]),
    ops.GlacierVMOp("return", []),
    ops.GlacierVMOp("return_val", []),
    ops.GlacierVMOp("add", []),
    ops.GlacierVMOp("int", [ops.GlacierVMArg("value", ops.GlacierVMArgType.BIT_64)]),
    ops.GlacierVMOp("string", [ops.GlacierVMEnumeratedArg("bytes", ops.GlacierVMArgType.CHAR)]),
    ops.GlacierVMOp("subtract", []),
    ops.GlacierVMOp("multiply", []),
    ops.GlacierVMOp("divide", []),
    ops.GlacierVMHeaderOp(
        "function_jmp",
        [
            ops.GlacierVMArg("function_id", ops.GlacierVMArgType.BIT_64),
            ops.GlacierVMArg("offset", ops.GlacierVMArgType.BIT_32),
        ],
    ),
    ops.GlacierVMOp("header_end", []),
    ops.GlacierVMOp("print", []),
    ops.GlacierVMOp("eq", []),
    ops.GlacierVMOp("jump_if_true", [ops.GlacierVMArg("offset", ops.GlacierVMArgType.BIT_32)]),
    ops.GlacierVMOp("jump_if_false", [ops.GlacierVMArg("offset", ops.GlacierVMArgType.BIT_32)]),
    ops.GlacierVMOp("jump", [ops.GlacierVMArg("offset", ops.GlacierVMArgType.BIT_32)]),
    ops.GlacierVMOp("struct", [ops.GlacierVMArg("struct_id", ops.GlacierVMArgType.BIT_16)]),
    ops.GlacierVMOp(
        "get_struct_member", [ops.GlacierVMArg("member_index", ops.GlacierVMArgType.BIT_8)]
    ),
    ops.GlacierVMOp(
        "set_struct_member", [ops.GlacierVMArg("member_index", ops.GlacierVMArgType.BIT_8)]
    ),
    ops.GlacierVMOp("lt", []),
    ops.GlacierVMOp("vec", [ops.GlacierVMArg("size", ops.GlacierVMArgType.BIT_8)]),
    ops.GlacierVMOp("vec_access", []),
    ops.GlacierVMOp("map", [ops.GlacierVMArg("size", ops.GlacierVMArgType.BIT_8)]),
    ops.GlacierVMOp("map_access", []),
    ops.GlacierVMOp("vec_push", []),
    ops.GlacierVMOp("vec_len", []),
    ops.GlacierVMOp("vec_pop", []),
    ops.GlacierVMOp("map_insert", []),
    ops.GlacierVMOp("read_str", []),
    ops.GlacierVMOp("read_int", []),
]

GLACIER_VM_SOURCE = "vm/Ops.h"
GLACIER_COMPILER_SOURCE = "compiler/ops.py"
GLACIER_DISASSEMBLER_SOURCE = "disassembler/ops.py"


def generate_vm():
    vm_source = gen_vm.gen_vm(GLACIER_OPS)
    with open(GLACIER_VM_SOURCE, "w") as f:
        f.write(vm_source)
    print("glacierdsl: Generated VM sources.")


def generate_compiler():
    compiler_source = gen_compiler.gen_compiler(GLACIER_OPS)
    with open(GLACIER_COMPILER_SOURCE, "w") as f:
        f.write(compiler_source)
    print("glacierdsl: Generated compiler sources.")


def generate_disassembler():
    disassembler_source = gen_disassembler.gen_disassembler(GLACIER_OPS)
    with open(GLACIER_DISASSEMBLER_SOURCE, "w") as f:
        f.write(disassembler_source)
    print("glacierdsl: Generated disassembler sources.")


def glacierdsl():
    generate_vm()
    generate_compiler()
    generate_disassembler()


if __name__ == "__main__":
    glacierdsl()
