У меня есть язык с очень похожим на C ++ синтаксисом.Лексер и парсер находятся на своем месте и выдают правильный AST.Для большей части также выполняется бэкэнд.
Базовая система, используемая компилятором для создания типов, очень проста: все типы считаются встроенными, а все экземпляры являются глобальными.Так что есть просто простая карта, которая сопоставляет имя типа с методом, который создает Variable , который в основном является универсальным типом, таким как 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 .Я очень старался, но не могу понять, как это сделать.Может быть, я просто неправильно начал с простого сопоставления типов и по этой причине я не могу разобраться с этим.
Итак, вопрос прост: возможно ли это сделать?И как?