설명서를 유동이 원해서 쓰긴 하는데 사실 언젠가는 써야했던 것이긴 합니다.
설명이 ㅄ같아도 이해해주세요.
0. 개요: 구문론, 코드 작성, 의미론, 질의와 응답.
1. 구문론
Butterfly에서 기본 객체는 타입, 술어, 변수, 생성자의 4가지 종류 중 하나입니다.
다른 객체는 무엇이고 어떻게 만드는지 알아봅시다.
1.1 값
값은 n항 생성자가 n개의 값과 결합한 것입니다.
즉, 0항 생성자는 그 자체로 값입니다.
1.2. 항
항은 변수이거나 n항 생성자가 n개의 항과 결합한 것입니다.
즉, 모든 값은 항입니다.
1.3. 식
식은 n항 술어가 n개의 항과 결합한 것입니다.
1.4. 타입
모든 결합이 적법한 것은 아닙니다. 타입이 일치해야 합니다.
1.5. 공리
0개 이상의 식을 전제로 하고 1개의 식을 결론으로 합니다.
2. 코드 작성
Butterfly에서 모든 문장은 타입선언, 타입 정의, 술어 선언, 공리 생성 4 가지 중 하나입니다.
2.1. 식별자(identifier)
타입, 술어, 변수, 생성자만이 식별자를 가집니다.
타입과 술어의 식별자는 대문자 또는 소문자의 유한열이며 첫 글자는 무조건 대문자입니다.
변수와 생성자의 식별자는 소문자 또는 숫자 또는 밑줄문자의 유한열이며 첫 글자는 무조건 소문자입니다.
예를 들어 Nat은 타입의 식별자가 될 수 있고 n_1은 변수의 식별자가 될 수 있습니다.
2.2. 타입 선언
타입의 식별자가 될 수 있는 문자열에 점을 붙이면 됩니다.
Nat이라는 타입을 선언하고 싶으면 다음과 같이 하면 됩니다.
- Nat.
2.3. 술어 선언
술어의 식별자가 될 수 있는 문자열 뒤에 괄호와 점을 붙이고
괄호 안에 각 항이 취할 타입을 적어주면 됩니다.
예를 들어 자연수를 첫 번째 항으로 취하는 1항 술어 Main을 다음과 같이 선언할 수 있습니다.
- Main( Nat ).
2.4. 타입 정의
타입의 식별자를 쓴 다음 중괄호를 붙이고
중괄호 안에서 생성자들을 정의합니다.
생성자들은 그것의 각 항이 취하는 타입과 형식문법의 생성규칙에 의하여 정의됩니다.
예를 들어 타입 Nat을 다음 코드에서처럼 0항 생성자 zero와 1항 생성자 succ으로 정의할 수 있습니다.
- Nat
- {
- zero( ) → 'z'.
- succ( Nat ) → 's' 1.
- }
여기서 0항 생성자 zero( )와 대응되는 문자열은 'z'이고,
첫 번째 항의 타입으로 Nat을 가지는 1항 생성자 succ( Nat )과 대응되는 문자열은 's' 1입니다.
단, 이때 1은 succ의 첫 번째 항과 대응되는 문자열을 의미합니다.
2.5. 공리 생성
전제가 되는 식들을 쓰고 "/"를 붙인 뒤 결론을 쓰고 점을 붙입니다.
예를 들어 다음과 같이 공리 2개를 코딩할 수 있습니다.
- / Main( zero( ) ).
- Main( n ) / Main( succ( n ) ).
3. 의미론
이제 작성한 코드가 무슨 의미인지 알아봅시다.
3.1. 값
생성자가 값들과 결합한 것이 값이라고 말했죠?
그러므로 succ( zero( ) )나 succ( succ( zero( ) ) )은 값입니다.
모든 적법한 값은 타입에 속하고 문자열로 변환될 수 있습니다.
위의 두 값은 Nat에 속하고 각각 'sz'와 'ssz'로 변환될 수 있습니다.
succ과 대응되는 문자열은 's' 1이고 zero와 대응되는 문자열은 'z'이므로
succ( zero( ) ) → 's' zero( ) → 's' 'z' ???? 'sz'이고
succ( succ( zero( ) ) ) → 's' succ( zero( ) ) → 's' 's' zero( ) → 's' 's' 'z' ???? 'ssz'이기 때문입니다.
한편 위의 두 값이 서로 다름을 알 수 있습니다.
3.2. 항
변수 그 자체로 항이 될 수 있고, 생성자가 항들과 결합해도 항입니다.
그러므로 succ( n ), succ( succ( n ) )은 항입니다.
모든 적법한 항은 타입에 속하고 위의 두 항은 Nat에 속합니다.
여기서 위 두 항은 각각 's' n과 'ss' n으로 변환될 수 있습니다.
한편, 항에 있는 모든 변수들에 값을 배정하여 그 항을 값으로 평가할 수 있습니다.
3.3. 식
술어가 항들과 결합한 것으로 Main( succ( n ) )이나 Main( 's' n )은 식입니다.
항 succ( n )을 문자열로 변환하면 's' n이기 때문에
인터프리터는 위 두 식을 같다고 간주합니다.
식에 있는 모든 변수에 변수 배정에 따라 값을 배정하면
식이 유도될 수 있는지 없는지를 논할 수 있습니다.
3.4. 공리
각 공리는 임의의 변수 배정에 대하여 전제들이 모두 유도될 수 있을 때 결론도 유도될 수 있다는 뜻을 가집니다.
"/ Main( zero( ) )." 같은 공리는 전제들의 집합이 공집합이므로 식 Main( 'z' )는 임의의 변수 배정에 대하여 항상 유도될 수 있습니다.
그리고 공리 "Main( n ) / Main( succ( n ) )."에 의하여 식 Main( 'sz' )가 유도되고 다시 식 Main( 'ssz' )가 유도되고 ....
한편, 공리를 생성자와 괄호를 일일이 치지 않고 문자열로 단축해서 코딩할 수 있습니다.
4. 질의와 응답
한 코드를 인터프리터가 해석하면 질의를 받아 응답할 수 있습니다.
질의받은 식의 각 변수에 어떤 값을 배정할 때 그 식이 유도될 수 있는지를 답합니다.
예를 들어 "Main( 'ssz' )?"라고 질의하면
- +
- + a → 'z'.
- ▶ a → 's' Nat1.
- ▶+ Nat1 = a.
예시가 너무 빈약한가요? 질문 받아요.
반환에 관한 구문들이 잘 와닿지가 않네요 +나 ▶+가 어떤 의미로 쓰인건가요?
+는 유도될 수 있다는 뜻이고 세모는 가지를 의미합니다. - 훈다리 훈다리
타입을 나타내는 기호로 =말고 다른 거 쓰시는 건 어떤가요?
아아 그리고 궁금했던건데 문자열에 type 할당이 가능하나요? 모든 문자열은 정의될 때 type이 할당되어 있는건가요?
모든 문자열에 타입을 할당할 수 없을 수 있습니다. 한 문자열이 타입에 따라 다른 값을 가질 수 있습니다.
그리고 설명하기가 ㅈ 같은 Main( a )는 다시 설명해드리도록 하겠습니다.
그러면 이러한 문자열들은 undefined된 타입을 샂나요?
괜찮아요 저거 대강 이해한거 같아요(?) ㅋㅋ
문자열은 항의 단축표현이고 Butterfly는 타입이 있는 언어입니다. 술어 선언과 타입 정의를 통하여 항상 변수와 항의 타입을 추론할 수 있고 타입이 안 맞다면 인터프리터가 코드를 해석하는 데 실패합니다. 그리고 Butterfly에서 가능한 입출력은 질의와 응답 뿐입니다. 따라서 문자열은 String이나 Array Char 같은 타입을 가지지 않고 그냥 항의 단축표현으로서만 쓰입니다.
알겠읍니다 물론 문자열 타입도 정의하자면 정의할 수는 있겠군요
여담인데 정규표현식은 지원하실 계획이신가요?
그리고 Butterfly는 기본 자료형을 가지지 않습니다. 모든 자료형을 만들어서 써야합니다.
정규표현식을 어디에 쓰시게요? 일단은 위에 쓴 기능이 전부라서요.
말씀드린 것처럼 문자열 타입을 정의하고 싶어서요 ㅋㅋ
아니요. 대신 생성자의 정의가 형식문법의 생성규칙과 비슷하니 그걸 이용하십시오.
음 근데 항의 단축 표현으로서 문자열을 쓴다면 문자가 고갈되거나 하진 않을까요?
만약 하나의 프로그램에 두 개 이상의 타입이 있고, 동일한 문자를 축약 표현으로 공유한다면, 이 경우에는 어떻게 하나요?
좋은 질문입니다. 술어 선언과 생성자의 정의는 항상 타입을 쓰도록 하고 있죠. 그러므로 항상 타입을 추론할 수 있습니다. 그리고 같은 타입 내에서 단축표현끼리 충돌한다면 인터프리터가 Error를 띄우고 한 문자열이 타입에 따라 다른 값을 나타내는 것이 허용되기 때문에 안심하고 쓰십시오.
타입 있는 Prolog에 파싱 기능을 추가한 것이 Butterfly입니다.
http://gall.dcinside.com/mgallery/board/view/?id=github&no=1438&page=1
용어가 너무 어려워요 족같애서 못하겟어요
죄송합니다 ㅠㅠ