I am developing a c++ interpreter and I don't really have the best way to approach making an inbuilt library. i have added functions (for the most part) however the functions are useless if I can't print to console, take user input etc. here is what I thought of first:
#include <iostream>
#include <string>
#include <any>
#include <vector>
#include <sstream>
#include <functional>
#include <map>
#define VOIDFC void* (*)
using std::string;
namespace marine {
namespace inb {
namespace console {
template <typename string>
void log(std::string s) {
std::cout << s << std::endl;
}
template<typename int>
void log(int i) {
std::cout << i << std::endl;
}
template<typename float>
void log(float i) {
std::cout << i << std::endl;
}
};
template<typename Type, typename ...Args>
struct LibHolder;
struct FuncInfo {
const char* name;
int param_c;
std::vector<Base::Decl> paramTypes;
};
template<typename Type, typename ...Args>
struct LibHolder {
using __t = Type (*)(Args...);
std::map<FuncInfo, __t> inb_functions{};
void add(FuncInfo f, __t t) {
inb_functions.push_back(f, t);
}
};
LibHolder<void, void*> void_1arg;
LibHolder<void, void*, void*> void_2arg;
LibHolder<void, void*, void*, void*> void_3arg;
LibHolder<void, void*, void*, void*, void*> void_4arg;
LibHolder<void, void*, void*, void*, void*, void*> void_5arg;
LibHolder<void, void*, void*, void*, void*, void*, void*> void_6arg;
static void init() {
/*console*/
{
void_1arg.add({ "log", 1, {Base::Decl::INT} }, (void (*) (void*))console::log<int>);
void_1arg.add({ "log", 1, {Base::Decl::FLOAT} }, (void (*) (void*))console::log<float>);
void_1arg.add({ "log", 1, {Base::Decl::STRING} }, (void (*) (void*))console::log<string>);
}
}
using ret_st = void* (*);
template<int param_c = 1,typename ...Params>
static auto getINBMethod(std::vector<Base::Decl> v, std::string name) {
switch (param_c) {
case 0:
throw marine::errors::IndexError("A function cannot take 0 arguments.");
case 1:
for (auto& x : void_1arg.inb_functions) {
if (x.first.name == name) return &x.second;
}
case 2:
for (auto& x : void_2arg.inb_functions) {
if (x.first.name == name) return &x.second;
}
case 3:
for (auto& x : void_3arg.inb_functions) {
if (x.first.name == name) return &x.second;
}
case 4:
for (auto& x : void_4arg.inb_functions) {
if (x.first.name == name) return &x.second;
}
case 5:
for (auto& x : void_5arg.inb_functions) {
if (x.first.name == name) return &x.second;
}
case 6:
for (auto& x : void_6arg.inb_functions) {
if (x.first.name == name) return &x.second;
}
}
return nullptr;
}
}
}
I am kind of new to function pointers and I can tell that this is far from a good solution. basically my interpreter would find a function call ex 'print("hello world!")' and look for the inbuilt function print below using getINBMethod(). I'm not sure if there is a better way to do this, as the way I do function in my language is also very dodgy, I basically skip parsing the function until it is called. not the best I know...
i want to be able to scale this, so i could have different modules, like networking, and others that you would import in your script and then the functions would be in a vector or something waiting to be executed. of course i need the function name as i would need to check it when we call it.
any help would be appreciated!