아희희

이 문서는 아희의 확장 버전 초안을 기술하고 있습니다. 여기 있는 어떤 내용도 실제로 구현된 바는 없습니다.

명령들

아희희의 모든 명령들은 그 모양에 따라 크게 일곱 종류로 나뉜다.

무시
  • + 아무 받침: 아무 일도 하지 않음.
움직임
  • + 오류 받침: 가기 또는 돌아가기. (새롬)
  • : (미정)
  • : (미정)
계산
  • + 받침 없음1: 더하기.
  • + 받침 없음: 빼기.
  • + 받침 없음: 곱하기.
  • + 오류 받침: 나누기. (바뀜)
  • + 오류 받침: 나머지. (바뀜)
한공간
  • + /가 아닌 받침: 넣기.
  • + 받침: 숫자 입력.
  • + 받침: 문자 입력.
  • + 받침 없음: 되넣기.
  • + 받침 없음: 뒤집기.
  • + /가 아닌 받침: 빼기.
  • + 받침: 숫자 출력.
  • + 받침: 문자 출력.
여러공간
  • + 아무 받침: 선택.
  • + 아무 받침: 옮기기.
비교
  • + 받침 없음: 크거나 같으면 1.
  • : (미정)
  • + 받침 없음: 0이면 반대 방향으로.
종료
  • + 받침 없음: 끝내기.

“가기” 명령

명령에 있는 모음에 따라 방향을 변경했다고 가정하고(실제로는 바꾸지 않는다), 이 명령 다음으로 실행될 위치를 찾아서 그 위치의 문자를 마커(marker)로 해석한다. 다음으로 실행될 위치는 항상 (현재 위치 + 바뀔 방향)으로 계산된다.

가힣            여기서의 마커는 "힣"이다.

갸노풉츙        "갸" 다음에 원래 실행되어야 할 명령은 "풉"이므로 이 글자가 마커가 된다.

아아아파기      "기" 다음에 "파"가 실행되어야 하므로 이것이 마커가 된다.

가杏            다음 글자가 꼭 한글이어야 할 필요는 없다. 아무튼 공백만 아니면 된다.

가 뚱          다음 글자가 공백일 경우 (이는 코드 한쪽 끝에 명령이 걸칠 때도 포함)
                이 코드는 특수한 의미를 가지게 된다. 아래를 참고.

갸 뚱          이 코드의 경우 "갸" 다음으로 실행될 명령이 공백이 아니라 "뚱"이므로
                본래의 의미대로 동작한다. 하지만 뒤에 설명할 이유로, 이 코드는 의도한
                대로 동작하지 않는다.

만약 이 명령이 가기 명령인 것이 확실하면, 명령에 있는 모음에 따라 방향을 변경한다. (대부분의 아희 명령은 명령 실행 이후에 방향을 변경한다. 이 명령은 예외이다.)

시작하기 전에, 마커 다음으로 실행되어야 할 위치와 본래 방향이 스택에 저장된다. (즉, 명령 다음 다음으로 실행되었어야 할 위치가 저장된다.)

그 뒤 코드 안에서 주어진 마커를 검색하여 그 마커가 있는 위치로 이동한다. 다만, 마커 상하좌우에 한글 음절(명령으로 인식되는)이 없어야 한다. (코드 한쪽 끝 너머는 공백으로 가득차 있는 것으로 생각한다.)

해당 위치를 기준으로 방향 변경 없이 다음에 실행되어야 할 명령부터 실행이 재개된다. (마커와 같은 문자는 따라서 명령으로 인식되지 않는다.)

가ㅁ*아아아    기본적인 사용 방법. "가ㅁ"는 "ㅁ"이 있는 위치로 커서를 이동시킨다.
 *****    코드에 "ㅁ"가 두 개 있고, 그 중 하나는 왼쪽에 "가"가 있으므로 무시된다.
ㅁ*아아아아    두번째 "ㅁ"는 왼쪽과 아래가 코드 끝, 오른쪽이 "*", 윗쪽이 전각 공백이므로
                조건을 만족, "ㅁ" 다음 명령인 "*"부터 실행을 재개한다.

갸 ㅁ 아희    마커와 명령이 인접해 있진 않은데 마커 위치에 공백이 없을 경우(...),
                실행은 그대로 진행되지만(즉 실행되는 명령 순서는 "갸", "아", "희" 순)
                스택에는 ㅁ의 위치가 저장된다는 점이 다르다. 이를 응용하면 while 문과
                같은 기능을 좀 더 짧게 구현할 수 있다.

  아우        어느 방향에서 들어 와도 문제가 없게 하려면 좀 삽을 파야 한다.
아  아우      조금 더 고생하면 가능한 방향 8종류(상하좌우, 한칸/두칸)에 따라
오 ㅁ 아아    완전히 다른 역할을 하도록 만들 수도 있다.
   오
  아오

이동 가능한 마커가 여러 개 있을 경우 여러 후보 중 랜덤하게 선택한다. 이는 Befunge의 “?” 명령을 대신하는 데 쓸 수 있다.

가!            1, 2, 3 중 아무 거나 랜덤하게 출력하는 프로그램.
  ! 붇
 ! 밤반타망희
  ! 볼

이동 가능한 마커가 “없을” 경우 오류로 처리한다. 여기에 대해서는 아래를 참고하라.

의사 코드:

“돌아가기” 명령

만약 명령 다음에 나와야 할 마커 위치에 공백이 있을 경우, 공백을 찾아서 이동하는 대신 스택에 저장되었던 다음 명령이 실행될 위치로 이동하고 방향을 원래대로 되돌린다.

명령 실행 후에 방향 변경이 진행된다. 즉, 명령에 지정된 모음이 만약 올바른 방향을 나타낸다면 다음으로 실행될 명령은 (마커가 있던 위치 + 새로이 바뀐 방향)에 있는 문자가 된다. (가기 명령이 스택에 저장하는 위치는 마커가 있던 위치이기 때문임.)

가ㅁ구 가ㅁ희  전형적인 사용 방법. ㅁ에 있는 코드는 별표(ASCII로 6x7=42)를 출력한다.
  ㅁ ㅁ      마지막 명령의 모음이 "ㅙ", 즉 방향을 변경시키지 않으므로
  가ㅁ고      ㅁ에 있는 코드가 실행된 뒤에 돌아 와서도 마지막에 ㄱ 명령과 함께
                변경되었던 방향은 그대로 유지된다.
ㅁ 밝밣따맣괘

가ㅁ ㅁ 밝붏  ㅁ에 있는 코드는 동일하지만, 마지막 명령의 모음이 "ㅜ"로 바뀌었다.
 희  구멓떠  마커가 있는 위치에서 모음이 적용되어 그 아래 명령부터 실행이 재개된다.

아야ㅁ기        간단한 무한 루프. 일단 처음에 "기"가 가기 명령이므로 방향을 반전시킨 뒤
기 ㅁ          첫 줄의 ㅁ를 마커로 삼고, 마커 위치인 둘째 줄로 이동한 뒤에 반전된 방향
                그대로 진행해서 돌아가기 명령인 "기"에 다다른다. 이제 마커의 위치로 이동하고
                원래 방향(이긴 한데 이 경우 이전과 같음)을 되돌린 뒤에 *다시* 반전을 수행,
                다음 실행되는 명령은 첫째 줄의 "기"가 된다. 그 다음은 무한 반복.

스택이 비어 있을 때는 오류로 처리된다. 여기에 대해서는 아래를 참고하라.

의사 코드: (가기 명령에서 이어짐)

“나누기”와 “나머지” 명령

기존 나누기 및 나머지 명령과 동일하나, 나눔수가 0일 때의 처리가 다르다.

이들 명령을 만나면, 우선 현재 공간(storage)에서 위에서 두번째 숫자를 빼지 않고 확인한다. (만약 공간에 두 개보다 적은 숫자가 있다면, 두번째 숫자는 0으로 가정한다.) 이 숫자가 0일 경우 스택을 건드리지 않고 바로 후술할 오류 핸들러로 이동한다. 사용할 오류 핸들러는 받침에 따라 결정된다.

현재 공간에 나눠지는 수와 나눔수를 남겨 두는 이유는 오류 핸들러가 그 숫자를 보고 적절한 처리를 할 수 있게 하기 위함이다. 다른 경우에는 정상적으로 두 숫자가 뽑히고 나눗셈 또는 나머지 연산이 실행된다.

다른 명령들

는 멀티쓰레딩을 위하여 사용할 예정이다. (forking + synchronization primitive) 이 컨텍스트에서는 은 프로그램을 바로 중단하는 것이 아니라 쓰레드 하나를 중단하게 된다.

는 어떤 용도로도 사용이 예정되어 있지 않으나, 이동에 관련된 명령이 될 가능성이 크다.

는 어떤 용도로도 사용이 예정되어 있지 않으나, 비교에 관련된 명령이 될 가능성이 크다. (min/max?)

여러 공간 명령들의 받침 에 대한 정의 역시 현재는 되어 있지 않다.

오류 처리

기존 아희의 명령들 중 나눗셈(ㄴ) 명령 및 나머지(ㄹ) 명령은 0으로 나눴을 때의 처리가 엄밀히 정의되어 있지 않았다. 이 때문에 인터프리터마다 0으로 나눌 때의 처리가 서로 다르다. (파이썬 버전은 0을 푸시, 자바스크립트 버전은 NaN, esotope는 예외, 등등등)

새로이 추가된 오류 처리 기능은 가기 명령을 통해 이루어지며, 오류 핸들러의 형태로 사용된다. 사용할 에러 핸들러는 오류를 낼 수 있는 명령의 받침을 바꿔서 결정한다. 에러 핸들러는 “해”, “핵”, “핶”, …, “햏”까지 28가지 존재한다. 여기에는 여러 이유가 있는데,

TODO 생각해 보니 “해”는 한 글자로 나오기는 쉽겠다. 다른 글자가 없을까? 아니면 ㅉ를 reserved letter로 하고 그걸 오류 처리 용으로 쓰든지..

가기/돌아가기 명령을 제외한 모든 다른 명령들은, 오류가 발생했을 때 명령이 있던 위치와 (현재 명령의 모음이 이미 적용된) 현재 방향을 스택에 집어 넣고 오류 핸들러로 이동한다. 오류 핸들러에서 돌아가기 명령을 쓰면 오류가 났던 명령 다음에 실행될 명령, 즉 모음 때문에 방향이 변경되지 않았다면 그냥 원래 위치로 돌아가서 코드를 재시작하게 된다.

명령에 따라 오류 핸들러가 불릴 적의 스택 상태는 다르며, 각 명령에 자세히 서술되어 있다. 0으로 나누기 오류의 경우 명령이 실행되기 전의 스택 상태로 복귀된다.

다음은 이런 방법을 사용해서 0으로 나눴을 때 42가 나오도록 하는 코드이다.

반바낳망희

햏 마무      -- 스택에서 나눔수와 나눠질 수를 제거한다
   밝밣뚜  -- 42를 스택에 넣는다
     개  -- 방향 변화 없이 오류 핸들러에서 나간다

  1. 받침이 있는 경우에도 동일하게 작동하나, 이는 어디까지나 하위 호환성을 위해 유지하는 것이지 의도된 동작은 아님을 나타냄.


ikiwiki를 씁니다.
마지막 수정