아희 언어의 명세

마지막 수정: 2016-01-31

아희는 한글로 된 난해한 프로그래밍 언어입니다.

주의! 아래의 스펙은 미완성이며 뒷날에 바뀔 수 있습니다.

개요

인터프리터가 아희를 실행하는 방법은 befunge와 비슷합니다. 즉, 코드 공간 안에 커서가 있어서 커서가 위치한 곳에 적혀 있는 명령을 수행하고, 또 그 명령에 따라 커서가 움직이는 것입니다. 하지만, 그 코드가 ASCII가 아니라 한글이라는 점이 다릅니다.

한글은 홀소리와 닿소리로 나눌 수 있습니다. 홀소리는 커서가 이동할 방향을 지정하고, 닿소리는 인터프리터가 수행할 명령을 지정합니다. 받침이 있는 글자는 닿소리가 두 개가 되는데, 이 때 받침은 명령을 보조하는 인자로 작용합니다.

아희에서 쓰이는 저장 공간은 여러 개가 있습니다. 대부분이 스택이고, 큐가 하나 있습니다. 그리고 확장기능과 소통하는 통로가 있는데, 스택과 마찬가지로 씁니다. 집어넣기(push)로 인수를 전달하고 뽑아내기(pop)로 결과를 받아옵니다.

코드

  • 아희의 코드는 UTF-8로 표현된 유니코드 문자로만 이루어진 텍스트입니다.
  • 아희의 코드에는 어떤 UTF-8 문자도 올 수 있으나, 닿소리, 홀소리 실행에는 오직 유니코드 한글 낱자 영역(16진수 코드 포인트 AC00-D7A3, hangul syllable 영역)의 문자만 영향을 끼치고 영역 밖의 문자는 커서가 이동할 때 지나갈 수 있는 빈 공간처럼 취급합니다.
    • 완전하지 않은 낱자인 ㄱ, ㄷ, ㅑ, ㅓ 등은 무시합니다. 이런 기능을 사용하고 싶다면 기능이 없는 닿소리나 기능이 없는 홀소리를 조합해 쓸 수 있습니다.
    • 첫가끝 코드 등의 다른 방식으로 표현된 한글도 무시합니다.
  • 코드는 닿소리부터 실행하고 홀소리에 따라 움직입니다. 하지만 닿소리가 홀소리의 동작을 재정의할 경우에는 진행방향을 결정한 후, 실제로 이동하기는 전에 재정의가 이루어집니다.
    1. 닿소리를 먼저 실행합니다. 이때 진행방향 재정의가 있다면 재정의를 예약합니다.
    2. 홀소리에 따라 이동 방향을 결정합니다.
    3. 예약된 진행방향 재정의가 있다면 이동 방향을 변경합니다.
    4. 이동 방향에 따라 이동합니다.
  • 아희의 코드는 줄바꿈에 민감합니다. 줄바꿈 문자는 Line feed 문자인 유니코드 0A 또는 흔히 'n'로 가리키는 문자를 사용합니다. 단 그 앞에 Carriage return 문자인 유니코드 0D 또는 흔히 'r'로 가리키는 문자가 있는 경우 두 문자를 합쳐서 줄바꿈으로 다룰 것을 권고합니다.

홀소리

  • 아희는 코드를 매 유니코드 문자 하나를 격자 단위로 하는 평면으로 해석합니다.
  • 커서를 옮기는 데는 한글 문자의 홀소리에만 영향을 받습니다. 각 홀소리의 동작은 아래의 정리를 참고합니다.
  • 커서의 진행에는 관성이 있습니다. 홀소리가 아무 일도 하지 않으면 이전의 이동 방향과 크기를 유지하려는 성질이 있습니다.
  • 프로그램이 시작할 때 커서는 1행 1열에 있고 아래 방향으로 한 칸 진행하려는 상태입니다.
    • 이는 가상의 0행 1열에 '우' 문자가 있어 아래로 한 칸 이동해 온 것과 같은 상태로 해석할 수 있습니다.
    • 이는 기본 방향이 오른쪽인 funge와는 다른 점입니다. 이렇게 함으로서 코드 맨 윗줄에 #!을 추가로 넣더라도 문제없이 동작할 수 있습니다.
  • 커서가 코드 공간의 한 쪽 끝에 다다르면 커서는 반대편 끝으로 이동합니다.
    • 반대편 끝은 코드 텍스트에서 진행방향 반대편에 존재하는 첫 문자를 가리킵니다. 첫 문자는 줄바꿈 문자를 제외한 어떤 문자도 될 수 있습니다.
  • 연산에 필요한 충분한 갯수의 값이 저장공간에 저장되어 있지 않은 경우, 커서는 그 명령을 실행하지 않고 진행해야 할 방향의 반대방향으로 움직입니다.
    • 종료만 제외하고, 중복과 바꿔치기 명령을 포함한 모든 뽑아내기를 쓰는 명령에 해당합니다.

