파룸의달.png+
파룸  마테소인 뤼미에르 공화국 라네쥬교  피네트어

빠른 것을 더 빠르게 정확한 것을 더욱 정확하게

 
— 아프엘의 1법칙 중 일부

개요

해당 문서에선 Application Processing Language를 줄여 '아프엘'이라고 부르겠다. 아프엘은 이전 뤼미에르 공화국파룸RIMAYA에서 만들어진 프로그래밍 언어이다. 참고로 대부분의 함수나 예악어는 영어이다.

아프엘 명칭

아프엘은 전체 언어 이름의 이니셜 'APL'을 뤼미에르어의 발음을 기반으로[3] 부르는 명칭이다. 참고로 뤼미에르어로 해석하면 AivPixto`Lan이다 실제론 프로그래밍 언어가 가지고있는 정식 명칭은 없고 Application Processing Language이라고 불리던걸 여러 프로그래머들이 '아프엘'이라고 줄여부르는 것이다.

장점

다른 프로그래밍 언어에 비해서 빠르고 엄청 가볍다. 프로그램의 규모가 커지더라도 빠른 처리를 보장한다. 그리고 언어가 가볍기 때문에 적은 리소스를 가지고 있는 하드웨어에선 프로그램 자체가 무겁더라도 대부분의 경우 원할한 작동이 가능하다. 이렇게 빠른 처리가 가능하고 가볍다보니 대부분의 내장 프로그램들은 아프엘로 제작된다. 이러한 것이 가능한 이유는 2진법 개념을 버리고 4진법 개념을 도입했기 때문이다.[4]

단점

4진법을 지원하는 하드웨어이어야 한다. 물론 2진수를 사용하는 하드웨어 시스템에서도 사용은 가능하지만, 무척 빠른 성능을 보장하진 않는다. 게다가 2진법 하드웨어에서 돌아가게 만들려면 개발자가 프로그램을 '유니버셜 가이드라인'에 맞게 코드를 작성해야한다.

유니버셜 가이드라인

소스코드 최상단에 아래과 같이 적어야한다. 다만, 유니버셜을 사용하게 되면, 4진법 하드웨어에서 성능 저하가 발생할 수 있고 2진법 환경에서 또한 완벽한 성능을 보장하지 못한다.

  • 아프엘 v3까지의 유니버셜 정의
BAY::TYPE > COUNT > 2 / 4 > BAY
BIT::TYPE > GET::BAY::TYPE > IF { 2 } | 32 / 64 > ELSE { 4 } | FREE > BIT
  • 아프엘 v4의 유니버셜 사용
DEFINE UNI

아프엘의 법칙

  • 제1법칙 : 아프엘을 현재의 어떠한 것보다 빠른 것을 더 빠르게 정확한 것을 더욱 정확하게 만들어줄 것이다.
  • 제2법칙 : 아프엘은 어떠한 프로그램을 만들어도 신경쓰지 않는다. 아프엘은 프로그래머를 믿는다.[5]
  • 제3법칙 : 아프엘은 혼자선 어설프고 부족하다.[6] 그래서 부모님[7] 필요하다.

매개 전달자

아프엘 v1에선 매개 전달자의 사용이 매개의 값을 열고 닫거나 매개의 값을 다른 함수로 던져줄 수 있는 기능을 가졌다. 하지만. 아프엘 v2에선 매개의 값을 다른 함수로 던져줄 수 있는 기능과 다이렉트 엑세스 그리고 형식 묻기[8]로 사용된다. 일반 변수에 값을 전달하는데에 사용할 순 있긴하다.[9]

다이렉트 엑세스

아프엘은 변수를 제작하지도 않고도 다이렉트로 메모리에 값을 저장하고 접근할 수 있다. 변수의 타입은 아프엘에서 스스로 정한다. [10] 메모리의 값을 저장하기 위해선 무조건 매개 전달자를 사용해서 저장해야한다. 메모리가 감당만 가능하다면, 무한대로 저장할 수 있다. 또한, 배열을 저장할 땐 [최소 시작][최대 종료]로 값을 지정하여 저장한 값을 가져올 수 있다. 메모리의 할당은 프로그램 실행 전 사용되는 메모리의 만큼 할당과 함께 공간이 확보 된다.[11] 이렇게 확보가 되면 일반적으로 변수를 생성하는 것보다 더욱 매끄럽고 빠르게 작동되며 가능한 경우 메모리와 프로세서의 정보 전달 과정에서 우선순위가 최상단으로 배치될 수 있다. 이 개념들이 어렵다면, 미리 만들어져있는 매우 빠른 변수라고 생각하면 편하다.

  • 올바른 예시
asked.number("값을 이 곳에 입력해주세요. : ") >> mem.sav[0]
mem.sav[1] << asked.number("값을 이 곳에 입력해주세요. : ")
  • 틀린 예시
mem.sav[0] = asked.number("값을 이 곳에 입력해주세요. : ")
mem.sav[1] >> asked.number("값을 이 곳에 입력해주세요. : ")

메모리에서 값을 가져올 땐 일반 변수에서 가져오듯이 가져오면 된다.

확장자

아프엘의 소스코드 확장자는 *.al, *.als, *.alfp이 있다. 각 확장자가 의미하는 바가 있는데
일반적으로 *.al과 *.als은 아프엘의 소스코드임을 나타내지만, *.alfp은 일반적인 텍스트의 소스코드가 아닌 암호화된 소스코드 프로젝트이다.

암호화 저장

아프엘 v3부터 암호화 저장을 지원한다.[12]

암호화 프로젝트 *.alfp에서 LAXA2 알고리즘을 사용한다. 암호화 된 프로젝트에서 지속적으로 읽기/쓰기 하는 것은 아니다.
빠른 처리를 위해서 캐쉬 저장소에 해독된 소스코드에 접근하여 읽기/쓰기 후 저장 시 다시 암호화하여 저장된다.
당연하게도 LAXA2의 특성상 소스코드 유출 방지와 같은 보안을 염두하고 제작 된 저장 방식이 아니다. LAXA2는 오직 컴퓨터의 바이러스 및 멀웨어 같은 악성 소프트웨어로부터 파일을 손상되는 것을 보호하는 것이다.

아프엘 v2

아프엘의 첫 공식 업데이트이다. 기존에 매우 시인성이 떨어졌던 매개 전달자[13]를 대폭 변경하였다. 또한, 아프엘 v2부턴 더 나은 발전을 위해 오픈소스로 변경하였다.
또한, 컴파일 성능이 이전 버전에 비하여 최대 2배 정도 향상되었다.

아프엘 v3

대부분 편의성 기능과 소스코드 관련 기능들이 추가되고 일부 디버깅이 친절해졌다.
특히나 메모리 접근에 실수에 대한 디버깅은 정말 많이 개선되었다. 이 외에는 CSM 실행 함수[14] 가 추가되었다.

아프엘 v4

디버거와 컴파일 성능이 대폭 개선되고 문법이 깔끔해졌다. 정말 말도 안되게...

컴파일 시간 비교

팩토리얼을 계산하는 프로그램을 작성 후 컴파일을 하면 아프엘의 버전별로 다음과 같은 시간 차이를 보여준다.

  • 아프엘 v1
compiling : 7.2173 sec
converting to executable : 2.1048 sec
  • 아프엘 v2
compiling : 3.4007 sec
converting to executable : 1.0079 sec
  • 아프엘 v3
compiling : 3.3996 sec
converting to executable : 1.0082 sec
  • 아프엘 v4
compiling : 0.4621 sec
converting to executable : 0.1894 sec

버전별 아프엘 디버깅 비교

아래와 같은 오류를 가진 코드를 실행하고 아프엘의 버전별로 디버깅 메세지를 비교하는 다음과 같다.
고정폭을 사용하지않으면, 틀린 부분을 표시해주는 화살표가 비정상적으로 보이니 유의하자.

# 아프엘 v1 ~ v3
if(true and false)
{
    out.steer(""Hello, World!")
}
# 아프엘 v4
if(true and false)
{
    viwe(""Hello, World!")
}


  • 아프엘 v1에서의 디버깅 메세지
# COMPILE ERROR #
[Syntax Error : 1]
 LINE => [1]
[Unknown Error : 2]
 LINE => [3]
 
:: An error occurred in that syntax::
  • 아프엘 v2에서의 디버깅 메세지
$ COMPILE ERROR $
Couldn't compile for the following reasons!

# [LINE : 1] / [ERROR : 2] #
if(true and false)
 ! => undefined variables.
 ! => conditional expression not valid.
 
# [LINE : 3] / [ERROR : 2] #
out.steer(""Hello, World!")
 ! => The function or class you are trying to use is not defined.
 ! => There are more parameters than necessary.
  • 아프엘 v3에서의 디버깅 메세지
$ COMPILE ERROR! $
Compilation could not be completed normally due to the following error!

# [LINE : 1] / [ERROR : 3] / [WARING : 1] #
if(true and false)
        ^-----^---^----- [3]
 ! => true is undefined.
 ! => and is undefined.
 ! => false is undefined.
 ? => conditional expression not valid.
 
# [LINE : 3] / [ERROR : 3] #
out.steer(""Hello, World!")
         ^--------^--------------^ [3]
 ! => The function or class named steer is not defined.
 ! => An unknown parameter was passed to the string endpoint.
 ! => String is not closed.
  • 아프엘 v4에서의 디버깅 메세지
$ COMPILE ERROR! $
Compilation could not be completed normally due to the following error!

# [LINE : 1] / [ERROR : 4] / [WARING : 1] #
if(true and false)
       ^^-----^---^----- [4]
 ! => true is undefined. Do you mean True?
 ! => and is undefined. Do you mean &?
 ! => false is undefined. Do you mean False?
 ! => conditional expression not valid.
 ? => The following code will never run!
 
# [LINE : 3] / [ERROR : 3] #
viwe(""Hello, World!")
^------------^--------------^ [3]
 ! => There is no function called viwe. Do you mean view?
 ! => A string was found at the string endpoint. Do you mean "Hello, World!"?
 ! => String is not closed. If you must use double quotes inside a string, use \".

예시

아프엘 v2

  • Hello, World! 출력
BAY::TYPE > 4 > BAY

program start(none)
{

    out.string("Hello, World!")

}


  • 변수 생성해서 두 값을 입력받아서 더하기
BAY::TYPE > 4 > BAY

program start(none)
{

    A = asked.number("첫 번째 값을 입력하세요 : ")
    B = asked.number("두 번째 값을 입력하세요 : ")
    C = A + B
    out.freetype("결과 값은 : {C}입니다.")
    
}


  • 변수 생성 없이 계산기 만들기
BAY::TYPE > 4 > BAY

program start(none)
{
    
    asked.freetype("식을 입력하시오 : ") >> format.ary("number string number") >> mem.sav[0][2]
    
    choice(mem.load[1])
    {
    
        "+" << equal {
                mem.load[0] + mem.load[2] >> mem.sav[3]
        }
        
        "-" << equal {
                mem.load[0] - mem.load[2] >> mem.sav[3]
        }
    
        "*" << equal {
                mem.load[0] * mem.load[2] >> mem.sav[3]
        }
    
        "/" << equal {
                mem.load[0] / mem.load[2] >> mem.sav[3]
        }
        
        all-else {
            "오류가 발생했습니다." >> mem.sav[3]
        }
    
    }
    
    out.freetype("결과 값은 : {mem.load[3]}입니다.")
    
}


  • 매개 전달자 극한의 사용의 예시 이런 짓은 하지말자..
BAY::TYPE > 4 > BAY

program start(none)
{

    asked.number("첫 번째 값을 입력하세요 : ") >> mem.sav[0] >> next >> asked.number("두 번째 값을 입력하세요 : ") >> mem.load[0] + value >> out.value
    
}
  • 다음과 같이 처리한 것이다.
1. 사용자에게 값 묻기
2. 물어본 값을 0번 메모리 슬롯에 저장
3. 다음 명령 실행
4. 사용자에게 값 묻기
5. 0번 메모리 슬롯 값 + 물어본 값[15]
6. 전달 된 값[16] 출력

아프엘 v4

  • Hello, World! 출력
src Main()
{
    view("Hello, World!")
}


  • 변수 생성해서 두 값을 입력받아서 더하기
src Main()
{
    A = read("첫 번째 값을 입력하세요 : ")
    B = read("두 번째 값을 입력하세요 : ")
    C = A + B
    view(`결과 값은 : {C}입니다.`)
}


  • 변수 생성 없이 계산기 만들기
src Main()
{
    
    read("식을 입력하시오 : ") >> format("n s n") >> mem.sav[0][2]
    
    choice(mem.load[1])
    {
    
        if "+" {
                mem.load[0] + mem.load[2] >> mem.sav[3]
        }
        
        if "-" {
                mem.load[0] - mem.load[2] >> mem.sav[3]
        }
    
        if "*" {
                mem.load[0] * mem.load[2] >> mem.sav[3]
        }
    
        if "/" {
                mem.load[0] / mem.load[2] >> mem.sav[3]
        }
        
        else {
            "오류가 발생했습니다." >> mem.sav[3]
        }
    
    }
    
    view(`결과 값은 : {mem.load[3]}입니다.`)
    
}


각주

  1. 2024년 11월 4일 20시 39분 37초 기준. 미디어위키 표현식의 한계에 의해서 이 값은 정확하게 나타나기 힘들다. 정확한 값을 얻기 위해서는 사트/표준#Python 구현에서 설명하는 방법을 통하는 것이 바람직하다.
  2. 디스코드 서버에는 차단된 사람이 아니라면 누구나 들어올 수 있습니다.
  3. 근데 아프엘은 사실 틀린 말이다. 각 이니셜의 발음을 따 부르는 것인데, 그렇게 따지면 아프엘이 아니라 뤼미에르어로 부르면 아프르가 맞는 명칭이다. 하지만, 부를 때 편의성을 위해 뤼미에르어콜세이로마를 그냥 적용해서 부르는 것이다.
  4. 자세한 내용은 4진법 컴퓨팅을 참고하십시오.
  5. 아프엘은 구조적으로 컴파일만 되면 뭐든지 OK!라는 마인드다..
  6. 이는 차라리 어딘가 나사빠진 메모리 관리 적용할 바에 아예 메모리 관리를 없애서 아예 어설프게 만든 것에 대한 의미다.
  7. 여기서 칭하는 부모님은 프로그래머를 말한다.
  8. 사용자에게 값을 물었을 때 어떤 형식으로 받고 싶은지 정할 수 있고 따로 값을 받을 수도 있다.
  9. 굳이?
  10. 대부분 4형식 [int, float, string, TYPE+Array] number로 표시 된 값은 정수와 실수를 자체적으로 구분하여 int float로 다시 변경한다.
  11. 사용되지 않는 메모리 중에서...
  12. 명령어 도구로 'APL { ALFP << '파일경로' } >> { RST << '파일경로' }'를 입력하면 암호화된 프로젝트가 생성된다.
    생성된 프로젝트는 APL이 내장된 컴퓨터라면 클릭하여 열 수 있다.
  13. 아프엘에선 >> 매개 << & 매개 >> 매개 >> 와 같이 사용하는 것을 매개 전달자라고 한다.
  14. CSM 실행 함수
    CSM{ CSM 코드 }
  15. 4단계로부터 전달받은 값
  16. 5단계에서 계산 된 값