Я пытаюсь создать простой динамический интерпретатор языка в C ++. Я хотел бы иметь возможность объявлять динамически типизированные массивы, но я не уверен, как хранить их в каком-либо объекте в C ++.
В Ruby / Python я могу хранить все, что захочу, но как эффективный способ сделать это в C ++?
(Также, если у кого-то есть ссылка на просто лексер / парсер / интерпретатор с открытым исходным кодом для динамических языков, таких как Ruby, я был бы признателен за ссылку).
Вам нужно будет выбрать какое-то нестандартное решение, основанное на семантике вашего языка. Например, вы можете использовать boost::any
в хранить любой объект, но вы не сможете выполнить, например, поиск по имени. Знание некоторого ассемблера полезно здесь, потому что вы в основном подражаете этому. То, что делает большинство людей, это что-то вроде
struct Object {
boost::any cppobject;
std::unordered_map<std::string, std::function<void(boost::any&, std::vector<boost::any>&)> funcs;
};
std::vector<Object> stuff;
Когда, на вашем гипотетическом языке, у вас есть что-то вроде
stuff[0].hi();
Тогда вы можете преобразовать его в нечто вроде
std::vector<boost::any> args;
// fill args
stuff.at(0).funcs["hi"](stuff.at(0).cppobject, args);
// now args holds the result
Вполне возможно и дальше оптимизировать эту схему, но не обобщать ее дальше, поскольку она уже максимально общая.
Динамические языки хранят универсальные объекты с помощью указателей, вы можете сделать то же самое в C ++. Храните указатель на общий «объект», который вы определяете в своих классах C ++, это эффективный способ сделать это.
Альтернативой использованию объединений или динамического выделения объектов общего базового типа (и их снижения в зависимости от ситуации с помощью dynamic_cast или эквивалентной конструкции) является повышение :: вариант, который позволяет вам писать код, такой как:
typedef boost::variant<int, float, char, std::string> LangType;
std::vector<LangType> langObjects;
Если ваша конструкция допускает такую реализацию, то она имеет преимущество в том, что она безопасна во время компиляции и позволяет избежать любого штрафа, налагаемого использованием кучи, виртуальных функций и полиморфных снижений производительности.