2011-12-08 67 views
8

我有一種非常類似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") 

那麼這將創建一個變量例如它的內部保存一個std :: vector的< X>。我努力嘗試,但無法弄清楚如何做到這一點。也許我只是用簡單的類型映射開始了錯誤的方式,這就是我無法理解它的原因。

所以問題很簡單:是否可以這樣做?如何?

+0

當你從AST製作C++代碼時,它已經是編譯器了。 – belgther

+0

有關術語的小小挑剔:編譯器將代碼從一種格式轉換爲另一種格式。解釋器執行一些代碼。 –

+0

@JoachimPileborg感謝您指出這一點..我真的不擅長術語。 – stijn

回答

2

我不知道我得到了你的問題所在,但如果你爲M的參數類型(vector<>list<>,...)和N簡單類型(intdouble,...),你就需要M * N個實際的實現,如果你想支持所有的組合。所有這些實現必須在編譯時知道(或者原則上你可能會立即調用C++編譯器)。你真的想要這個嗎?

解決方法可以是使用非鍵入的容器。例如,vector<Object*>存儲可隨後轉換爲所需類型的指針,例如dynamic_cast。這樣您只需要M個參數類型的實現,並且可以獨立地將「數組」分解爲vector和「X」至X

+0

你對M * N是正確的,但是最好有一些動態系統也支持嵌套模板和多個模板參數,或者可以擴展嵌套模板和多個模板參數。我會看看這種非類型的方法是否讓我在某處,看起來很有趣。 – stijn

+0

@stijn,你仍然可以擁有你的語言輸入的所有東西,有模板和其他任何東西。當您嘗試將類型從您的語言一對一映射到C++時,例如您正在嘗試對「數組」 - >向量執行此操作時出現問題。但是,您不必這樣做 - 只要您的編譯器進行類型檢查,任何看起來用您的語言鍵入的內容都不必在實現中鍵入。 –

1

通常,按照您所描述的方式執行模板類型的方式,但不是提前創建所有可能的組合,而是按需創建它們。所以,你可能有一個getType程序,如:

std::function< Variable() > getType(std::string name) { 
    auto rv = typeList[name]; 
    if (rv) return rv; 
    auto template_start = name.find('<'); 
    if (template_start != string::npos) { 
     auto template_end = name.rfind('>'); 
     std::string arg = name.substr(template_start+1, template_end); 
     std::string base = name.substr(0, template_start); 
     typeList[name] = rv = InstantiateTemplate(base, arg); 
     return rv; } 
    throw UnknownTypeError(name); 
} 

調用此方法在方案中提及的任何類型的,按需創建所需的模板實例。

+0

感謝您的輸入,但您的函數的最大部分實際上是解析器已經做的;此外它是遞歸的,所以我的解析器處理嵌套模板,其中包含數組 >>的無限參數,併爲它創建一個名爲TypeSpecifier的AST節點。我的問題是如何編寫'InstantiateTemplate'功能,即如何將TypeSpecifier轉換爲實際的類型實例。 – stijn