У меня есть язык с синтаксисом, очень похожим на C ++. Лексер и синтаксический анализатор на месте и выдают правильный AST. По большей части бэкэнд тоже готов.
Базовая система, которую компилятор использует для создания типов, очень проста: все типы считаются встроенными, а все экземпляры - глобальными. Итак, есть простая карта, которая сопоставляет имя типа с методом, который создает переменную , которая по сути является универсальным типом, таким как boost :: any. Другая карта с именем переменной в качестве ключа и переменной в качестве значения служит глобальной областью:
std::map< std::string, std::function< Variable() > typeList;
//register some types
typeList[ "X" ] = Variable::Create<X>;
typeList[ "Y" ] = CreateInstanceOfY;
....
Когда компилятор получает узел AST для инициализации, такой как X myVar;
, он в основном делает
std::map< std::string, Variable > globalScope;
globalScope[ "myVar" ] = typeList[ "X" ]();
Когда myVar используется позже, к нему можно получить доступ с помощью простой диспетчеризации типов, например
X& x = myVar.GetReference<X>();
. Теперь я хотел бы немного расширить это и использовать простые шаблоны.Предположим, есть тип «массив», который реализован с использованием вектора. Я мог бы зарегистрировать все, как
typeList[ "array<X>" ] = Variable::Create< std::vector< X > >;
, но это не совсем управляемо, так как это придется повторять для всех комбинаций. В идеале мне понадобится функциональность, позволяющая написать что-то вроде этого:
typeList.CreateTemplateVariable( "array", "X" )
, который затем создаст экземпляр Variable, внутри которого хранится std :: vector
Итак, вопрос простой: возможно ли это сделать? А как?