Rumah >pembangunan bahagian belakang >Golang >Sokongan untuk fungsi Pascal

Sokongan untuk fungsi Pascal

王林
王林asal
2024-07-16 08:03:50617semak imbas

Suporte às funções do Pascal

Bagi mereka yang tidak mengikuti POJ (Pascal pada JVM) ia adalah pengkompil yang mengubah subset daripada Pascal kepada JASM ( Java Assembly) supaya kita boleh menggunakan JVM sebagai persekitaran pelaksanaan.

Dalam siaran terakhir kami mempunyai beberapa penambahbaikan dalam penangkapan ralat, sokongan untuk pengendali hubungan untuk jenis rentetan dan kemungkinan untuk mentakrif (dan menggunakan) prosedur Pascal.

Dalam penerbitan ini kami akan merangkumi sokongan untuk fungsi Pascal (fungsi). Tidak lama sebelum kita boleh menyelesaikan objektif terakhir projek: membaca nombor daripada input standard dan mengira pemfaktorannya.

Ketika kami sedang menyusun untuk JVM, adalah perlu untuk memperincikan fungsi pelbagai titik mesin maya yang luar biasa ini. Oleh itu, pada pelbagai masa saya memperincikan fungsi dalaman JVM serta beberapa arahannya (opcodes).

Sokongan untuk fungsi Pascal (fungsi)

Sehingga kini kami mempunyai cara untuk mentakrifkan dan menggunakan prosedur Pascal. Daripada PR ini, ia juga mungkin untuk mentakrifkan dan menggunakan fungsi Pascal.

Dalam komit ini, program Java telah dilaksanakan untuk memahami cara JVM menangani fungsi mentakrif dan memanggil. Daripada program Java di bawah:

public class FunctionCall {
    public static void main(String[] args) {
        System.out.println("Hello from main!");
        System.out.println(myMethod());
    }

    static String myMethod() {
        return "Hello from myMethod!";
    }
}

Apabila kami membuka kelas kami mendapat pemasangan berikut:

1:  public class FunctionCall {
2:      public static main([java/lang/String)V {
3:          getstatic java/lang/System.out java/io/PrintStream
4:          ldc "Hello from main!"
5:          invokevirtual java/io/PrintStream.println(java/lang/String)V
6:
7:          getstatic java/lang/System.out java/io/PrintStream
8:          invokestatic FunctionCall.myMethod()java/lang/String
9:          invokevirtual java/io/PrintStream.println(java/lang/String)V
10:
11:         return
12:     }
13:
14:     static myMethod()java/lang/String {
15:         ldc "Hello from myMethod!"
16:
17:         areturn
18:     }
19: }

Dengan contoh ini adalah mungkin untuk mengenal pasti bahawa:

  • Untuk memanggil kaedah, JVM menggunakan arahan "invokestatic FunctionCall.myMethod()java/lang/String" (baris 8) di mana:
    • invokestatic ialah arahan yang menerima sebagai argumen tandatangan lengkap kaedah yang akan dipanggil;
    • FunctionCall ialah nama kelas;
    • myMethod()java/lang/String ialah tandatangan lengkap kaedah dengan parameternya (dalam contoh ini tiada) dan jenis pulangan (dalam contoh ini java/lang/String) ;
  • Arahan areturn (baris 17) menamatkan fungsi dan meninggalkan rentetan kembali pada tindanan.

Begitulah, daripada program Pascal di bawah:

program function_call_wo_params;

function myfunction : string;
begin
    myfunction := 'Hello from myfunction!';
end;

begin
    writeln('Hello from main!');
    writeln(myfunction());
end.

POJ telah dilaraskan untuk menjana JASM berikut:

// Code generated by POJ 0.1
public class function_call_wo_params {
    ;; function myfunction : string;
    static myfunction()java/lang/String {
        ldc "Hello from myfunction!"
        astore 100   ;; Posição 100 guarda o retorno da função
        aload 100    ;; Empilha o retorno da função
        areturn      ;; Deixa "Hello from myfunction!" na pilha
    }

    ;; procedure principal (main)
    public static main([java/lang/String)V {
        ;; writeln('Hello from main!');
        getstatic java/lang/System.out java/io/PrintStream
        ldc "Hello from main!"
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        ;; writeln(myfunction());
        getstatic java/lang/System.out java/io/PrintStream
        invokestatic function_call_wo_params.myfunction()java/lang/String 
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        return
    }
}

Yang paling penuh perhatian pasti perasan "astore 100" di atas dan berfikir:

  • Mengapa menyimpan pulangan fungsi dalam pembolehubah setempat? Ini disebabkan oleh fakta bahawa dalam Pascal nilai pulangan fungsi boleh ditetapkan N kali semasa fungsi, tetapi kita hanya boleh menyusun satu hasil dalam JVM;
  • Kenapa di kedudukan 100? Pembolehubah tempatan fungsi atau prosedur bermula pada kedudukan 0, jadi kedudukan 100 dipilih sewenang-wenangnya untuk menyimpan pulangan;
  • Tetapi bukankah mungkin untuk mengoptimumkan supaya dalam contoh ini hanya arahan ldc "Hello from myfunction!" dijana diikuti dengan arahan return? Ya, memang betul, tetapi POJ tidak melaksanakan fasa pengoptimuman yang wujud dalam penyusun pasaran, sesuatu yang boleh dilaksanakan pada masa hadapan.

Komit ini melaksanakan sokongan untuk "fungsi" taip dalam jadual simbol dan dalam penghurai.

Dalam contoh di atas, fungsi tidak mempunyai hujah. Dalam komit ini, hasil yang diharapkan untuk fungsi dengan hujah telah dilaksanakan. Dengan ini daripada program Pascal di bawah:

program function_call_with_two_params;

function addvalues(value1, value2: integer) : integer;
begin
    addvalues := value1 + value2;
end;

begin
    writeln('2+4=', addvalues(2, 4));
end.

POJ menjana JASM berikut dengan betul:

// Code generated by POJ 0.1
public class function_call_with_two_params {
    ;; function addvalues(value1, value2: integer) : integer;
    static addvalues(I, I)I {
        ;; addvalues := value1 + value2;
        iload 0
        iload 1
        iadd 
        istore 100
        iload 100

        ireturn 
    }

    ;; procedure main
    public static main([java/lang/String)V {
        ;; writeln('2+4=', ...);
        getstatic java/lang/System.out java/io/PrintStream
        ldc "2+4="
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream

        ;; aqui código para invocar addvalues(2, 4)
        sipush 2
        sipush 4
        invokestatic function_call_with_two_params.addvalues(I, I)I 

        ;; aqui código para invocar writeln com retorno addvalues
        invokevirtual java/io/PrintStream.print(I)V
        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        return
    }
}

Langkah seterusnya

Dalam penerbitan seterusnya kita akan bercakap tentang konteks, pepijat ditemui, ayat bersarang, kemasukan data dan menyimpulkan objektif terakhir projek ini: mengira faktorial secara rekursif.

Kod projek lengkap

Repositori dengan kod dan dokumentasi lengkap projek ada di sini.

Atas ialah kandungan terperinci Sokongan untuk fungsi Pascal. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn