2008년 01월 27일
새로운 언어 디자인에 도전(..?) : Code Name - Sapphire (ver 0.001)
요즘에는 짬이 날때마다 기분전환 삼아서 새로운 스크립트 언어를 디자인해 보곤 합니다. 그러면서 특히 많이 참고를 하고 있는게 Lua 스크립트인데, 이 Lua를 좀 더 심플하게 다듬어 본다면 어떨까 싶었죠. 그런데 어제는 오랜만에 무척 좋은 아이디어가 떠올랐습니다. (라고 생각했습니다...)
그건 바로 "튜플(tuple) 구조만 가지고도 프로그래밍이 가능하지 않을까?" 였습니다.
여기서의 '튜플'이라 (1 2 3) 처럼 여러개의 값을 하나로 묶어놓은 구조라고 보면 되겠습니다. 이건 뭐 그냥 떠오르는 대로 이름을 붙인거라서요... 어쨌든 이 표현식 하나만 가지고 프로그래밍을 할 수 있는 언어를 디자인 해보려고 밤을 새서 궁리를 해봤습니다(...) 그리고 한발 더 나아가서 객체지향 비슷한 표현까지 구현려고 했습니다만... 이제와서 새삼 깨달은 거지만, 함수형 언어와 객체 지향의 표현을 같이 섞는다는게 여러가지로 충돌하는 점이 많더군요. 그나마 Lua의 테이블 구조에서 약간의 힌트를 얻었지만, 생각했던 만큼 깔끔한 표현이 나오지 않아서 답답했습니다.
여튼... 밤새 고민한 결과 최종적으로 그럭저럭 만족스런 표현식을 만들 수 있었습니다.
튜플 선언
───────
이름 붙이기
───────
함수 선언
───────
함수는 약간의 변형된 형식의 튜플로 선언합니다.
함수 실행
───────
함수를 수행하는 식 역시 튜플로 표현합니다.
prefix 표기법을 사용합니다.
연산자 실행
───────
연산자도 함수와 똑같이 취급됩니다.
결론적으로...
기본적인 실행 단위는 튜플(tuple)이며, 이 튜플의 첫번째 원소가 함수(function)일 경우는 함수를 수행하는 식으로 판단합니다. 함수가 아닐 경우는 값으로 구성된 튜플로 판단합니다.
이 하나의 원리만 가지고도, 기본적인 함수형 프로그래밍이 가능합니다.
축약 문법
───────
그런데 튜플로 구성된 식을 적다보면 필연적으로 괄호가 많이 나오게 됩니다. 그래서 해석에 크게 지장이 없는 범위에서 ( )를 제거할 수 있게 해봤습니다.
기본적으로 가장 바깥에 있는 ( )는 생략할 수 있다고 보면 되겠습니다.
.
.
.
그런데 여기까지 만들어 놓고 보니까, 이게 어디서 많이 보던 표현이라는 겁니다(...)
그 이유는 간단했습니다...
"실컷 만들었더니... LISP랑 거의 똑같잖아 !!!"
몇가지 예외적인 문법을 제외하고, 저 위의 튜플(tuple)을 리스트(list)로 말을 바꾸기만 하면 거의 LISP랑 다를게 없었습니다(...)
LISP의 간단한 형태인 Scheme의 표현식을 한번 적어보겠습니다.
정말 이거야 말로... 리스트라는 하나의 표현체계로 모든걸 다 처리해 버리는 엄청난 녀석이었습니다(...)
새로운 언어를 디자인하려다가 엉뚱하게도 그 암호같은 LISP 문장을 이해할 수 있게 되버린...

