`this`는 정적이지 않습니다.

2708 단어 language
몇 주 전에 프로그래밍 언어 전용 서브레딧에서 static 키워드에 대한 토론이 있었습니다. static는 실제로 스토리지 클래스이며 언어의 유형 시스템의 일부가 아니지만 특히 정적 함수에 관한 경우 매우 흥미롭게 역설적입니다.

모든 함수는 정적입니다.



바이너리 관점에서 볼 때 정적 함수와 비정적 함수는 없습니다. 기능은 모두 일급 엔터티입니다. 기능에 대한 static의 요점은 마법이 없다는 약속에 가깝습니다.

매직 함수의 전형적인 예는 멤버 함수입니다. 멤버 함수는 정적 함수이지만 많은 언어에서 볼 수 있듯이 자체 유형에 속합니다.

함수 유형의 구조



함수 유형은 매개변수 유형과 반환 유형으로 정의됩니다. 이것은 큰 거짓말이 시작되는 곳입니다

전역 함수에 대한 포인터를 가져 갑시다

module m;
function f(){}
var atF = &f;


이제 멤버 함수에 대한 포인터를 가져 갑시다.

module m;
struct S
{
    static function f1(){}
    function f2(){}
}

atF = &S.f1; // OK
atF = &S.f2; // NG, but type system lies here 


여기서 일어나는 일은 실제로 유형 불일치가 아닙니다. 모든 함수는 본질적으로 정적이라는 점을 기억하십시오. 여기서 일어나는 일은 언어 의미론이 유형 시스템을 깨뜨린다는 것입니다. f1f2는 모두 무효 함수입니다. 동일한 매개변수 유형, 동일한 반환 유형.

가장 큰 질문은 왜 대부분의 구조화된 언어가 컨텍스트를 공식적인 매개변수로 만들지 않았는가입니다.

공식적인 이것



여기 재미가 온다

module m;
struct S
{
    static function f1(){}
    function f2(S* this){}
}


따라서 더 이상 필요하지 않습니다static.

module m;
struct S
{
    function f1(){}
    function f2(S* this){}
}


그런 다음 f1f2에 대한 포인터는 실제로 다른 유형을 갖습니다.

컨텍스트 캡처가 편리합니다.



대부분의 언어는 유형 시스템을 깨기 때문에 멤버 함수에 대한 포인터를 가져오려면 특별한 것이 필요합니다. 정적 인 것처럼 멤버 함수에 대한 포인터를 사용하면 작동하지 않습니다. 그것을 사용하는 것은 segfault의 약속입니다.

유형 시스템을 깨는 언어는 팻 포인터에서 컨텍스트를 캡처하는 것입니다. 매우 똑똑합니다. 매직 함수가 있기 때문에 이제 매직 포인터가 필요합니다.

스틱스 방식



이 문서에서 설명하는 문제는 Styx에서 해결됩니다. 사전 시맨틱 패스 중에 this 매개변수가 static가 아닌 멤버 함수에 추가되므로 멤버 함수는 유형이 정확합니다. 그런 다음 이진 관점에서 this가 레지스터로 전달됩니다.

예를 들어 프로그램

unit this_is_not_static;

struct S
{
    static function f1(){ printf("%s\n", echo(func_t).stringof); }
    function f2(){ printf("%s\n", echo(func_t).stringof); }
}

function main():s32
{
    S.f1();
    var S s;
    s.f2();
    return 0;
}   


출력

static function f1()
function f2(S* this)


서론에서 언급한 토론 중에 정식 매개변수this가 필요한 언어가 하나 이상 있다는 말을 들었습니다. 이것은 내가 고려하는 옵션이지만 static 완전히 제거하지는 않습니다. 이 스토리지 클래스에는 다른 흥미로운 용도가 있습니다.

좋은 웹페이지 즐겨찾기