Pangaea 언어의 원형 체인 정보

15761 단어 자제 언어Pangaea
TL;DR
  • 각 대상이 부모 대상의 참조를 가지도록 순서대로 진행하여 원형 체인
  • 을 실현한다.
  • 삽입 방법은 특정한 데이터 구조를 요구하기 때문에 평가에 사용되는 수신기도 원형 체인을 따라 검색
  • 원형 자체도 자신의 방법을 사용할 수 있도록 방법 호출 시 은근히 0값으로 전환
  • 개시하다
    2020년부터 스스로'팡나아'라는 프로그래밍 언어를 만들었다.
    원형 기반의 동적 유형 언어에서 하위 대상은 부모 대상의 속성을 계승한다.
    cat := {
      name: "Tama",
      # NOTE: Pangaeaではメソッドは単なる関数プロパティ
      meow: m{ "Meow. I am #{.name}.".p }
    }
    
    kitten := cat.bear({name: "Mike"})
    
    cat.meow # "Meow. I am Tama."
    kitten.meow # "Meow. I am Mike."
    
    언어에 대한 상세한 내용과 강좌는 과거의 보도를 보십시오.
    이 글에서는 판가를 원형 체인으로 계승할 때 시행착오가 있었던 점을 소개한다.
    (집필할 때도 창작부분v0.8.0 예상)
    상속수
    Pangaea의 상속 트리는 다음과 같습니다.예를 들어 소양{a: 1}이 계승Obj,[1, 2]이 계승Arr했다.
    - BaseObj
      - Obj
        - (object literal) {a: 1} etc.
        - Arr
          - (arr literal) [1, 2] etc.
        - Err
          - AssertionErr
          - NameErr
          - ...(その他各種エラー)
        - Func
          - (func literal) {|x| x+1} etc.
        - Iter
          - (iter literal) <{|x| x+1}> etc.
        - Map
          - (map literal) %{"a": 1} etc.
        - Nil
          - nil
        - Num
          - Float
            - (float literal) 1.0 etc.
          - Int
            - 0
              - false
            - 1
              - true
            - (int literal)
        - Range
          - (range literal) (1:10:2) etc.
        - Str
          - (str literal) "foo" etc.
    
    대상 조작 방법(속성)이 있는 것은 부 대상ArrObj이고 각 소양은 이것만 계승(자신이 없음)이다.
    원형 체인의 설치
    방법(속성)의 해결
    모든 대상은 자신의 부모 대상(원형)1이 있기 때문에 순서대로 호출하는 방법을 얻었다.
    원형 체인의 대상이 상응하는 명칭을 가진 방법이 있으면 이 방법을 되돌려주고 마지막까지 찾지 못하면 토해낸다NoPropErr2.
    # {a: 1} はプロパティaを持っているのでそれを直接呼び出す
    {a: 1}.a # 1
    # {a: 1} はプロパティ keysを持たないが、 Obj が持っている
    {a: 1}.keys # ["a"]
    # foo は誰も持っていない
    {a: 1}.foo # NoPropErr: property `foo` is not defined.
    
    # 参考:プロトタイプの一覧
    {a: 1}.ancestors # [Obj, BaseObj]
    
    해석기 내부에서도 이 같은 설명을 간단하게 실시했다.
    object/findprop.go
    func FindPropAlongProtos(o PanObject, propHash SymHash) (PanObject, bool) {
        // trace prototype chains
        for obj := o; obj != nil; obj = obj.Proto() {
            prop, ok := findProp(obj, propHash)
    
            if ok {
                return prop, true
            }
        }
        return nil, false
    }
    
    func findProp(o PanObject, propHash SymHash) (PanObject, bool) {
        obj, ok := o.(*PanObj)
        if !ok {
            return nil, false
        }
    
        elem, ok := (*obj.Pairs)[propHash]
    
        if !ok {
            return nil, false
        }
    
        return elem.Value, true
    }
    
    수신기의 해결
    다른 한편, 내부 설치로서 단지 이렇게 해서는 안 된다.
    삽입 방법은 특정한 데이터 구조 (int와arr 등) 가 필요합니다.데이터 구조는 상속 관계와 무관하기 때문에 하위 대상은 부모 대상의 방법을 사용할 수 없다.
    난처하다
    # 配列リテラル。データ構造は *object.PanArr
    arr := [1, 2]
    # arrを継承。データ構造はデフォルトの *object.PanObj
    child := arr.bear({a: 1})
    # has? は Arrの組み込みメソッド。*object.PanArrのデータ構造を要求するので、childをレシーバにすると処理できない!
    child.has?(1)
    
    따라서 삽입식 방법에서 평가에 사용되는 수신기(or파라미터)도 원형 체인을 통해 얻을 수 있다.
    props/arr_props.go
    func ArrProps(propContainer map[string]object.PanObject) map[string]object.PanObject {
        return map[string]object.PanObject{
            // Obj.has?の実装。要素一覧を舐めるので*PanArrのデータ構造が必要
            "has?": f(
                func(
                    env *object.Env, kwargs *object.PanObj, args ...object.PanObject,
                ) object.PanObject {
                    if len(args) < 2 {
                        return object.NewTypeErr("Arr#has? requires at least 2 args")
                    }
                    // レシーバは第一引数として渡される(型はインターフェースPanObject)が、実装が*PanArrでない場合要素を参照することができない
                    // そこで、プロトタイプチェーンを辿り*PanArrであるプロトタイプを取得
                    self, ok := object.TraceProtoOfArr(args[0])
                    if !ok {
                        return object.NewTypeErr(`\1 must be arr`)
                    }
    
                    // 以下selfをレシーバとし本処理
                    for _, elem := range self.Elems {
                        // ...
                    }
                },
            ),
    
    object/traceproto.go
    func TraceProtoOfArr(obj PanObject) (*PanArr, bool) {
        for o := obj; o.Proto() != nil; o = o.Proto() {
            if v, ok := o.(*PanArr); ok {
                return v, true
            }
        }
        return nil, false
    }
    
    child가 계승[1, 2]했기 때문에child.has?(1)는 실질적으로Arr['has?]([1, 2], 1)로 평가된다.수신기 대체 수신기는 언뜻 보면 위화감이 있지만 child 부모[1, 2]로 대처하는 것은 상속적으로 자연스러운 일이다.대체로 몇 가지 모델을 시험해 보았지만 예상대로 일을 하고 있다.
    계승의 예
    # 1. 配列リテラル [1, 2] (Arrを継承、データ構造は*PanArr)
    [1,2].has?(1) # true
    
    # 2. Arrをcallで継承 (できるものはリテラル [1, 2] と同じ。データ構造は*PanArr)
    Arr(1,2).has?(1) # true
    
    # 3. リテラルをbearで継承 (データ構造は*PanObj)
    child3 := [1, 2].bear({a: 1})
    child3.has?(1) # true
    
    # 4. Arrをbearで継承→callで継承 (データ構造は*PanArr)
    childArr := Arr.bear({foo: "bar"})
    childArr(1, 2).has?(1) # true
    
    # 5. リテラルをcallで継承 (データ構造は*PanArr)
    [1,2](3, 4).has?(1) # false
    
    *PanArr가 여러 원형 체인5.에 나타나도 수신기는 자신[3, 4]을 정확하게 사용했다.
    원형을 0값으로 볼 수 있도록 하다
    위에도 해결할 수 없는 문제가 하나 있다.Arr 자신의 방법을 사용할 수 없습니다.Arr 그 조상ObjBaseObj의 데이터 구조는 모두 *PanObj였고, 요구*PanArr의 삽입식 방법으로는 수신기의 오류를 해결할 수 없었다.
    물론 못 사용하기로 결정하면 되지만 모처럼 원형Arr을 표시해 배열로 처리했으면 좋겠다.따라서 수신기Arr[]에 의해 해결될 수 있다.
    우선, 모든 대상을 위해 0치 개념을 도입한다.
  • *PanObj 유형: 임의의 대상을 0값으로 할 수 있습니다
  • ex: Arr 0값 있음[]
  • 이외에: (편의를 위해) 자신을 0값으로 설정
  • 특정 데이터 구조를 나타내는 구조이기 때문에 수신기는 대부분 자신에게 해결되고 0값을 참고할 필요가 없다
  • 이어 수신기 해결 중 0값을 확인한다.
    object/traceproto.go
    func TraceProtoOfArr(obj PanObject) (*PanArr, bool) {
        for o := obj; o.Proto() != nil; o = o.Proto() {
            if v, ok := o.(*PanArr); ok {
                return v, true
            }
    
            // ゼロ値確認を追加
            // 自身のデータ構造が違っても、ゼロ値が*PanArrならゼロ値にレシーバ解決
            if a, ok := o.Zero().(*PanArr); ok {
                return a, true
            }
        }
        return nil, false
    }
    
    이렇게 되면 맑은 날Arr에 자신의 방법을 사용할 수 있다.
    # Arr は組み込みメソッドでは [] として扱われる
    Arr + [1, 2] # [1, 2]
    Arr.len # 0
    Arr.has?(1) # false
    
    (이 부분은 아직 수정 중이며 집필할 때 완성만 했다Arr.
    끝말
    원형의 계승구조는 간단하게 표현할 수 있지만 숨겨진 실제 데이터 구조를 처리할 때 생각해야 할 부분이 많다.
    이 보도의 내용은 다음 판본v0.8.0에 발표될 예정이다."이게 더 좋아요!"이런 댓글 달아주시면 감사하겠습니다!
    자바스크립트처럼 부모가 프로타입을 사용하는 속성을 가지고 있는 것이 아니라 원형으로 부모 자신을 참조하는 것이다. 
    엄밀히 말하면 모든 대상의 조상BaseObj까지 속성을 찾지 못하면 속성을 다시 획득_missing(Rubby 참조)

    좋은 웹페이지 즐겨찾기