그래서...이왕 이렇게 되거...
그냥 LISP를 기본으로 삼고 이걸 변형시켜 볼까 합니다.
그럼 남은 과제는 유사 객체지향 표현을 만드는 거였습니다.
이걸 위해서 저는 튜플의 변형인 집합(set) 구조를 고안해 봤습니다.
집합 선언
───────
집합 안에 함수 선언
────────────
집합의 원소 꺼내기
────────────
이 집합구조를 이용해서, 클래스(class)를 흉내내 보겠습니다.
클래스 만들기
────────────
객체 생성
────────────
사실 여기서 클래스라는 것은 존재하지 않습니다. 그냥 집합 자체가 클래스이자 객체의 역할을 수행합니다. 객체는 클래스 역할을 하는 집합을 복사(clone)해서 생성해 내면 됩니다.
상속
────────────
상속도 별것 없습니다. 기존의 집합에 새로운 집합을 합성 시키면 됩니다.
현재는 여기까지 디자인 되어 있습니다만... 아직도 보완해야 될 점은 많아 보이는 군요.
그건 바로 "튜플(tuple) 구조만 가지고도 프로그래밍이 가능하지 않을까?" 였습니다.
여기서의 '튜플'이라 (1 2 3) 처럼 여러개의 값을 하나로 묶어놓은 구조라고 보면 되겠습니다. 이건 뭐 그냥 떠오르는 대로 이름을 붙인거라서요... 어쨌든 이 표현식 하나만 가지고 프로그래밍을 할 수 있는 언어를 디자인 해보려고 밤을 새서 궁리를 해봤습니다(...) 그리고 한발 더 나아가서 객체지향 비슷한 표현까지 구현려고 했습니다만... 이제와서 새삼 깨달은 거지만, 함수형 언어와 객체 지향의 표현을 같이 섞는다는게 여러가지로 충돌하는 점이 많더군요. 그나마 Lua의 테이블 구조에서 약간의 힌트를 얻었지만, 생각했던 만큼 깔끔한 표현이 나오지 않아서 답답했습니다.
여튼... 밤새 고민한 결과 최종적으로 그럭저럭 만족스런 표현식을 만들 수 있었습니다.
튜플 선언
───────
(a b c) --> a,b,c 3개의 값을 가지는 튜플
이름 붙이기
───────
point = (x y) --> x와 y의 값을 가지는 튜플을 point 라는 이름으로 정의한다
(a b) = (1 2) --> = 의 왼쪽식이 튜플일 경우에: a = 1, b = 2
(a b) = (b a) --> a = b, b = a 즉, a와 b의 swap
함수 선언
───────
함수는 약간의 변형된 형식의 튜플로 선언합니다.
( x | (+ x 1)) --> x를 인자로 받고 (x + 1)의 결과를 돌려주는 익명 함수
inc = (x | (+ x 1) ) --> 함수에 이름 붙이기
함수 실행
───────
함수를 수행하는 식 역시 튜플로 표현합니다.
prefix 표기법을 사용합니다.
(inc x) --> inc 함수에 x를 인자로 넘겨서 실행
f = (a b c | (* (+ a b) c)) --> f(a,b,c) = a + b * c
(f 1 2 3) --> f(1,2,3)을 실행
연산자 실행
───────
연산자도 함수와 똑같이 취급됩니다.
(+ a b) --> a + b
(- a b) --> a - b
(* a b) --> a * b
(/ a b) --> a / b
결론적으로...
기본적인 실행 단위는 튜플(tuple)이며, 이 튜플의 첫번째 원소가 함수(function)일 경우는 함수를 수행하는 식으로 판단합니다. 함수가 아닐 경우는 값으로 구성된 튜플로 판단합니다.
이 하나의 원리만 가지고도, 기본적인 함수형 프로그래밍이 가능합니다.
축약 문법
───────
그런데 튜플로 구성된 식을 적다보면 필연적으로 괄호가 많이 나오게 됩니다. 그래서 해석에 크게 지장이 없는 범위에서 ( )를 제거할 수 있게 해봤습니다.
inc = x | + x 1 --> (inc = (x | (+ x 1))) 와 동일
a b = 1 2 --> ((a b) = (1 2))와 동일
기본적으로 가장 바깥에 있는 ( )는 생략할 수 있다고 보면 되겠습니다.
.
.
.
그런데 여기까지 만들어 놓고 보니까, 이게 어디서 많이 보던 표현이라는 겁니다(...)
그 이유는 간단했습니다...
"실컷 만들었더니... LISP랑 거의 똑같잖아 !!!"
몇가지 예외적인 문법을 제외하고, 저 위의 튜플(tuple)을 리스트(list)로 말을 바꾸기만 하면 거의 LISP랑 다를게 없었습니다(...)
LISP의 간단한 형태인 Scheme의 표현식을 한번 적어보겠습니다.
(list 1 2 3) --> (1 2 3)
'(1 2 3) --> (1 2 3)
(+ 1 2 3) --> 1 + 2 + 3
(apply + '(1 2 3)) --> (+ 1 2 3) --> 1 + 2 + 3
(define (area-of-disk r) (* 3.14 (* r r))) --> 함수 선언: area-of-disk(r) = r * r * 3.14
정말 이거야 말로... 리스트라는 하나의 표현체계로 모든걸 다 처리해 버리는 엄청난 녀석이었습니다(...)
새로운 언어를 디자인하려다가 엉뚱하게도 그 암호같은 LISP 문장을 이해할 수 있게 되버린...

"절망했다..."
그래서...이왕 이렇게 되거...
그냥 LISP를 기본으로 삼고 이걸 변형시켜 볼까 합니다.
그럼 남은 과제는 유사 객체지향 표현을 만드는 거였습니다.
이걸 위해서 저는 튜플의 변형인 집합(set) 구조를 고안해 봤습니다.
집합 선언
───────
{a b c} --> a,b, c 3개의 중복되지 않은 원소가 들어있는 집합
set = {a b c}
집합 안에 함수 선언
────────────
set = { (f = (x | + x 1)) (g = (y | * y y)) }
-- 조금 보기 좋게 다듬으면...
set = {
f = x | + x 1
g = y | * y y
}
집합의 원소 꺼내기
────────────
set = {1 2 3 (sum = + 1 2 3)}
(# set 1) --> set에 1 이라는 원소가 있으면 1을 반환, 없으면 nil을 반환
#set 1 --> 축약 문법으로 약간 보기좋게(?)
#set sum --> 집합에 있는 함수를 꺼내온다
n = 1
#set (n) --> #set 1 과 동일한 효과
이 집합구조를 이용해서, 클래스(class)를 흉내내 보겠습니다.
클래스 만들기
────────────
stack = {
data = ()
push = value | : data value --> :는 튜플 결합 연산자 --> ex) (: (1 2) 3) => (1 2 3)
top = last data --> last 함수는 튜플의 마지막 원소를 반환
}
#stack push 10
#stack top --> 10
객체 생성
────────────
사실 여기서 클래스라는 것은 존재하지 않습니다. 그냥 집합 자체가 클래스이자 객체의 역할을 수행합니다. 객체는 클래스 역할을 하는 집합을 복사(clone)해서 생성해 내면 됩니다.
class = {
data = 0
inc = (data = + data 1)
}
object = (clone class)
-- 혹은
object = : class {} --> class 집합과 비어있는 집합을 합성한 새로운 집합 생성
상속
────────────
상속도 별것 없습니다. 기존의 집합에 새로운 집합을 합성 시키면 됩니다.
inherited = : class {
dec = inc -1
}
현재는 여기까지 디자인 되어 있습니다만... 아직도 보완해야 될 점은 많아 보이는 군요.
# by | 2008/01/27 10:01 | 日記 | 트랙백 | 덧글(6)




☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
아 그러고 보니 인터넷을 돌아다니다 보니 이런걸 딱 발견했더라는...
http://j2k.naver.com/j2k.php/korean/lyrical.bugyo.tk
......마법 언어 리리컬☆Lisp .......