미스티컬
(suberic.net)- Mystical은 PostScript 프로그램을 마법진처럼 보이는 원형 구조로 그리는 표기 방식이며, 문서에서는 언어처럼 다루지만 실제로는 PostScript의 시각적 표현에 가까움
- 핵심 구조는 링(ring) 이며, 실행 배열
{}, 비실행 배열[], 딕셔너리<< >>를 테두리·별·삼각형·다각형으로 구분함 - 링 가장자리의 텍스트와 시길(sigil) 은 PostScript 연산자·변수·키워드·문자열·이름을 기호나 장식된 형태로 바꿈
mystical.ps는 배열·실행 배열·딕셔너리를 Mystical 이미지로 렌더링하고,mystify.py는 PostScript 프로그램을 8.5x11 페이지의 8인치 폭 Mystical 그림으로 감싸며 주석도 변환함- 현재 Mystical 이미지를 읽어 계산하는 인터프리터는 없고, 사람이 이미지를 PostScript로 바꿔 실행할 수 있는 수준임
PostScript를 마법진처럼 그리는 표기
- Mystical은 마법진을 닮은 프로그래밍 언어를 만들고 싶다는 목표에서 출발함
- 실제로는 마법진처럼 보이는 방식으로 PostScript를 작성하거나 그리는 방법에 가까움
- 설치와 입문 문서는 별도로 제공됨
링 기반 구조
- Mystical 프로그램은 링(ring) 으로 구성됨
- 링은 안쪽과 바깥쪽 테두리를 가진 원형 띠이며, 그 안에 텍스트와 시길이 배치됨
- 메인 링의 내용은 오른쪽 끝인 3시 방향에서 시작해 반시계 방향으로 흐름
- PostScript의 각도 체계를 따르며, 링을 바깥쪽에서 쓴다는 가정도 반영함
- 하위 링은 자신을 호출한 구조와 연결된 지점에서 시작함
-
세 가지 링 타입
- 실행 배열은 PostScript의
{ }에 해당하며, 안팎에 단순한 원형 테두리가 있고 내부에 별 모양이 들어감 - 실행 배열의 시작·끝 지점은 연금술의 “작업 완료” 기호에서 따온 심볼로 표시됨
- 비실행 배열은 PostScript의
[ ]에 해당하며, 실행 배열과 비슷하지만 별 모양이 없음 - 비실행 배열의 시작·끝 지점은 단순한 삼각형으로 표시됨
- 딕셔너리는 PostScript의
<< >>에 해당하며, 이중 바깥 테두리와 단일 안쪽 테두리를 가진 다각형으로 표시됨 - 딕셔너리의 시작·끝 지점 표시는 배열과 같음
- 딕셔너리 이미지의 항목 순서는 PostScript 텍스트와 다를 수 있음
- PostScript에서는 딕셔너리 삽입 순서가 보존되지 않기 때문임
- 실행 배열은 PostScript의
-
중첩 구조와 제약
- 한 구조가 다른 구조 안에 나타나면, 포함 지점의 작은 원 또는 점에서 선이 나와 하위 링의 시작·끝 시길로 연결됨
- PostScript에서는
[ ]나<< >>를 Mystical이 처리하기 어려운 방식으로 사용할 수 있음 - 예시처럼 배열 경계를 조건문이나 분기 안에서 나누는 형태는 피해야 함
gsave/grestore,begin/end같은 명령은 균형이 맞지 않거나 루프를 가로지르는 방식으로 쓰일 가능성이 커서 일반 시길로 취급됨
텍스트와 시길
- 링의 가장자리에는 텍스트나 시길이 놓임
- PostScript에서
/name으로 쓰는 이름은 Mystical에서 이름 텍스트 또는 시길을 감싸거나 겹치는 삼각형으로 표시됨 - PostScript의 문자열
()은 문자열 텍스트를 담은 cartouche 형태로 표현됨 -
표준 시길
- 많은 내장 연산자에는 자체 표준 시길이 있음
- 연산자나 이름으로 나타날 때는 텍스트 대신 시길을 쓰지만, 문자열 안에서는 적용되지 않음
- 표준 시길은 대체로 명령의 첫 글자와 개념의 그림을 조합해 만들었고, 일부는 더 설명적인 그림이나 표준화된 시각 언어를 사용함
- 전체 목록은 Standard Sigils에서 볼 수 있음
- 예시로 다루는 연산자 범주
dup,copy,add,mul,negfor,forall,repeatif,ifelse, 비교 연산자moveto,lineto,arc,curveto,stroke,fillgsave,grestore,translate,scale,rotate- 색상 설정·조회 연산자
dict,begin,end,def,get,put,length
-
사용자 시길
- 새 함수나 이름의 시길은 런타임에
sigil_bank에 추가할 수 있음 - 사용자 시길은 원점을 중심으로 한 1 단위 정사각형 안에 들어가야 하며, 좌표값은 0.5를 넘지 않아야 함
- 편의를 위해 좌표계를 변환할 수 있음
stroke대신nstroke를 쓰면 표준 시길과 같은 서예적 효과를 얻음- 사용자 변수용 시길은 어떤 시길 체계로도 설계할 수 있음
- 예시는 Spare의 Chaos Magick 체계에서 영감을 받은 letter collision을 주로 사용함
- kameas, wheels, Square Word Calligraphy, Circular Gallifreyan, sitelen sitelen, 그림, 말장난 등도 가능함
- 공식 연산자에서 파생된 새 이름은 해당 연산자의 표준 시길을 포함할 수 있음
- 새 함수나 이름의 시길은 런타임에
/name { ring } def용 결합 표기
def에는 별도 시길이 있지만, 이름을 푸시하고 함수를 푸시한 뒤 그 이름에 함수를 정의하는 패턴이 자주 등장함- Mystical은
/name { ring } def형태를 위한 특수 문법을 제공함- 일반 이름 삼각형을 사용함
- 연결선의 끝이 이름 바로 아래에 놓임
def시길은 완전히 생략됨
- 이 문법은 단순화를 위해 다른 두 링 타입에도 확장됨
- 다른 방식으로
def를 사용할 때는 일반def시길을 그대로 사용함 - 딕셔너리 안의
/name { ring }에도 비슷한 결합 표기를 고려했지만, 잘못 처리될 가능성이 커서 적용하지 않음
주석 처리 방식
- Mystical의 주석은 프로그램 안의 특정 지점을 가리키는 불완전한 말풍선 안의 작은 텍스트로 표시됨
- 실제 PostScript 주석은 Mystical 렌더러가 보기 전에 사라지므로,
mystify.py가 주석을 감지 가능한 코드 시퀀스로 바꿈 - 예를 들어
% Show a standard message, centered horizontally같은 주석은 다음 형태로 변환됨(Show a standard message, centered horizontally) /mystical_comment_flag pop pop
- 렌더러는 이 패턴을 감지해 Mystical 주석으로 표시할 수 있음
샘플 알고리듬
- 페이지 상단의 그림은 Quicksort 예시임
- Euclid의 GCD 알고리듬 예시도 포함됨
- 이 예시는 dmmlib의
/arg {exch def} def함수를 사용함
- 이 예시는 dmmlib의
Mystical 이미지 생성 함수
- 모든 함수는
mystical.ps에 정의되어 있음 mystical- 배열, 실행 배열, 딕셔너리를 받아 Mystical 형태로 렌더링함
- 필요한 경우 하위 구조까지 내려가며 그림
- 전체 이미지는 단위 원에 맞게 스케일됨
mystical_evokemystical과 같지만 현재 딕셔너리에서 조회할 이름을 입력으로 받음
mystical_evoke_labelmystical_evoke와 비슷하지만, 위쪽에 이름-정의 결합 표기를 추가함- 이름 시길이 똑바로 보이도록 이미지를 회전함
- 세 함수에는 모두
_unscaled가 붙은 버전이 있음- 이 버전들은 스케일링 단계를 건너뜀
- 링 두께가 1 단위라서 이미지가 상당히 커짐
- 사용법은 Mystical usage notes에 있음
Mystical 이미지 생성 프로그램
- 현재 제공되는 프로그램은 Python 스크립트
mystify.py하나임 mystify.py는 두 가지 작업을 수행함- PostScript 프로그램 전체를 Mystical 프로그램으로 그리는 코드로 감싸고, 8.5x11 페이지 중앙에 8인치 폭으로 배치함
%로 시작하는 PostScript 주석 줄을 Mystical 주석으로 변환함
- 파일 맨 앞의 주석은 변환하지 않음
- 예:
%!PS
- 예:
- 들여쓰기가 같은 인접한 주석 줄들은 줄바꿈이 포함된 하나의 긴 주석으로 처리됨
-
레이아웃 제약
- 현재 코드는 하위 원들이 충돌하지 않도록 레이아웃을 계산함
- 계산이 지나치게 안전해서 대부분의 프로그램이 매우 넓게 퍼질 수 있음
- 페이지 예시는 파싱·레이아웃 함수인
mystical_get_spell,mystical_make_evocation_ligature를 실행한 뒤 결과를 조정하고,draw_sigil,draw_link를 호출해 만들었음 - 기본 레이아웃은 개선할 계획임
언어로 볼 수 있는지
- 현재 Mystical은 PostScript 프로그램을 그리는 방법임
- Mystical 이미지를 입력받아 적절한 계산을 수행하는 인터프리터는 없음
- 사람이 Mystical 이미지를 읽고 실행할 수도 있고, 더 가능성 있게는 사람이 이를 PostScript 프로그램으로 바꾼 뒤 실행할 수 있음
다른 언어 적용 가능성
- 이 접근은 Forth처럼 연산자만 있는 언어에도 적용 가능해 보임
- 더 복잡한 문장 구조를 가진 언어에는 적용하기 어려울 수 있음
- 중괄호나 들여쓰기마다 새 링을 만들면 지나치게 복잡해질 수 있는지는 알 수 없음
다운로드
댓글과 토론
Hacker News 의견들
-
일본 애니메이션 Dennō Coil이 떠오름. 아이들이 바닥에 저자의 것과 거의 같은 방식으로 컴퓨터 프로그램을 그려 놓고, 일종의 주문처럼 발동시키는 장면이 나옴. 강력 추천함
- 그 작품을 정말 좋아했음. 아이들이 새 기술을 받아들이는 방식이 어른들과 어떻게 다른지 잘 보여줬고, Google Glass보다도 5년쯤 앞서 있었음
-
Aphyr의 블로그 연작 "Xing the technical interview"에 나오는 이세계 주인공이 선호할 법한 프로그래밍 언어 같음. 이 시리즈의 별도 글로도 충분히 어울릴 듯함
https://aphyr.com/posts/354-unifying-the-technical-interview- 실제 프로그래밍 면접에서 이걸 써보고 싶을 정도임
-
Anonymous의 "Black Perl"이 떠오름. Perl 코드를 주문처럼 읽히게 만든 고전적인 작품임
https://en.wikipedia.org/wiki/Black_Perl -
정말 놀라움. 이 작업의 라이선스가 궁금함. 현재 만드는 게임에서 주문을 시각적으로 표현할 방법이 부족했는데, Forth 비슷한 방식에 재귀만 있는 파생형으로 만들면 딱 맞을 듯함
Mystical은 사용자가 게임 안에서 구조적으로 자기 주문을 작성하면서도, 일반 프로그래밍과 같은 사고방식을 유지한 채 세계관 안의 일부처럼 느끼게 해주는 퍼즐 조각을 채워줌- Noita에도 지팡이 안에서 주문을 프로그램처럼 구성하는 비슷한 지팡이 제작 시스템이 있음. 반복, 배수 적용, 복제 같은 요소를 조합함
https://store.steampowered.com/app/881100/Noita/
- Noita에도 지팡이 안에서 주문을 프로그램처럼 구성하는 비슷한 지팡이 제작 시스템이 있음. 반복, 배수 적용, 복제 같은 요소를 조합함
-
나도 이런 걸 만들고 있었음. 내 것은 명령 순서가 중요하지 않다는 장점이 있는 논리 언어 Dusa를 기반으로 함
그래서 표현력 높고 조밀한 룬을 만들 수 있는 여지가 많지만, 자동 배치 프로그램을 만드는 일은 어려웠음. 좋든 나쁘든 Mystical만큼 읽기 쉽지는 않음
가위바위보를 실행하는 예시: https://sunny.garden/@spenc/113870784615196721 -
이 토끼굴도 마음에 들 것 같음: https://www.reddit.com/r/UFOs/comments/145teoz/isaac_and_the...
-
게임 용도로 연금술·신비주의 기호를 찾아봤는데, 기호나 알파벳 자체에 대한 자료는 많아도 이런 큰 도식을 만들 때 참고할 문법은 거의 없어서 답답했음
이건 정말 대단함. 코드를 체계적으로 표현했을 때 이렇게 미적으로 만족스러울 수 있다는 점이 깊이 와닿음 -
신문자 체계(neography) 와 인공어가 만난 느낌임. 아름다운 문자 체계를 가진 인공어를 사용하는 독특한 프로그래밍 언어를 꼭 보고 싶음
직접 만들어보려는 생각도 있었지만 결국 착수하지 못했음 -
카오스 매직과 시길 주문 입문 자료로는 이것도 있음: https://archive.org/details/the-psychonaut-field-manual
-
직접 해봤는데 예상대로 훌륭함. 보기에도 좋은 알고리즘 설계를 시도하는 일이 꽤 재미있고, 결과물도 놀랄 만큼 읽기 쉬움
다만 b나 괄호처럼 뒤집으면 헷갈릴 수 있는 기호, 예를 들어 begin/end에 해당하는 기호에는 익숙해질 시간이 필요함. 다른 사람들처럼 Lisp나 Forth에 적용하는 것도 궁금함