2012-02-27 104 views
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中保留了去核和扩大的功能。