簡體   English   中英

如何為 Jasmin 字節碼聲明嵌套的 function?

[英]How to declare nested function for Jasmin byte code?

我正在編寫一個編譯器,我需要將 Mini Pascal(Pascal 的一個簡單版本)轉換為 Jasmin 字節碼。

  1. 但是如何在 Jasmin 語言中聲明嵌套的 function呢?

  2. 因為function tt(I): I只能傳入一個 Integer (即rr )如何將變量dfunction 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM