什麼是抽象語法樹?

抽象語法樹(Abstract Syntax Tree,AST)是一種以 XML 格式呈現原始碼結構的工具。它將原始碼中的注解、空白字元、換行符號以及大小寫差異全部抽象化掉,只保留程式碼的邏輯結構。

正因如此,AST 非常適合用來分析大量原始碼、尋找特定的程式碼模式——而這些模式若用傳統的文字比對(例如 grep)來搜尋,往往因為注解、縮排或換行方式不同而難以找到。

實際問題:迴圈中的 ui.Interface.refresh()

本文以偵測迴圈中不當使用 ui.Interface.refresh() 為範例,說明 AST 的實際應用。有兩種常見的問題模式:

  1. 迴圈中完全沒有呼叫 refresh()——畫面更新不及時,使用者看不到進度。
  2. 迴圈在每次疊代都呼叫 refresh()——呼叫次數過多,造成效能問題。

建議的解決方式是加入帶有 MOD 條件的 refresh 呼叫,限制呼叫頻率,例如每 100 次疊代才呼叫一次:

IF MOD(i, 100) = 0 THEN
    CALL ui.Interface.refresh()
END IF

技術實作:使用 fglcomp -Tx 產生 AST

Genero 編譯器提供一個未公開的選項 fglcomp -Tx,可以產生表示抽象語法樹的 XML 輸出。分析程式透過以下步驟找出有問題的程式碼:

  1. 使用 fglcomp -Tx 對目標 .4gl 檔案產生 XML(AST)
  2. 透過 xml 擴充套件使用 XPath 表達式在 XML 中搜尋 symboltoken 元素
  3. 遍歷父子節點關係,判斷 refresh() 呼叫是否在迴圈範圍內
  4. 取得 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)

已知限制

作者提到,此範例為簡化版本,尚未處理以下情況——這些都是將其擴充為實際應用時需要進一步處理的部分:

  • FOREACHWHILE 迴圈(本範例只分析 FOR 迴圈)
  • 迴圈內包含函式呼叫的情況(需要追蹤函式內部是否有 refresh)
  • DISPLAY TO 陳述式(另一種觸發畫面更新的方式)

應用場景

這種 AST 分析技術不僅限於 refresh() 的偵測,理論上可以套用到任何需要在大量 .4gl 檔案中找出特定程式碼模式的場景,例如:

  • 找出所有沒有檢查 int_flag 的對話框
  • 確認所有 CONSTRUCT 的 formonly 欄位都有加 TYPE
  • 找出直接使用全域變數而非透過函式存取的程式碼
原文:https://4js.com/ask-reuben/ig-303/  ·  有任何 Genero 技術問題或翻譯疑問,歡迎來信 support@t100.app