각 홀소리의 기능은 다음과 같습니다.

  • ㅏ, ㅓ, ㅗ, ㅜ - 커서를 각각 오른쪽, 왼쪽, 위, 아래로 한 칸 옮깁니다.
  • ㅑ, ㅕ, ㅛ, ㅠ - 커서를 각각 오른쪽, 왼쪽, 위, 아래로 두 칸 옮깁니다.
  • ㅡ - 커서가 가로로 왔으면 그 방향과 크기 그대로, 세로로 왔으면 전에 있던 자리로 옮기고 진행 방향도 뒤집습니다.
  • ㅣ - 커서가 세로로 왔으면 그 방향과 크기 그대로, 가로로 왔으면 전에 있던 자리로 옮기고 진행 방향도 뒤집습니다.
  • ㅢ - 커서를 전에 있던 자리로 옮기고 진행 방향도 뒤집습니다.
  • 기능 없음: ㅐ ㅔ ㅒ ㅖ ㅘ ㅙ ㅚ ㅝ ㅞ ㅟ (커서가 이동하는 방향과 크기는 변하지 않습니다.)

닿소리

각 닿소리의 기능은 다음과 같습니다.

ㅇ 묶음 - 받침은 모두 무시합니다.

  • ㅇ은 없음 명령으로 아무 일도 하지 않습니다.
  • ㅎ은 끝냄 명령으로 커서의 실행을 끝냅니다. 이 때 현재 선택된 저장 공간에 값이 하나 이상 남아 있으면 ㅁ 명령으로 뽑아낼 수 있는 값을 뽑아내 운영체제에 돌려 줍니다. 저장 공간이 비어 있으면 0을 돌려줍니다.
    • 저장 공간이 비어 있더라도 커서의 실행은 끝냅니다. 반대 방향으로 이동하지 않습니다.

ㄷ 묶음 - 셈. 받침은 모두 무시합니다.

  • ㄷ은 덧셈 명령으로 저장공간에서 두 값을 뽑아낸 다음 둘을 더한 값을 저장공간에 집어넣습니다.
  • ㄸ은 곱셈 명령으로 저장공간에서 두 값을 뽑아낸 다음 둘을 곱한 값을 저장공간에 집어넣습니다.
  • ㅌ은 뺄셈 명령으로 저장공간에서 두 값을 뽑아낸 다음 나중 값에서 먼저 값을 뺀 값을 저장공간에 집어넣습니다.
  • ㄴ은 나눗셈 명령으로 저장공간에서 두 값을 뽑아낸 다음 나중 값에서 먼저 값을 나눈 값을 저장공간에 집어넣습니다.
  • ㄹ은 나머지 명령으로 저장공간에서 두 값을 뽑아낸 다음 나중 값에서 먼저 값을 나눈 나머지를 저장공간에 집어넣습니다.
  • 뽑아내는 두 개의 값은 ㅁ 명령을 두 번 실행해 뽑아낼 수 있는 값과 같습니다.

