Написание компилятора: как заставить работать простые шаблоны?

У меня есть язык с синтаксисом, очень похожим на 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 . Я очень старался, но не могу понять, как это сделать. Может быть, я просто неправильно начал с простого сопоставления типов, и поэтому я не могу понять это.

Итак, вопрос простой: возможно ли это сделать? А как?

8
задан thiton 8 December 2011 в 14:40
поделиться