>백엔드 개발 >Golang >파스칼 함수 지원

파스칼 함수 지원

王林
王林원래의
2024-07-16 08:03:50617검색

Suporte às funções do Pascal

POJ(JVM의 Pascal)을 따르지 않는 사람들을 위해 하위 집합을 Pascal에서 JASM( Java Assembly)를 통해 JVM을 실행 환경으로 사용할 수 있습니다.

지난 게시물에서는 오류 캡처, 문자열 유형에 대한 관계 연산자 지원, Pascal의 프로시저 정의(및 사용) 가능성이 일부 개선되었습니다.

이 간행물에서는 Pascal 함수(함수)에 대한 지원을 다룹니다. 얼마 지나지 않아 프로젝트의 마지막 목표인 표준 입력에서 숫자를 읽고 계승값을 계산하는 작업을 완료할 수 있습니다.

JVM용으로 컴파일하는 동안 이 놀라운 가상 머신의 다양한 지점의 기능을 자세히 설명할 필요가 있습니다. 따라서 JVM의 내부 기능과 일부 지침(opcode)을 여러 번 자세히 설명합니다.

파스칼 함수 지원(함수)

지금까지는 Pascal의 프로시저를 정의하고 호출하는 방법이 있었습니다. 이 PR에서 Pascal의 함수를 정의하고 호출하는 것도 가능합니다.

이 커밋에서는 JVM이 함수 정의 및 호출을 처리하는 방법을 이해하기 위해 Java 프로그램을 구현했습니다. 아래 Java 프로그램에서:

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!";
    }
}

클래스를 분해하면 다음과 같은 어셈블리가 생성됩니다.

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: }

이 예를 통해 다음을 확인할 수 있습니다.

  • 메서드를 호출하기 위해 JVM은 "invokestatic FunctionCall.myMethod()java/lang/String"(8행) 명령을 사용했습니다. 여기서:
    • invokestatic은 호출할 메서드의 전체 서명을 인수로 받는 명령어입니다.
    • FunctionCall은 클래스 이름입니다.
    • myMethod()java/lang/String은 매개변수(이 예에서는 없음)와 반환 유형(이 예에서는 java/lang/String)을 포함하는 메소드의 완전한 서명입니다. ;
  • 명령어 areturn(라인 17)은 함수를 종료하고 반환 문자열을 스택에 남깁니다.

아래 Pascal 프로그램에서 가져온 내용은 ​​다음과 같습니다.

program function_call_wo_params;

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

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

POJ는 다음 JASM을 생성하도록 조정되었습니다.

// 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
    }
}

가장 세심한 사람은 위의 "astore 100"을 보고 다음과 같이 생각했을 것입니다.

  • 왜 함수 반환을 지역 변수에 저장하나요? 이는 Pascal에서는 함수 중에 함수의 반환 값을 N번 설정할 수 있지만 JVM에서는 하나의 결과만 쌓을 수 있기 때문입니다.
  • 왜 100위인가요? 함수 또는 프로시저의 지역 변수는 위치 0에서 시작하므로 위치 100은 반환값을 저장하기 위해 임의로 선택되었습니다.
  • 그러나 이 예에서는 ldc "Hello from myfunction!" 명령만 생성되고 이어서 areturn 명령이 생성되도록 최적화하는 것이 가능하지 않을까요? 예, 그렇습니다. 하지만 POJ는 시장 컴파일러에 존재하는 최적화 단계(향후 구현될 수 있음)를 구현하지 않습니다.

이 커밋은 기호 테이블과 파서에서 "함수" 유형에 대한 지원을 구현합니다.

위의 예에서 함수에는 인수가 없습니다. 이 커밋에서는 인수가 있는 함수에 대해 예상되는 결과가 구현되었습니다. 아래의 Pascal 프로그램에서 이를 사용하세요.

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가 다음 JASM을 올바르게 생성했습니다.

// 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
    }
}

다음 단계

다음 간행물에서는 컨텍스트, 발견된 버그, 중첩 문장, 데이터 입력에 대해 이야기하고 이 프로젝트의 마지막 목표인 계승을 재귀적으로 계산한다는 결론을 내릴 것입니다.

완전한 프로젝트 코드

프로젝트의 전체 코드와 문서가 포함된 저장소가 여기에 있습니다.

위 내용은 파스칼 함수 지원의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.