게시판 인덱스

 
 FAQFAQ   검색검색   멤버리스트멤버리스트   사용자 그룹사용자 그룹   사용자 등록하기사용자 등록하기 
 개인 정보개인 정보   비공개 메시지를 확인하려면 로그인하십시오비공개 메시지를 확인하려면 로그인하십시오   로그인로그인 

숙제 6-1에서 두 종류의 module간의 타입 충돌에 대한 질문입니다.

 
글 쓰기   답변 달기     게시판 인덱스 -> 4190.310 Programming Languages (Fall 2012)
이전 주제 보기 :: 다음 주제 보기  
글쓴이 메시지
윤형석



가입: 2012년 9월 5일
올린 글: 26

올리기올려짐: 2012년11월13일 15:45    주제: 숙제 6-1에서 두 종류의 module간의 타입 충돌에 대한 질문입니다. 인용과 함께 답변

작년 게시판을 보다보니, 다음과 같은 글이 있었습니다.


https://ropas.snu.ac.kr/phpbb/viewtopic.php?t=2997



인용:
이번 숙제에서 Sm5와 Sonata라는 두 모듈을 사용하는데 실제 이 두 모듈 내부의 type 정의들은 거의 일치합니다.

그러다보니 Sm5의 PUSH obj 명령어의 obj를 바로 Sonata에 집어넣으면 type error가 발생합니다. 실제로는 Sm5.obj와 Sonata.obj의 내부 구조는 똑같은데 말이죠.



1.
Ocaml 메뉴얼을 찾아보니 이런 경우 "with type" 이라는 형식을 이용한 sharing constraints를 통해 두 타입을 같다고 지정할 수 있다고 합니다. 하지만 예제 코드를 보면 이런 정의가 타입이 있는 모듈 내에서 이뤄지기 때문에 hw6_1.ml만 제출해야 하는 이번 숙제에서는 사용하기 힘든 것 같습니다. 두 모듈을 open으로 불러들인 후 두 모듈간에 sharing constraints를 지정해 줄 수 있는 방법이 있나요?



2. 처음에는 그냥 저 문제를 회피(?)하고 내부로 파고들어 일일히 선언을 해줄려고 했었는데 역시 문제가 생겼습니다.

| (Sm5.PUSH (Sm5.Val (Sm5.L (i1, i2)))) :: rest ->
(Sonata.PUSH (Sonata.Val (Sonata.L (i1, i2)))) :: (rozetta rest)

Error: This pattern matches values of type 'a * 'b
but a pattern was expected which matches values of type Sm5.Sm5.loc

두 모듈 모두 type loc = (int * int)로 정의되어있는데도 불구하고 저런 에러가 발생하는 이유에 대해 질문을 드립니다. loc이라는 타입이 양 모듈의 sig에서는 선언만 되어 있고 definition은 struct 속에 들어가 있기 때문에 hw6_1.ml에서는 접근할 수 없어서 에러가 발생하는 것인가요?


여기에 이 때 당시의 조교님이 답변을 다음과 같이 달아뒀는데, 이 답변 그대로 받아들여도 될까 싶어 질문을 드립니다.


인용:
이 부분을 어떻게 해야할까 고민을 많이 해보았습니다.


분명 Sm5의 정의에 따르면 cmd를 이용해서 직접 Loc이나 Record를 push할 수 있습니다.

하지만 그게 일반적인, 제대로 된 Sm5 프로그래밍 방법은 아닐것입니다.

Loc은 malloc을 이용해 할당받은것을 이용해야합니다.
그렇지 않은 주소를 직접 이용하면 메모리 구현에 따라 에러가 발생할 수 있겠죠.

마치 C에서 보통 주소값을
코드:

int *p = malloc(16);
int *q = &i;


이런식으로 쓰는것이 정상적인 방법이지만

코드:

int *p=(int *)0x08048576;


이렇게 쓰는것도 허용하는 것처럼요. 하지만 이런 식의 주소값은
그 프로그램이 얹혀 돌고있는 기계와 운영체제를 확실히 꿰고있을 때에만
매우 제한적으로 쓰입니다.


Sm5의 모듈타입에서 loc과 record의 타입을 숨기고있는것도 그런 상황을 반영합니다.

실제로 K -> SM5 인터프리터를 작성하실때는 그런 고민을 하지 않으셨을겁니다.

malloc과 box, unbox만으로 필요한 모든것을 표현할 수 있으니까요.



그래서 다음과 같이 결정했습니다.

1. Sm5 모듈은 기존에 드린 뼈대 그대로입니다.

loc 값과 record 값이 어떻게 생겼는지 알 수 없기 때문에,

그런 입력은 들어오지 않는다고 가정하겠습니다.

입력으로 들어온 Sm5 프로그램이 loc이나 record 상수를 push하려 시도하면

코드:

raise (Invalid_argument "rozetta")


예외를 발생시켜주세요.

예를 들어,

코드:

Sm5.PUSH(Sm5.Val(Sm5.L location))
Sm5.PUSH(Sm5.Val(Sm5.R record))


이런 명령들은 입력으로 들어오지 않습니다.

물론 이는 push v::C 의 경우에만 해당됩니다.
push x::C로 이미 환경에 저장되어있던 무언가를 꺼내오는 것에는 해당되지 않습니다.


2. Sonata 모듈의 경우 모듈 타입에 loc = int * int 라는 부분을 추가하겠습니다.

Sm5 프로그램을 Sonata 프로그램으로 인코딩하는 과정에서

미리 고정된 loc 값이 필요하다면 쓰실 수 있습니다.

sonata.ml 파일의

코드:

module type SONATA =
sig
...
and loc
...
end


이 부분을

코드:

module type SONATA =
sig
...
and loc = int * int
...
end


이렇게 고쳐서 쓰세요.

뼈대도 이렇게 고쳐서 다시 올려드리겠습니다.

단, record는 여전히 가려져있습니다.
어떤 record 값을 만들어야한다면 push와 box 명령을 이용하세요.
위로
사용자 정보 보기 비밀 메시지 보내기
이승중



가입: 2010년 6월 22일
올린 글: 561

올리기올려짐: 2012년11월13일 18:28    주제: 인용과 함께 답변

1은 그대로 따르겠습니다.

2번은 뼈대코드에 이미 반영되어 있습니다.
위로
사용자 정보 보기 비밀 메시지 보내기
이전 글 표시:   
글 쓰기   답변 달기     게시판 인덱스 -> 4190.310 Programming Languages (Fall 2012) 시간대: GMT + 9 시간(한국)
페이지 11

 
건너뛰기:  
새로운 주제를 올릴 수 없습니다
답글을 올릴 수 없습니다
주제를 수정할 수 없습니다
올린 글을 삭제할 수 없습니다
투표를 할 수 없습니다


Powered by phpBB 2.0.21-7 (Debian) © 2001, 2005 phpBB Group
Translated by kss & drssay