什麼是抽象語法樹?
抽象語法樹(Abstract Syntax Tree,AST)是一種以 XML 格式呈現原始碼結構的工具。它將原始碼中的注解、空白字元、換行符號以及大小寫差異全部抽象化掉,只保留程式碼的邏輯結構。
正因如此,AST 非常適合用來分析大量原始碼、尋找特定的程式碼模式——而這些模式若用傳統的文字比對(例如 grep)來搜尋,往往因為注解、縮排或換行方式不同而難以找到。
實際問題:迴圈中的 ui.Interface.refresh()
本文以偵測迴圈中不當使用 ui.Interface.refresh() 為範例,說明 AST 的實際應用。有兩種常見的問題模式:
- 迴圈中完全沒有呼叫 refresh()——畫面更新不及時,使用者看不到進度。
- 迴圈在每次疊代都呼叫 refresh()——呼叫次數過多,造成效能問題。
建議的解決方式是加入帶有 MOD 條件的 refresh 呼叫,限制呼叫頻率,例如每 100 次疊代才呼叫一次:
IF MOD(i, 100) = 0 THEN
CALL ui.Interface.refresh()
END IF
技術實作:使用 fglcomp -Tx 產生 AST
Genero 編譯器提供一個未公開的選項 fglcomp -Tx,可以產生表示抽象語法樹的 XML 輸出。分析程式透過以下步驟找出有問題的程式碼:
- 使用
fglcomp -Tx對目標 .4gl 檔案產生 XML(AST) - 透過
xml擴充套件使用 XPath 表達式在 XML 中搜尋symbol和token元素 - 遍歷父子節點關係,判斷 refresh() 呼叫是否在迴圈範圍內
- 取得
location屬性(行號、欄號),以精確定位原始碼位置
範例程式說明
本文提供兩個程式碼檔案:
askreuben303_test.4gl(測試程式)
包含四個 FOR 迴圈,示範各種不同的程式碼模式:有些迴圈沒有呼叫 refresh()、有些每次都呼叫、有些正確使用 MOD 條件。這是被分析的目標程式。
askreuben303.4gl(分析程式)
對 askreuben303_test.4gl 進行分析,判斷每個迴圈是否符合規範,並輸出結果指出哪些迴圈通過驗證、哪些包含問題。
執行輸出範例(示意):
Loop at line 10 : PASS (uses MOD condition)
Loop at line 25 : FAIL (no ui.Interface.refresh call)
Loop at line 42 : FAIL (refresh called on every iteration)
Loop at line 58 : PASS (uses MOD condition)
已知限制
作者提到,此範例為簡化版本,尚未處理以下情況——這些都是將其擴充為實際應用時需要進一步處理的部分:
FOREACH和WHILE迴圈(本範例只分析FOR迴圈)- 迴圈內包含函式呼叫的情況(需要追蹤函式內部是否有 refresh)
DISPLAY TO陳述式(另一種觸發畫面更新的方式)
應用場景
這種 AST 分析技術不僅限於 refresh() 的偵測,理論上可以套用到任何需要在大量 .4gl 檔案中找出特定程式碼模式的場景,例如:
- 找出所有沒有檢查
int_flag的對話框 - 確認所有 CONSTRUCT 的 formonly 欄位都有加 TYPE
- 找出直接使用全域變數而非透過函式存取的程式碼
原文:https://4js.com/ask-reuben/ig-303/
· 有任何 Genero 技術問題或翻譯疑問,歡迎來信
support@t100.app