代碼生成

語法解析流程簡(jiǎn)述

lua之類的腳本語言先把源代碼翻譯成字節(jié)碼,而后再使用虛擬機(jī)執(zhí)行字節(jié)碼。
而從源代碼到字節(jié)碼要經(jīng)過多個(gè)過程:

詞法解析,語法解析,語義解析,代碼生成。
源代碼->單詞流->語法樹->帶語義的語法樹->字節(jié)碼。

語義解析主要是完善語法樹,添加語義信息:

  1. 設(shè)置變量作用域。
  2. 設(shè)置break和continue對(duì)應(yīng)的循環(huán)語句。

lua的官方實(shí)現(xiàn)做了優(yōu)化,將4步流程壓縮成一個(gè)。詞法解析提供接口供語法解析調(diào)用,語法解析、語義解析壓縮成一個(gè)流程,代碼生成提供接口供語法解析使用。這也造成解析代碼難以看懂修改。

luna的實(shí)現(xiàn):詞法解析還是提供接口,語法解析,語義解析,代碼生成是分開的,就好懂很多了。(其中的觀察者模式用的不適合)

oms的實(shí)現(xiàn)中語義解析合并代碼生成中。

詞法解析,語法解析,代碼生成。
源代碼->單詞流->語法樹->字節(jié)碼。

指令生成

遍歷語法樹生成代碼的過程比較無腦,對(duì)每個(gè)語法樹節(jié)點(diǎn)類型寫一個(gè)解析函數(shù)。
一個(gè)例子。

void HandleBlock(Block tree)
{
    foreach(var stmt in tree.statements)
    {
        if (stmt is DoStatement)
            HandleDoStatement(stmt as DoStatement);
        else if (stmt is WhileStatement)
            HandleWhileStatement(stmt as WhileStatement);
        else if (stmt is IfStatement)
            HandleIfStatement(stmt as IfStatement);
        else if (stmt is ForStatement)
            HandleForStatement(stmt as ForStatement);
        else if (stmt is ForEachStatement)
            HandleForEachStatement(stmt as ForEachStatement);
        else if (stmt is ForInStatement)
            HandleForInStatement(stmt as ForInStatement);
        else if (stmt is FunctionStatement)
            HandleFunctionStatement(stmt as FunctionStatement);
        else if (stmt is LocalFunctionStatement)
            HandleLocalFunctionStatement(stmt as LocalFunctionStatement);
        else if (stmt is LocalNameListStatement)
            HandleLocalNameListStatement(stmt as LocalNameListStatement);
        else if (stmt is ReturnStatement)
            HandleReturnStatement(stmt as ReturnStatement);
        else if (stmt is BreakStatement)
            HandleBreakStatement(stmt as BreakStatement);
        else if (stmt is ContinueStatement)
            HandleContinueStatement(stmt as ContinueStatement);
        else if (stmt is AssignStatement)
            HandleAssignStatement(stmt as AssignStatement);
        else
            HandleExpRead(stmt);
    }
}

指令系統(tǒng)和局部變量分配

lua的指令是帶寄存器地址的,最多3地址,一個(gè)地址一個(gè)字節(jié),也就限制了局部變量的總數(shù)不可能超過256個(gè)。
自己實(shí)現(xiàn)時(shí),指令也是帶寄存器地址的,最直接的好處是,指令能少很多。然后局部變量分配就是基于棧的了,簡(jiǎn)單方便。
簡(jiǎn)化的指令bit分配。

code: int32_t
A   : uint8_t
B   : uint8_t
C   : uint8_t
Bx  : int16_t (B+C)

局部變量每個(gè)函數(shù)單獨(dú)分配,從0開始,定義一個(gè)局部變量就+1,退出block時(shí)回收當(dāng)前作用域內(nèi)的。
臨時(shí)分配的也要及時(shí)回收,如

void HandleAssignStatement(AssignStatement tree)
{
    HandleExpList(tree.exp_list, tree.var_list.Count);
    // var list
    int register = GetNextRegisterId();
    ResetRegisterId(register + tree.var_list.Count);
    for(int i = 0; i < tree.var_list.Count; ++i)
    {
        HandleVarWrite(tree.var_list[i], register + i);
    }
    ResetRegisterId(register);// 回收臨時(shí)分配的局部變量。
}

語義分析部分

在遍歷語法樹時(shí),要維護(hù)作用域樹循環(huán)結(jié)構(gòu)鏈表

//"while" exp "do" block "end"
void HandleWhileStatement(WhileStatement tree)
{
    EnterLoop();// 進(jìn)入循環(huán)
    EnterBlock();// 進(jìn)入新的作用域
    HandleExpRead(tree.exp);
    // jump to loop tail when expression return false
    var f = GetCurrentFunction();
    var code = Instruction.ABx(OpType.OpType_JmpFalse, GetNextRegisterId(), 0);
    int index = f.AddInstruction(code, -1);
    AddLoopJumpInfo(JumpType.JumpTail, index);
    HandleBlock(tree.block);// 變量循環(huán)block
    LeaveBlock();// 退出作用域
    // jump to loop head
    code = Instruction.Bx(OpType.OpType_Jmp, 0);
    index = f.AddInstruction(code, -1);
    AddLoopJumpInfo(JumpType.JumpHead, index);
    LeaveLoop();// 退出循環(huán)
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,577評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,600評(píng)論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,944評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評(píng)論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,108評(píng)論 0 290
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,652評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,385評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,616評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評(píng)論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,798評(píng)論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評(píng)論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,334評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,570評(píng)論 2 379

推薦閱讀更多精彩內(nèi)容

  • 指令集 lua_capture_error_log lua_use_default_type lua_malloc...
    吃瓜的東閱讀 12,065評(píng)論 0 2
  • 上次我們翻譯了由Unity開發(fā)人員JOSH PETERSON所寫的、IL2CPP深入講解系列的第一期,現(xiàn)在第二期的...
    IndieACE閱讀 9,588評(píng)論 0 11
  • 前面講過語法的解析之后,代碼生成方面就簡(jiǎn)單很多了。雖然myc是一個(gè)簡(jiǎn)單的示例編譯器,但是它還是在解析的過程中生成了...
    懿民閱讀 502評(píng)論 0 1
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,339評(píng)論 11 349
  • 姓名:顧君 單位:寧波大發(fā)化纖有限公司 學(xué)習(xí)組:第234期努力一組 【日精進(jìn)打卡第140天】 【知~學(xué)習(xí)】 《六項(xiàng)...
    JASONGU_2f28閱讀 221評(píng)論 0 0