2013-11-04 2 views
4

그래서 VM 실행을위한 바이트 코드와 네이티브 바이너리로 컴파일하기위한 중간 언어로 컴파일하는 프로그래밍 언어를 개발 중입니다. 충분히 낮은 수준의 이식성을 가지고 있기 때문에 C를 선택했기 때문에 기존 컴파일러를 재사용하고 각기 다른 플랫폼과 기이 한 것들에 대해 어셈블리에 컴파일러를 작성하지 않아도되므로 엄청난 노력을 아낄 수있었습니다.순환 종속성 수수께끼를 "우아하게"해결

그러나 기존 컴파일러에는 단점이 있으며 그 중 하나는 순환 종속성 문제입니다. 명확한 선언을하지 않고 포인터와 여분의 간접 참조와 낭비되는 메모리를 사용하지 않고도 선언문을 정의와 분리하지 않고도 C/C++과 달리 우아한 방식으로 순환 종속성을 해결하려고합니다 ... 다른 말로하면, 일부 프로그래밍 언어처럼 개발자로부터이 문제를 멀리하십시오.

현재의 C/C++ 컴파일러의 주된 문제점은 프로그래머의 의도가 이미 코드로 표현되어 있기 때문에 미래가 아니라해도 미래를 내다 볼 수 없다는 것입니다. 그 문제가 없다면 파싱 진행의 특정 시점을 넘어서는 것을 인식하지 못하고 원형 의존성이있는 객체의 크기를 알고 적절한 오프셋을 계산할 수 있습니다.

나는 상속 된 구조체 멤버의 "인라인 확장"을 단순히 수행하는 "위조 된"상속을 이미 구현 했으므로 동일한 접근법을 사용하여 실제로 집계를 위조 할 수도 있다고 생각합니다. 가장 기본적이고 간단한 예에서 :

typedef struct { 
    int A_a; 
    int b; 
} B; 

및 컴파일러는 "번역"약간의 수행합니다 :

typedef struct { 
    int a; 
} A; 

typedef struct { 
    A a; 
    int b; 
} B; 

이된다

B b; 
b.a.a = 7; 

이된다 :

b.A_a = 7; 

그리고 같은 방식으로 모든 struc 튜어는 기본 유형 만 포함하는 단일 루트 구조로 축소되었습니다. 이 방법은 크기가 미리 알려지지 않은 구조체에 절대적으로 사용되는 형식이 없으므로 정의 순서가 무의미 해집니다. 당연히이 혼란은 사용자로부터 숨겨져 있으며, 사용자 측이 구조화되고 읽기 쉽도록 유지되는 동안 컴파일러의 "눈으로 볼 수있는"것입니다. 그리고 그것은 말할 것도없이 바이너리 풋 프린트는 일반 C/C++ 코드와의 호환성을 위해 보존되지만 붕괴 구조는 집계 또는 상속을 사용하는 일반 구조와 동일한 바이너리입니다.

제 질문은 소리가 좋은 아이디어 같습니까? 잘못 될 수있는 것이 있다면 내가 놓친 것입니까?

편집 : C/C++ 관련 어려움을 "닭고기 또는 계란"논리적 인 역설이 아닌 순환 의존성으로 해결하는 것을 목표로합니다. obviosly 무한 루프의 어떤 형태로 이어지지 않고 두 객체가 서로를 포함하는 것은 불가능합니다.

+1

인상적 수 있지만 인라인 확장에 대한 진짜 "포인트"가 있습니다 ? 'baa'가 아닌'b.A_a'에 접근 할 때 생성 된 코드가 다른 것입니까? 정확히 똑같을 것이라고 기대할 수 있습니다. 많은 이득을주지 않고 "최적화"하기 위해 많은 작업을하고 있습니다. – unwind

+1

@unwind - 순환 종속성은 멸종 된 무관 한 문제가됩니다. –

+1

아, 알겠습니다. C와 유사한 예제에서 역순으로 A와 B가있는 경우 더 명확했을 것입니다. C 선언은 문제가 없으며 원형 문제는 없습니다. – unwind

답변

1

원시 멤버를 가리켜 "호환 가능한 유형"에 대한 포인터를 얻을 수 없으므로 하위 구조에 대한 포인터를 안전하게 사용할 수 없습니다. 예 :

struct Foo { 
    short a; 
    int b; 
}; 

struct Bar { 
    struct Foo foo; 
}; 

struct Bar bar; 

포인터 후 &bar.foo&bar.foo.a는 다른 유형을 가지고 상호 교환 사용할 수 없습니다. 또한 엄격한 앨리어싱 규칙을 위반하지 않고 정의되지 않은 동작을 트리거하여 서로의 유형에 캐스트 할 수 없습니다.

문제

전체 struct 정의 매번 인라인 방지 할 수 있습니다 :

struct Bar { 
    struct { short a; int b; } foo; 
}; 

지금 &bar.astruct Foo 호환되는 유형입니다 struct {short; int;}에 대한 포인터입니다.

(이 또한. 패딩/struct -typed 회원들과 원시적 구성원 간의 정렬 차이가 있지만, 나는이의 예를 찾을 수 없습니다

+0

필자는 수동으로 패딩 바이트를 수동으로 삽입하여 바이너리 호환성을 유지하지만, 컴파일러는 구조를 집계 할 때 C 컴파일러가 수행 할 작업을 준수합니다. –