3

對於我的編程語言中的代碼生成,我使用訪問者模式,我想找到處理賦值語句的更好方法。訪客模式和編譯器代碼生成,如何處理分配?

我的虛擬機是基於註冊的每個表情節點走訪只需按下一個註冊號爲全球性的棧,所以當我訪問二進制表示節點正進行類似代碼:

static void visit_binary_expr (gvisitor_t *self, gnode_binary_expr_t *node) { 
    DECLARE_CODE(); 

    bool is_assignment = (node->op == TOK_OP_ASSIGN); 
    if (is_assignment) { 
     // assignment is right associative 
     visit(node->right); 
     visit(node->left); 
    } else { 
     // visiting binary operation from left to right 
     visit(node->left); 
     visit(node->right); 
    } 

    if (!is_assignment) { 
     uint32_t r3 = ircode_register_pop(code); 
     uint32_t r2 = ircode_register_pop(code); 
     uint32_t r1 = ircode_register_push_temp(code); 

     opcode_t op = token2opcode(node->op); 
     ircode_add(code, op, r1, r2, r3); 
    } 
} 

有了這個代碼,我可以像過程的指令:A + b 假設變量在寄存器1和變量b在寄存器產生2代碼將是:

ADD 3 1 2 

的問題是,分配需要一組不同的指令,並且具有上在堆棧上註冊號碼是不夠的。例如,爲了訪問(讀取)全局變量,我應該使用GLOAD指令,同時將(寫入)存儲到全局變量中,我應該使用GSTORE指令。

我目前正在通過將布爾is_assignment值存儲到每個節點來解決該問題,所以我可以遞歸地檢查要生成哪個指令,但這需要將大量邏輯分佈到每個訪問節點中,我真的很想找出更優雅的方式,其中只有visit_binary_expr函數可以決定什麼是最好的生成指令。

回答

1

由於賦值與其他二元操作(它具有改變左手邊操作數的副作用)有很大不同,所以將它作爲完全獨立的操作進行處理是有意義的,根本不涉及二元操作。在這種情況下,你會得到類似visit_assignment這樣的對應類型的第二個參數。

然後,您可以避免當前代碼中存在的所有檢查。此外,根據您的語言允許的目標類型,處理分配目標可以使用一組不同的遍歷函數,不同的訪問者或具有標誌的同一訪問者,該標誌指示正在處理目標,而不是正則表達式。哪種方法更好的決定取決於您需要生成的語言和代碼。

相關問題