[UPL] Conditional Branch
expression은 값으로 계산되는 코드조각이고, statement는 프로그램의 메모리를 변환시키는 코드조각이다.

expression을 계산할 때는 Store에서 Expression을 받아 계산한 Value를 돌려주고,
statement를 계산할 때는 Store를 받아 Statement를 실행하면 새로 업데이트한 Store를 돌려준다.
삼항연산자는 조건분기문의 expression 버전으로, 값으로 계산된다.

Concrete Syntax를 정의해보자.
기존 언어에서 if - then - else 을 추가하고, 크기 비교 연산자와 논리값을 추가하자.
Functional Language처럼 분기를 조작할 때는 expression을 사용한다.
if - then - else 구문을 사용할 때 어디까지가 else에 속한 expression인지 확실하게 결정하지 못 하는 상황이 발생할 수 있는데.. 우선은 if - then - else 구문은 다른 expression과 비교했을 때 우선순위가 낮다고 가정하자.
즉, else 이후에 오는 expression이 더 먼저 계산된다.

Concrete Syntax를 확장했으니 Abstract Syntax도 확장해보자.
b는 true / false를 나타내는 boolean 리터럴
e?e : e 에서 각각 expression은 condition expression / true branch expression / false branch expression (삼항연산자)
e < e 는 대소비교를 수행하는 구문



항상 그렇듯.. 새로 추가한 표현식은 위와 같은 트리를 의미한다.
FVAE를 정의할 때, 정수만 가질 수 있었던 Value에 Closure를 추가해 함수도 값으로 취급될 수 있도록 설정했다.
Conditional Branch 를 추가하기 위해 true / false 같은 Bool 도메인도 Value에 추가해주자.


이제 Semantics를 작성해야 하는데.. 기존 언어에서 b 리터럴만 추가해주자.
추가로, e1 + e2 부분에서 e1을 계산한 결과가 정수 대신 함수나 bool 값이 나온 경우 undefined behavior로 처리해주자.
삼항연산자에 대한 Semantics는 두 가지로 나눠서 기술해 줘야 한다.
e1의 계산 결과가 true / false에 따라 두 가지로 나눠서 정의해주자.
당연히.. e1을 계산한 결과가 정수나 함수인 경우 undefined behavior로 Runtime Error를 뱉어주자.


Formal Semantics를 정의할 때도 두 가지로 나눠서 정의해줘야 한다.
이렇게 여러 개의 규칙으로 하나의 Semantics를 정의하는것도 괜찮지만, 여러 규칙들이 서로 동시에 만족되는 경우가 없어야 한다.
언어를 확장하다 보니 Value 도메인이 너무 복잡해지는데.. Syntatic Sugar로 이 부분을 간단하게 처리할 수는 없을까?
true와 false를 closure로 처리하면 편할 것 같은데.


1. C언어처럼, 새로 추가된 bool 도메인의 값인 true와 false를 정수로 표현 - true를 파싱하면 1을 반환하는 Abstract Syntax로 변환
2. true와 false를 closure로 표현 - true를 파싱하면 인자 두 개를 받아 첫 번째 인자를 돌려주는 Abstract Syntax로 변환
2번 방법을 Church boolean이라고 부른다.



1번 방식을 사용할 때 Abstract Syntax와 Semantics가 어떻게 변하는지 확인해보자.
일단 Abstract Syntax에서는 bool 도메인이 없어지고, bool 도메인을 사용하는 연산들을 다시 정의해줘야 한다.
여기서는 1을 true로, 0을 false로 간주하고 작업하니 true를 판단할 때 1만 사용할 수 있었는데, 저 부분의 Semantics를 1 대신 <> 0 연산으로 수정하면 C언어처럼 true를 판단할 때 0이 아닌 모든 정수를 사용할 수 있다.


2번 방식은 lambda calculus를 사용해 bool 데이터를 Church Encoding하는 방식이다.
true는 파라미터를 두 개 받고 첫 번째 파라미터를 돌려주는 함수로 Desugaring,
false는 두 번째 파라미터를 돌려주는 함수로 Desugaring,
e1?e2 : e3는 e1 e2 e3 Function Application으로 Desugaring하자.
원래 저 삼항연산자 식에서는 e1을 계산한 결과가 true이면 e2 계산결과가 전체 식의 계산결과가 되고, false면 e3 계산결과가 전체 식의 계산결과가 된다.
e1의 계산 결과가 true이면 파라미터 두 개를 받아서 첫 번째 파라미터를 돌려주는 함수로 처리되니 e2 계산결과와 e3계산결과를 받아 e2계산결과를 돌려주게 되니 Desugaring한 식에서도 같은 방식으로 동작한다. (false도 마찬가지)
Abstract Syntax에서는 b 도메인과 Syntatic Sugar로 Desugaring되는 삼항연산자 표현식이 삭제된다.
Semantics를 살펴보면.. n1이 n2보다 작으면 true를 나타내는 closure를 돌려주고, 그렇지 않으면 false를 나타내는 closure를 돌려준다.
그냥 모든 데이터와 데이터간의 연산을 lambda abstractino과 function application으로 표현해 bool 값을 다룬다.
인자 여러개면 너무 헷갈리니까..
((λx. (λy. x)) a) b
a 적용 -> λy a 가 나옴 -> 여기에 b 적용 -> a 나옴
람다 정의는 우측 결합 우선이고, 함수 적용은 좌측 결합 우선이다.
Church Boolean은 그냥 값 대신 클로저로 bool을 정의하는거임
이 클로저는 애초에 선택자 함수로 정의됐으니까 이게 되는거. 처음에는 이게왜됨? 했는데 그냥 이해하고 받아들임
λx.λy. x 를
자바스크립트 람다식으로 표현하면..
const TRUE = x => y => x;
const FALSE = x => y => y;
이거랑 같은 표현식이다.
const TRUE = (x, y) => x;
const FALSE = (x, y) => y;
이거랑은 좀 다름
"첫 번째 인자 x를 받아서, 두 번째 인자 y를 받고 x를 리턴하는 함수"로 보는게 합리적임.
x를 받아서 함수를 리턴하는데.. 이 함수는 y를 받고 x를 리턴하는 함수.
'Computer Science > Universial Programming Language' 카테고리의 다른 글
| [UPL] MiniC 구현 (0) | 2025.05.26 |
|---|---|
| [UPL] Recursion (0) | 2025.05.18 |
| [UPL] 고차원 함수와 일차원 함수 (2) | 2025.04.18 |
| [UPL] Arithmetic Expression 정의 (1) | 2025.04.08 |
| [UPL] Syntax & Parsing (0) | 2025.04.04 |
댓글
이 글 공유하기
다른 글
-
[UPL] MiniC 구현
[UPL] MiniC 구현
2025.05.26 -
[UPL] Recursion
[UPL] Recursion
2025.05.18 -
[UPL] 고차원 함수와 일차원 함수
[UPL] 고차원 함수와 일차원 함수
2025.04.18 -
[UPL] Arithmetic Expression 정의
[UPL] Arithmetic Expression 정의
2025.04.08