← index
MasterX_System/compiler/ETL/interp.hpp
Source: MasterX_System/compiler/ETL/interp.hpp
#ifndef _INTERP_H__

#define _INTERP_H__


#include <unordered_map>

#include <unordered_set>

#include <stack>

#include <sstream>

#include <vector>

#include <string>

#include <iostream>

#include <algorithm>

#include <regex>

#include <set>

#include "types.hpp"

#include "ir.hpp"

#include "symbol.hpp"

#include "clib.hpp"


namespace interp {
    
    class Exception {
    public:
        Exception(const std::string &text) : data{text} {}
        std::string why () const { return data; }
    private:
        std::string data;
    };

    class Exit_Exception {
    public:
        Exit_Exception(int status) : code{status} {}
        int status() const { return code; }
    private:
        int code = 0;
    };

    struct Function {
        std::string functionName;
        std::vector<std::string> arg_names;
        std::vector<ast::VarType> arg_types;
        ast::VarType return_type;
    };

    class FunctionTable {
    public:
        void enterFunction(const std::string &name);
        void addParam(const std::string &name, ast::VarType type);
        Function &getFunction(const std::string &name);
        bool isDefined(const std::string &f);
    private:
        std::string curFunction;
        std::unordered_map<std::string, Function> func;
    };

    struct Var {
        Var() = default;
        Var(const std::string &n, ast::VarType v) : name{n}, numeric_value{0}, ptr_value{nullptr}, type{v} {}
        Var(const std::string &n, const std::string &value) : name{n}, string_value{value}, type{ast::VarType::STRING} {}
        Var(const std::string &n, long value) : name{n}, numeric_value{value}, type{ast::VarType::NUMBER} {}
        Var(const std::string &n, void *ptr) : name{n}, ptr_value{ptr}, type {ast::VarType::POINTER} {}
        Var(const Var &v) : name{v.name}, numeric_value{v.numeric_value}, string_value{v.string_value}, ptr_value{v.ptr_value}, type{v.type} {}
        Var(Var &&v) : name{std::move(v.name)}, numeric_value{v.numeric_value}, string_value{std::move(v.string_value)}, ptr_value{v.ptr_value}, type{v.type} {}

        Var &operator=(const Var &v) {
            name = v.name;
            numeric_value = v.numeric_value;
            string_value = v.string_value;
            ptr_value = v.ptr_value;
            type = v.type;
            return *this;
        }

        Var &operator=(Var &&v) {
            name = std::move(v.name);
            numeric_value = v.numeric_value;
            string_value = std::move(v.string_value);
            ptr_value = v.ptr_value;
            type = v.type;
            return *this;
        }

        std::string name;
        long numeric_value = 0;
        std::string string_value;
        void *ptr_value = nullptr;
        ast::VarType type;
    };

    using FuncPtr =  Var(*)(const std::vector<Var> &vars);

    class Functor {
    public:
        Functor() = default;
        Functor(const std::string &n, FuncPtr fp) : name{n}, f_ptr{fp} {}
        Functor(const Functor &f) : name{f.name}, f_ptr{f.f_ptr}, int_vars{f.int_vars} {}
        Functor(Functor &&f) noexcept : name{std::move(f.name)}, f_ptr{f.f_ptr}, int_vars{std::move(f.int_vars)} {}

        Functor &operator=(const Functor &f) {
            name = f.name;
            f_ptr = f.f_ptr;
            int_vars = f.int_vars;
            return *this;
        }

        Functor &operator=(Functor &&f) noexcept {
            name = std::move(f.name);
            f_ptr = f.f_ptr;
            int_vars = std::move(f.int_vars);
            return *this;
        }

        std::string name;
        std::vector<Var> int_vars;

        Var operator()(const std::vector<Var> &vars) {
            if(f_ptr != nullptr)
                return f_ptr(vars);

            throw Exception("Function: " + name + " Not found!");
        }   
    private:
        FuncPtr f_ptr = nullptr;
    };

