#include "instruction.hpp"

static void print_indent(int n, std::ostream& to) {
    while(n--) to << "  ";
}

void instruction_pushint::print(int indent, std::ostream& to) const {
    print_indent(indent, to);
    to << "PushInt(" << value << ")" << std::endl;
}

void instruction_pushglobal::print(int indent, std::ostream& to) const {
    print_indent(indent, to);
    to << "PushGlobal(" << name << ")" << std::endl;
}

void instruction_push::print(int indent, std::ostream& to) const {
    print_indent(indent, to);
    to << "Push(" << offset << ")" << std::endl;
}

void instruction_pop::print(int indent, std::ostream& to) const {
    print_indent(indent, to);
    to << "Pop(" << count << ")" << std::endl;
}

void instruction_mkapp::print(int indent, std::ostream& to) const {
    print_indent(indent, to);
    to << "MkApp()" << std::endl;
}

void instruction_update::print(int indent, std::ostream& to) const {
    print_indent(indent, to);
    to << "Update(" << offset << ")" << std::endl;
}

void instruction_pack::print(int indent, std::ostream& to) const {
    print_indent(indent, to);
    to << "Pack(" << tag << ", " << size << ")" << std::endl;
}

void instruction_split::print(int indent, std::ostream& to) const {
    print_indent(indent, to);
    to << "Split()" << std::endl;
}

void instruction_jump::print(int indent, std::ostream& to) const {
    print_indent(indent, to);
    to << "Jump(" << std::endl;
    for(auto& instruction_set : branches) {
        for(auto& instruction : instruction_set) {
            instruction->print(indent + 2, to);
        }
        to << std::endl;
    }
    print_indent(indent, to);
    to << ")" << std::endl;
}

void instruction_slide::print(int indent, std::ostream& to) const {
    print_indent(indent, to);
    to << "Slide(" << offset << ")" << std::endl;
}

void instruction_binop::print(int indent, std::ostream& to) const {
    print_indent(indent, to);
    to << "BinOp(" << op_action(op) << ")" << std::endl;
}

void instruction_eval::print(int indent, std::ostream& to) const {
    print_indent(indent, to);
    to << "Eval()" << std::endl;
}

void instruction_alloc::print(int indent, std::ostream& to) const {
    print_indent(indent, to);
    to << "Alloc(" << amount << ")" << std::endl;
}

void instruction_unwind::print(int indent, std::ostream& to) const {
    print_indent(indent, to);
    to << "Unwind()" << std::endl;
}
