4

我目前正在爲一種非常有限的面嚮對象語言開發編譯器。我想把所有的值作爲對象來處理,這些值的操作符將作爲方法來實現。編譯器將程序轉換爲基於堆棧的虛擬機的彙編程序。使用程序進行短路評估

在編譯過程中,我將整數文字轉換爲特殊「整數」類的對象。算術運算符被實現爲該類的方法(使用內聯彙編程序)。所以4 + 5基本上等於4.add(5)

我現在面臨的問題是布爾值的特殊情況。如果有if聲明:

if(10 > 5 || 12 < 10) 

這將目前轉化爲:10.greaterThan(5).or(12.lessThan(10))

現在很明顯,這些整數文字,也可以與副作用的函數調用。在這種情況下,將這些二元運算符用作方法調用會產生問題,因爲不可能進行短路評估。

所以我的問題是:

  1. 如何其他語言實現短路評價,但仍把每個值作爲一個對象?

  2. 根據維基百科「ALGOL 68使用」程序「實現用戶定義的短路操作程序&程序」。 - 這個怎麼用?

回答

4

常用的技術,我相信,無論是涉及或call by namecall by need。這個想法是,or的參數不是比較的結果,而是比較本身轉換爲thunk,每當(按名稱調用)或第一次(在調用中)轉換爲結果值需要)它是需要的。

將表達式轉換爲thunk時,您基本上正在創建一個匿名函數,您可以像這樣處理編譯問題。它涉及將表達式編譯爲將評估表達式的代碼。它還涉及創建一個對象(thunk本身),它引用(或包含)表達式使用的局部變量的副本,以及指向表達式編譯代碼的指針。該對象需要與您的布爾類進行接口兼容,以便使用它的代碼不必關心它是否具有真正的布爾值或者像這樣的thunk。每當有人需要布爾值時,thunk會執行編譯的表達式代碼並提供結果值。

如果按名稱打電話對您來說已經足夠,那就是這一切。對於需求調用,緩存評估結果會增加複雜性。

1

IIRC ALGOL使用call-by-name參數,這就是解決方案工作的原因。

||操作者可以被實施爲(僞碼):

if (cond1) goto label; 
if (cond2) goto label; 

label: 
    <body> 

nomatch: 
    ... 

對於&&的上述逆可以做到的。

1

重新:根據維基百科「Algol68的使用的‘proceduring’來實現用戶定義 短路運營商&程序」。 - 這個怎麼用?

Algol68-r0(原始/未修正的定義)有兩個與短路評估有關的概念。

想象一下編碼器想要定義一個「短路評估」的矩陣乘法運算符,所以一旦左邊的參數是一個「零」矩陣,那麼就會有進一步的右邊評估......這種用戶定義的定義可能是:

MODE MAT = FLEX[0,0]REAL; 
OP ISZERO = (MAT a)BOOL: ¢ insert actual code here ¢ ~; 

PRIO TIMESF = 7; 
OP TIMESF = (MAT a, PROC MAT in b)MAT: 
    IF ISZERO a THEN a ELSE MAT b = in b; ¢ insert actual code here ¢ ~ FI; 

MAT a = 0, b = 16, c = 25; 
print(a TIMESF b TIMESF c) ¢ would print 0 without calculating 16*25 ¢ 

相反,編碼器希望左邊和右邊的參數是並行計算的。這樣的用戶定義的定義可以是:

PRIO TIMESPAR = 7; 
OP TIMESPAR = (MAT a, MAT b)MAT: ¢ insert actual code here ¢ ~; 

逗號告訴編譯器,它是免費評估左手和右手按任何順序,甚至並行。 (這使編譯器優化評估選項)

或者編碼器可能需要強制評估是連續的:

PRIO TIMESSEQ = 7; 
OP TIMESSEQ = (MAT a; MAT b)MAT: ¢ insert actual code here ¢ ~; 

在這種情況下,「;」被稱爲「gomma」,適用於「逗逗」。

Algol68的-R1(修訂於1974年,可在SourceForge上的Windows和Linux),刪除了所有這些能力離開編碼器,手動/特別適用「proceduring」 ......如

第一組矩陣的定義是相同的:

MODE MAT = FLEX[0,0]REAL; 
PRIO TIMESF = 7; 
OP TIMESF = (MAT a, PROC MAT in b)MAT: 
    IF ISZERO a THEN a ELSE MAT b = in b; ¢ insert actual code here ¢ ~ FI; 

MAT a = 0, b = 16, c = 25; ¢ 3 1x1 matrices are "widening" from REAL numbers ¢ 

但使用不同的是,注意使用兩個lambda表達式(MAT:b乘以MAT:C)的和(MAT:C):

print(a TIMESF MAT:b TIMESF MAT:c) ¢ would print 0 without calculating 16*25 ¢ 

透明在Algol68-r1中保留了去核和擴大的功能。