    class LibraryFunctions {
    public:
        LibraryFunctions() = default;
        template<typename F>
        void addFunction(std::string name, F value) {
            functions[name] = Functor(name, value);
        }
        void defineInteger(std::string fname, std::string iname) {
            functions[fname].int_vars.push_back(Var(iname, ast::VarType::NUMBER));
        }
        void defineString(std::string fname, std::string sname) {
            functions[fname].int_vars.push_back(Var(sname, ast::VarType::STRING));
        }
        void definePointer(std::string fname, std::string pname) {
            functions[fname].int_vars.push_back(Var(pname, ast::VarType::POINTER));
        }
        Var callFunction(std::string name, const std::vector<Var> &v) {
            return functions[name](v);
        }
        Functor *getFunction(const std::string &n) {
            if(functions.find(n) != functions.end())
                return &functions[n];
            return nullptr;
        }
        void print(std::ostream &out) {
            for(auto &f : functions) {
                out << f.first << " [ ";
                for(size_t i = 0; i < f.second.int_vars.size(); ++i) {
                    out << f.second.int_vars[i].name << ":" << ast::VarString[static_cast<int>(f.second.int_vars[i].type)] << " ";
                }
                out << " ]\n";
            }
        }

    private:
        std::unordered_map<std::string, Functor> functions;
    };

    class Interpreter {
    public:
        Interpreter(const std::string &lib_path, symbol::SymbolTable &table);
        int execute(ir::IRCode &code, bool debug);
        void release();
        void outputDebugInfo(std::ostream &out);
    private:
        symbol::SymbolTable &sym_tab;
        FunctionTable ftable;
        LibraryFunctions lf_table;
        long ip = 0;
        std::string LIB_PATH = "/usr/local/lib";
        std::string curFunction;
        std::unordered_map<std::string, std::unordered_map<std::string, long>> numeric_variables;
        std::unordered_map<std::string, std::unordered_map<std::string, std::string>> string_variables;
        std::unordered_map<std::string, std::unordered_map<std::string, void *>> pointer_variables;
        std::unordered_map<std::string, long> label_pos;
        std::unordered_map<std::string, long> sub_labels;
        struct ReturnValue {
            std::string fname, rt_name;
            long pos;
        };

        std::vector<ReturnValue> call_stack;

        void collectLabels(const ir::IRCode &code);

        void executeAdd(const ir::IRInstruction &instr);
        void executeSub(const ir::IRInstruction &instr);
        void executeMul(const ir::IRInstruction &instr);
        void executeDiv(const ir::IRInstruction &instr);
        void executeMod(const ir::IRInstruction &instr);
        void executeAnd(const ir::IRInstruction &instr);
        void executeOr(const ir::IRInstruction &instr);
        void executeXor(const ir::IRInstruction &instr);
        void executeLShift(const ir::IRInstruction &instr);
        void executeRShift(const ir::IRInstruction &instr);
        void executeJump(const ir::IRInstruction &instr);
        void executeLoadConst(const ir::IRInstruction &instr);
        void executeSetConst(const ir::IRInstruction &instr);
        void executeAssignment(const ir::IRInstruction &instr);
        void executeLoadVar(const ir::IRInstruction &instr);
        void executeSet(const ir::IRInstruction &instr);
        void executeLabel(const ir::IRInstruction &instr);
        void executeNeg(const ir::IRInstruction &instr);
        void executeNot(const ir::IRInstruction &instr);
        void executeLt(const ir::IRInstruction &instr);
        void executeGt(const ir::IRInstruction &instr);
        void executeLte(const ir::IRInstruction &instr);
        void executeGte(const ir::IRInstruction &instr);
        void executeEq(const ir::IRInstruction &instr);
        void executeNeq(const ir::IRInstruction &instr);
        void executeLogicalNot(const ir::IRInstruction &instr);
        void executeLogicalAnd(const ir::IRInstruction &instr);
        void executeLogicalOr(const ir::IRInstruction &instr);
        void executeCall(const ir::IRInstruction &instr);
        void executeReturn(const ir::IRInstruction &instr);
        void executeConcat(const ir::IRInstruction &instr);

        long getIntegerValue(const std::string &operand);
        std::string stripQuotes(const std::string &value);
        
    };
}


#endif