2012-07-20 2 views
4

CIL로 컴파일하려고하는 사용자 정의 스택 기반 언어가 있으므로 JITed 될 수 있습니다. 언어 자체는 매우 간단합니다. 정수와 부울 만 있기 때문입니다. 그러나 각 데이터 유형에는 전용 스택이 있습니다. 언어 그 자체는 일련의 명령어들로, 각 명령어는 어느 한 스택으로부터 값을 엿보고, 푸시하고, 팝 할 수 있습니다. 명령에 의해 푸시/팝 된 정수 또는 부울 수는 절대로 변경되지 않습니다 (명령에 고정 된 값). 또한 언어가 값을 읽고 쓰며 외부 메모리를 나타내는 평면 정수 배열이 있습니다. 스택 자체는 임의적으로 깊을 수 있습니다.스택 기반 언어를 CIL로 컴파일

"add", "subtract"등과 같은 간단한 명령의 경우 정수 스택 명령을 CIL로 변환하는 것이 거의 쉽습니다. CIL 스택은 정수 스택을 대체 할 수 있습니다 (단, CIL 스택의 깊이에 대한 한도는 스펙이나 실제에서 어느 정도가 될 수 있습니까?) 그러나 StoreIfTrue와 같은 명령도 있습니다.이 명령은 정수 스택의 값을 일부 인덱스의 플랫 정수 배열에만 저장합니다 (인덱스도 포함). 부울 스택의 맨 위 값이 참이면 정수 스택에서). 그래서 일부 명령에 대해 부울 스택과 정수 스택에 대한 액세스가 필요합니다.

지금은 부울 스택을 나타내는 System.Collections.Generic.Stack을 유지 관리해야합니다. 그러나 CIL과보다 직접적으로 호환되는 단일 스택 모델에 내 사용자 지정 언어의 두 스택 모델을 "평평하게"하는 알려진 알고리즘이나 메서드가 있는지 궁금합니다.

+0

CIL 스택은 유형이 적어 int와 bool을 처리하고 혼합 할 수 있습니다. 다중 스택 실행 모델을 유형없는 단일 스택으로 변환 할 수있는 방법이 있어야하지만 어떻게해야하는지에 대한 질문에는 분명하지 않습니다. –

답변

0

예를 들어 C#에서 CIL 코드를 생성하는 방법을 알고 있는지 여부를 추론 할 수 없습니다. 이를 수행하려면 Reflection 또는 Cecil을 사용할 수 있습니다.

가상 실행 시스템 (VES, CIL 명령어를 실행할 가상 시스템 모델)의 경우 스택 (및 레지스터)의 값에는 연관된 복합 유형이 없습니다. 단순한 유형 (int32, int64, 관리 객체 참조, 관리 된 포인터 및 부동 소수점) 만 VES에서 추적합니다. 따라서 VES는 스택의 부울과 정수의 차이를 볼 수 없습니다 (내부적으로 VES는 부울을 32 비트 정수로 처리합니다). 따라서 실행 스택을 사용하여 부울 및 정수 스택을 시뮬레이트 할 수 없습니다. 당신도 똑같이 할 수 있습니다 : 부울을 정수와 0이 아닌 정수로 처리하고 부울을 참으로 처리하십시오. 따라서 두 정수를 비교하면 다른 정수가됩니다. 그러나 그 다음에는 스택이 두 개가 아니라 하나입니다.


편집 :

아, 그렇군요. 귀하의 언어는 일반적인 프로그래밍 언어를위한 것이며, 따라서 매우 견고해야하며 가능한 모든 입력 (유효하지 않은 입력 포함)에 대해 사전 정의 된 (또는 없음) 동작을 가져야합니다. 가능한 각 유형에 대해 별도의 스택을 가짐으로써 임의의 임의의 유형 대신 호환 가능한 피연산자가 사용되는 경우가 더 많습니다.

여러 스택을 시뮬레이션하는 데 단일 스택을 사용할 수 없으므로 각 유형에 대해 Stack<T> 실제 개체를 사용하고 CIL 스택을 사용하지 않을 것입니다. 이것은 몇 가지 장점이 있습니다 쉽게

  • 미래
  • 의 새로운 유형을 추가 할을 스택이 검사는
  • 쉽게이 유형을 혼합 사용자 정의 방식보다 관리 (예 : 작업 무 조작하기 위해) 경계 할 수 있습니다 하나의 스택에
  • 랜덤 액세스
  • CIL 내부를 알아야 할 필요가 없으므로 Mono 및.인터넷
  • CIL 스택은 스택 프레임과 주소를
+0

나는 CIL을 생성 할 수있다. 나는 정수로서 부울을 다루는 것이 싫어. 하지만 두 개의 논리 스택을 하나의 실제 실행 스택에 결합하는 방법은 없습니다. 그게 내 질문의 핵심이야. –

+0

또는 다음과 같이 말하십시오 : 제 언어는 두 개의 스택 머신을 사용합니다. 단일 스택 머신을 효율적으로 사용하려면 어떻게 처리해야합니까 (컴파일 단계의 일부로)? –

+0

일반적으로 하나의 스택을 사용하여 두 개의 스택을 시뮬레이션 할 수 없습니다. 왜 처음에는 논리 스택이 두 개입니까? 그것은 단지 하나의 스택을 가지며 모든 부울 및 정수 값을 섞어서 사용하는 것이 나에게 오해하지 않는 한 나에게 더 이해가됩니다. 'add' 명령은 두 개의 값을 (타입에 관계없이) 띄울 수 있고, 그것들을 더하고 결과를 되돌릴 수 있습니다. 그런 다음 부울을 취하는 후속 if 명령은 스택의 최상위 정수 ('add'에 의해 푸시 된 정수)를 가져오고 부울로 가장합니다. 그리고 다른 방법. – Virtlink

1

를 반환, 일시적 피연산자 다음이다 나는 하나의 스택에서 두 개의 독립적 인 스택을 저장하는, (가능한 적어도 외부의 임시 저장하지 않고 아니라고 생각하지만, 당신은 얻을 것 끔찍한 성능). 그 이유는 두 가지 스택의 꼭대기가 어떤 표현을 사용하든 관계없이 항상 실제 스택의 상단에 가깝게 배치하는 방법이 없기 때문입니다.

그러나 CIL은 스택과 힙을 가지고 있지 않으며 로컬 변수도 가지고 있습니다. 그러나 상수 인덱스를 통해서만 로컬 변수에 액세스 할 수 있습니다. 따라서 컴파일 타임에 항상 스택 상단의 인덱스를 알고 있고 스택의 최대 크기를 알고 있다면 로컬 변수를 사용하여 스택을 나타낼 수 있습니다. 그러나 나는이 두 조건이 당신의 경우에 유지 될 것이라고 생각하지 않습니다.

덕분에 스택 중 하나 또는 모두에 Stack<T>을 사용하는 것이 가장 좋은 방법이라고 생각합니다.

+0

스택 깊이를 처리하는 것은 까다로울 수 있지만 각 명령에 고정 된 arity가 있으므로 상수 인덱스를 찾는 것이 가능할 것이라고 생각합니다. 스택을 사용하는 것보다 훨씬 더 빠르는지 테스트해야합니다. . –

관련 문제