如何在带有 goto 或类似语言的合成语言解释器中实现 Try/Except/Finally?
How implement Try/Except/Finally in a made-up language interpreter with goto or similar?
如何在解释器上实现 try/catch/finally 功能(目前我使用的是 F#)?
我怀疑可以使用GOTO(但是,在解释器中也需要为它提供功能,不知道如何实现),但我从来没有使用过GOTO(只知道是邪恶的! ),也不了解如何保护环境。
P.D:我已经知道可以使用 CPS(Continuations)来模拟异常和任何其他控制流。然而,它使其余的语言实现变得复杂,并且需要通过优化来消除它的开销,对于这个问题,我希望了解其他替代方法
P.D.2:是否存在另一种 CPS 替代方案,可以轻松实现自定义控制流?或者为此概括 GOTO 的方法?
控件可以通过多种方式转义 "try" 块:
- 转到周围块中的标签(注意:转到 X 和转到 Y 是 2 种不同的转义!)
- Return 来自包含 try
的函数
- 在 try 中抛出异常
- 从 try 主体调用的函数传播异常
- (可检测地)在 try 体中调用 exit()
您可能有更多,具体取决于您的语言。
你的 try-finally 块必须做的是捕获所有这些,执行 finally 部分,然后继续预期的操作。
实现此目的的一种方法是为每个块逃生创建一个传送岛。转运岛作为这些行动中每一个行动的目标;如果控制到达转移岛 K,则发生块逃逸 K。 transfer island所做的就是调用一个包含finally子句的(无参)子程序,然后执行一个动作继续escape K.
想象一下下面的 try-finally 块:
try
...goto X... // ... means some control structure wrapped around this
...raise Z...
...call q()... // throws exception
...goto Y...
...return 5...
finally
<some actions>
end
...return <exp>
此代码可能编译为:
// try
... goto TIX... // TIk ==> "tranfer island k"
...exception=Z; goto TIE ...
...try call q()
catch exception; goto TIE
end try
...result=5; goto TIR...
// finally
local subroutine finally()
{ <some actions> }
TIX: call finally();
goto X;
TIY: call finally();
goto Y;
TIR: call finally();
goto RETURN;
TIE: call finally();
propagate exception; // means "pass control to containing exception handler"
...
// end try
result=<exp>;
RETURN:
return result;
在这种背景下,你必须让解释器执行操作,就好像这段代码存在一样。显然,解释器不需要实例化传输岛;它知道发生了哪种类型的块逃逸,可以执行finally动作,然后进行继续块逃逸。
如何在解释器上实现 try/catch/finally 功能(目前我使用的是 F#)?
我怀疑可以使用GOTO(但是,在解释器中也需要为它提供功能,不知道如何实现),但我从来没有使用过GOTO(只知道是邪恶的! ),也不了解如何保护环境。
P.D:我已经知道可以使用 CPS(Continuations)来模拟异常和任何其他控制流。然而,它使其余的语言实现变得复杂,并且需要通过优化来消除它的开销,对于这个问题,我希望了解其他替代方法
P.D.2:是否存在另一种 CPS 替代方案,可以轻松实现自定义控制流?或者为此概括 GOTO 的方法?
控件可以通过多种方式转义 "try" 块:
- 转到周围块中的标签(注意:转到 X 和转到 Y 是 2 种不同的转义!)
- Return 来自包含 try 的函数
- 在 try 中抛出异常
- 从 try 主体调用的函数传播异常
- (可检测地)在 try 体中调用 exit()
您可能有更多,具体取决于您的语言。
你的 try-finally 块必须做的是捕获所有这些,执行 finally 部分,然后继续预期的操作。
实现此目的的一种方法是为每个块逃生创建一个传送岛。转运岛作为这些行动中每一个行动的目标;如果控制到达转移岛 K,则发生块逃逸 K。 transfer island所做的就是调用一个包含finally子句的(无参)子程序,然后执行一个动作继续escape K.
想象一下下面的 try-finally 块:
try
...goto X... // ... means some control structure wrapped around this
...raise Z...
...call q()... // throws exception
...goto Y...
...return 5...
finally
<some actions>
end
...return <exp>
此代码可能编译为:
// try
... goto TIX... // TIk ==> "tranfer island k"
...exception=Z; goto TIE ...
...try call q()
catch exception; goto TIE
end try
...result=5; goto TIR...
// finally
local subroutine finally()
{ <some actions> }
TIX: call finally();
goto X;
TIY: call finally();
goto Y;
TIR: call finally();
goto RETURN;
TIE: call finally();
propagate exception; // means "pass control to containing exception handler"
...
// end try
result=<exp>;
RETURN:
return result;
在这种背景下,你必须让解释器执行操作,就好像这段代码存在一样。显然,解释器不需要实例化传输岛;它知道发生了哪种类型的块逃逸,可以执行finally动作,然后进行继续块逃逸。