ㅁ 묶음 - 저장공간

  • ㅁ은 뽑기 명령입니다. 지금 저장공간이 스택이라면 맨 위의 값, 큐라면 맨 앞의 값을 뽑아냅니다.(pop) 통로라면 거기서 값을 하나 뽑아옵니다.
    • ㅇ 받침이 오면 뽑아낸 값을 10진수로 출력합니다.
    • ㅎ 받침이 오면 뽑아낸 값에 해당하는 코드포인트의 유니코드 문자를 UTF-8로 출력합니다.
    • 다른 받침이 오면 뽑아낸 값을 버립니다.
  • ㅂ은 집어넣기 명령입니다. 지금 저장공간이 스택이라면 맨 위에, 큐라면 맨 뒤에 값을 집어넣습니다.(push) 통로라면 값을 하나 보냅니다.
    • ㅇ 받침이 오면 표준 입력에서 정수 문자열을 받아 이에 해당하는 값을 지금 저장공간에 집어넣습니다.
    • ㅎ 받침이 오면 표준 입력에서 UTF-8로 유니코드 문자를 받아 이에 해당하는 유니코드 코드포인트를 지금 저장공간에 집어넣습니다.
    • ㅇ이나 ㅎ이 아닌 받침에 대해서는 각각 상수를 저장공간에 집어넣습니다. 그 상수 값은 아래의 표를 참고합니다.
  • ㅃ은 중복 명령입니다. 지금 저장공간이 스택이라면 맨 위의 값을 그 값 위에 하나 더 집어넣고, 큐라면 맨 앞의 값을 앞에 하나 더 덧붙입니다. (통로라면 아까 보낸 값을 한 번 더 보냅니다.)
  • ㅍ은 바꿔치기 명령입니다. 지금 저장공간이 스택이라면 맨 위 값과 그 바로 아래 값을, 큐라면 맨 앞의 값과 그 바로 뒤 값을 바꿉니다. (통로라면?)

ㅂ의 경우 ㅇ, ㅎ 외의 나머지 받침이 있으면 그 받침을 구성하는 직선의 수와 원의 수의 합을 집어넣습니다. 받침이 없으면 0을 집어넣습니다.

2 2 3 5 4 4 2 3 4 3 4 4
4 4 5 5 7 9 9 7 9 9 8 6 4

받침 중에는 1획인 것이 없는데, 1은 2/2나 3-2 같은 셈으로 간단하게 만들 수 있습니다. 예: 반밧나, 밪반타 등.

ㅅ 묶음 - 제어, 저장공간 확장

  • ㅅ은 선택 명령으로 저장공간을 선택합니다. 어느 것을 선택하는지는 받침을 따르는데, 이에 대한 설명은 아래에 있습니다.
  • ㅆ은 이동 명령으로 저장공간에서 값 하나를 뽑아내 받침이 나타내는 저장공간에 그 값을 집어 넣습니다.
  • ㅈ은 비교 명령으로 저장공간에서 값 두 개를 뽑아 내서 비교합니다. 나중에 뽑아낸 값이 더 크거나 같으면 1을, 아니면 0을 지금 저장공간에 집어넣습니다.
  • ㅊ은 조건 명령으로 저장공간에서 값 하나를 뽑아내서 그 값이 0이 아니면 진행해야 할 방향대로, 0이면 그 반대 방향대로 갑니다.

저장공간

  • 아희에는 총 28개의 저장공간이 있습니다.
  • 저장공간은 스택, 큐, 통로 세 가지 종류가 있습니다.
  • 스택이 26개, 큐가 1개, 통로가 1개이며 각각의 저장공간에는 이름이 붙어 있습니다. 그 중 스택은 (받침 없음), ㄱ, ㄴ, ㄷ, ㄹ, ㅁ, ㅂ, ㅅ, ㅈ, ㅊ, ㅋ, ㅌ, ㅍ, ㄲ, ㄳ, ㄵ, ㄶ, ㄺ, ㄻ, ㄼ, ㄽ, ㄾ, ㄿ, ㅀ, ㅄ, ㅆ이 있습니다. ㅇ은 큐이며, ㅎ은 확장 기능과 소통하기 위한 통로입니다.
  • 각 저장공간은 ㅅ나 ㅆ 명령에서 받침으로 선택할 수 있습니다.
  • 처음에 선택되어 있는 저장공간은 (받침 없음) 스택입니다.
    • "사" 와 같은 명령으로 선택할 수 있습니다.
  • 저장공간은 최소한 32비트의 부호 있는 정수를 지원할 것을 권고합니다.

예제

다음은 "Hello, world!"를 출력하는 프로그램입니다.

밤밣따빠밣밟따뿌
빠맣파빨받밤뚜뭏
돋밬탕빠맣붏두붇
볻뫃박발뚷투뭏붖
뫃도뫃희멓뭏뭏붘
뫃봌토범더벌뿌뚜
뽑뽀멓멓더벓뻐뚠
뽀덩벐멓뻐덕더벅