
/* 
 * File:   VM_Command.h
 * Author: myau
 *
 * Created on November 14, 2019, 8:32 PM
 */

#ifndef VM_COMMAND_H
#define VM_COMMAND_H

#include "../Command.h"
#include <list>
#include <set>
#include <regex>
#include <cstdlib>

struct CmdLst : public std::list<Command*> {
public:

    enum VMCommandType {
        C_ARITHMETIC,
        C_PUSH,
        C_POP,
        C_LABEL,
        C_GOTO,
        C_IF,
        C_FUNCTION,
        C_RETURN,
        C_CALL,
        C_INCOMPLETE
    } VMCType = C_INCOMPLETE;
};

class VM_CommandFactory {
public:
    VM_CommandFactory(std::string i_un_name, CommandFactory *i_cf);
    CmdLst* construct(std::string formatted_input);
protected:
    CommandFactory *cf;
    std::string unit_name; //used by static segment
    //push
    CmdLst pushByVal(std::string i);
    CmdLst pushByRef(std::string i, std::string base_ref_str);
    CmdLst pushByAddr(std::string addr_str);
    //pop
    CmdLst popByRef(std::string i, std::string base_ref_str);
    CmdLst popByAddr(std::string addr_str);
    //arithmetic
    CmdLst aAdd();
    CmdLst aSub();
    CmdLst aNeg();
    CmdLst aEq();
    CmdLst aGt();
    CmdLst aLt();
    CmdLst aAnd();
    CmdLst aOr();
    CmdLst aNot();
private:
    const uint16_t temp_segment_location = 5;
    uint16_t unit_condition_counter;
    //Common asm patterns for VM Commands
    //for push commands
    CmdLst ATD(std::string addr_str);
    CmdLst DTS();
    CmdLst ROD(std::string ref_str);
    CmdLst RTD(std::string ref_str);
    //for pop commands
    CmdLst STD();
    CmdLst DRO(std::string ref_str);
    CmdLst DTR(std::string ref_str);
    //for arithmetic commands
    CmdLst OOO();
    CmdLst TOO();
    CmdLst TFC(std::string jmp_str);
};

struct UnrecognizedVMCommandException : public std::exception {

    const char * what() const throw () {
        return "Attempt to construct an unrecognized type of CmdLst";
    }
};

#endif /* VM_COMMAND_H */

