#pragma once
#include "inst.hpp"
#include "regs.hpp"
#include "scope.hpp"
#include "common.hpp"
#include <vector>


class Program {
    private:
        std::vector<const Inst*> lines;
        std::vector<const char*> pushes; // all register pushes (stack has no iterators)
        Regs regs;

        static width_t min_width(uint64_t);
        static const char* width_decl(width_t);
        static const char* cmp_decl(Token::cmp_t, bool);
        const char* replace_regs(const Scope*, const char*) const;

        bool peek(Token::op_t, std::vector<const Inst*>::const_iterator) const;
        bool min_width(const Scope*, const Token*, width_t&, width_t&) const;
        bool op_width(const Scope*, const Token*, const Token*, bool, bool, width_t&, width_t&) const;
        bool val2str(const Scope*, const Token*, width_t, bool, bool, bool, reg_id_t, char*) const;

        bool interpret_comment(std::vector<const Inst*>::iterator&);
        bool interpret_line(Scope*, std::vector<const Inst*>::iterator&);
        bool interpret_block(Scope*, std::vector<const Inst*>::iterator&);

    public:
        // TODO: destructor/cleanups
        void push(Inst*);
        bool interpret();
};