[英]How to declare nested function for Jasmin byte code?
我正在編寫一個編譯器,我需要將 Mini Pascal(Pascal 的一個簡單版本)轉換為 Jasmin 字節碼。
但是如何在 Jasmin 語言中聲明嵌套的 function呢?
因為function tt(I): I
只能傳入一個 Integer (即rr
)如何將變量d
從function ss
轉移到function tt
?
C++(自己翻譯自Mini Pascal):
#include <iostream>
using namespace std;
int a, b;
int ss(int rr)
{
int d;
int tt(int rr)
{
int e;
e = rr * 3;
return rr + d - e + b;
}
d = rr - 4;
return tt(rr);
}
int main()
{
b = -5;
a = ss(3);
cout << a;
return 0;
}
迷你帕斯卡:
PROGRAM test_nested_function(input, output, error);
VAR a, b : INTEGER;
FUNCTION ss(rr :INTEGER) : INTEGER;
VAR d : INTEGER;
FUNCTION tt(rr : INTEGER) : INTEGER;
VAR e : INTEGER;
BEGIN
e := rr * 3;
tt := rr + d - e + b;
END;
BEGIN
d := rr - 4;
ss := tt(rr)
END;
BEGIN
b := -5;
a := ss(3);
writelnI(a)
END.
當你從一種有閉包的語言翻譯成沒有閉包的語言時,你必須以某種方式保留對外部 function 的引用。 從廣義上講,有兩種方法可以做到這一點:嵌套閉包和平面閉包。 需要注意的重要一點是,在這兩種情況下,您的閉包都不是普通的頂級 function。它是某種恰好可調用的結構。
在嵌套閉包中,嵌套的 function 只是維護對封閉 scope 的引用作為指向某個抽象數據結構的指針。 因此, tt
維護對ss
的引用(在抽象中),然后可以通過ss.d
訪問d
變量。 Java 相同的偽代碼:
public class SsStructure {
private int rr;
private int d;
public SsStructure(int rr) {
this.rr = rr;
this.d = 0;
}
}
public class TtStructure {
private SsStructure closure;
public TtStructure(SsStructure closure) {
this.closure = closure;
}
public int call(int rr) {
...
}
}
public class Main {
public static int ss(int rr) {
SsStructure ss = new SsStructure(rr);
TtStructure tt = new TtStructure(ss);
ss.d = ss.rr - 4;
return tt.call(ss.rr - 4);
}
}
在這個 model 中,你的ss
function 在你的程序中得到一個閉包框架。 它的所有局部變量(或者至少是閉包所需的局部變量)都被放入該結構中,而不是被聲明為實際的局部變量。 然后該閉包結構被傳遞給任何需要它的嵌套 function。
如果你有多層嵌套的函數,那么閉包會維護對立即封閉的 scope 的引用。如果它需要訪問存在於閉包棧上多層的變量,它將通過間接引用來實現,因為每個閉包框架都保留一個參考其自身的封閉 scope。
使用平面閉包,您的嵌套 function 從封閉的 scope 接收實際具體變量的副本。您的tt
仍然是一個結構,但它不是存儲對其他一些ss
結構的引用,而是獲取它需要的實際int
。
public class TtStructure {
private int d;
public TtStructure(int d) {
this.d = d;
}
public int call(int rr) {
...
}
}
public class Main {
public static int ss(int rr) {
int d = rr - 4;
TtStructure tt = new TtStructure(d);
return tt.call(rr - 4);
}
}
這是一種更節省空間的方法。 與其在各處存儲一堆指針,不如只存儲實際數據和您需要的數據。 此外,如果你有嵌套的閉包,當你創建這些專門的結構時,你會自動將它們展平,因此間接性更少。
但是,如果您有可變閉包,則必須小心。 如果你有一個final
變量,那就沒問題了。 事實上,這正是Java 語言禁止關閉非final
變量的原因。
如果你想在閉包中允許可變變量,你需要顯式地添加一個間接層。 這可以是存儲一個實例變量的簡單 class,然后您可以在封閉的 scope和閉包中使用該變量。
public class Cell<T> {
public T impl;
public Cell(T impl) {
this.impl = impl;
}
}
您需要將任何局部變量包裝在Cell<T>
中,如果它 (a) 在閉包中使用,並且(b) 在任何時候重新分配給。 final
變量(因此永遠不會重新分配)不需要包裝,那些只在本地使用(永遠不會在閉包中)的變量不需要包裝。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.