Application Processing Language: 두 판 사이의 차이

 
(같은 사용자의 중간 판 24개는 보이지 않습니다)
8번째 줄: 8번째 줄:


== 아프엘 명칭 ==
== 아프엘 명칭 ==
아프엘은 전체 언어 이름의 이니셜 'APL'을 [[뤼미에르어]]의 발음을 기반으로 부르는 명칭이다. 참고로 뤼미에르어로 해석하면 AivPixto`Lan이다 실제론 프로그래밍 언어가 가지고있는 정식 명칭은 없고 [[Application Processing Language]]이라고 불리던걸 여러 프로그래머들이 '아프엘'이라고 줄여부르는 것이다.
아프엘은 전체 언어 이름의 이니셜 'APL'을 [[뤼미에르어]]의 발음을 기반으로<ref>근데 아프엘은 사실 틀린 말이다. 각 이니셜의 발음을 따 부르는 것인데, 그렇게 따지면 아프엘이 아니라 [[뤼미에르어]]로 부르면 아프르가 맞는 명칭이다. 하지만, 부를 때 편의성을 위해 [[뤼미에르어]]의 [[콜세이로마]]를 그냥 적용해서 부르는 것이다.</ref> 부르는 명칭이다. 참고로 뤼미에르어로 해석하면 AivPixto`Lan이다 실제론 프로그래밍 언어가 가지고있는 정식 명칭은 없고 [[Application Processing Language]]이라고 불리던걸 여러 프로그래머들이 '아프엘'이라고 줄여부르는 것이다.


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


== 단점 ==
== 단점 ==
4진법을 지원하는 하드웨어이어야 한다. 물론 2진수를 사용하는 하드웨어 시스템에서도 사용은 가능하지만, 무척 빠른 성능을 보장하진 않는다. 게다가 2진법 하드웨어에서 돌아가게 만들려면 개발자가 프로그램을 '유니버셜 가이드라인'에 맞게 코드를 작성해야한다.. 또한, 언어도 되게 어려운데 디버거까지 되게 불친절하다. 진짜 그냥 버그가 있다면, 알려주는 정보라곤 버그가 난 라인만 알려준다. 사실 이 경우는 아프엘의 구조적 문제이기도하다.. 또한, 아프엘은 시스템 내에서 알아서 처리하는 것이 극히 적다. 메모리 관리 등 여러 요소들은 개발자가 알아서 해야한다.
4진법을 지원하는 하드웨어이어야 한다. 물론 2진수를 사용하는 하드웨어 시스템에서도 사용은 가능하지만, 무척 빠른 성능을 보장하진 않는다. 게다가 2진법 하드웨어에서 돌아가게 만들려면 개발자가 프로그램을 '유니버셜 가이드라인'에 맞게 코드를 작성해야한다.


=== 유니버셜 가이드라인 ===
=== 유니버셜 가이드라인 ===
전처리기에 다음과 같이 적어야한다. 다만, 이로인해 일반 4진법 하드웨어에서의 약간 성능 저하가 발생할 수 있으며 2진법 환경에서 완벽한 성능을 보장하지 못한다.
소스코드 최상단에 아래과 같이 적어야한다. 다만, 유니버셜을 사용하게 되면, 4진법 하드웨어에서 성능 저하가 발생할 수 있고 2진법 환경에서 또한 완벽한 성능을 보장하지 못한다.


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


== 아프엘의 법칙 ==
== 아프엘의 법칙 ==
* 제1법칙 : 아프엘을 현재의 어떠한 것보다 빠른 것을 더 빠르게 정확한 것을 더욱 정확하게 만들어줄 것이다.
* 제1법칙 : 아프엘을 현재의 어떠한 것보다 빠른 것을 더 빠르게 정확한 것을 더욱 정확하게 만들어줄 것이다.
* 제2법칙 : 아프엘은 어떠한 프로그램을 만들어도 신경쓰지 않는다. 아프엘은 프로그래머를 믿는다.<ref>아프엘은 구조적으로 컴파일만 되면 뭐든지 OK!라는 마인드다..</ref>
* 제2법칙 : 아프엘은 어떠한 프로그램을 만들어도 신경쓰지 않는다. 아프엘은 프로그래머를 믿는다.<ref>아프엘은 구조적으로 컴파일만 되면 뭐든지 OK!라는 마인드다..</ref>
* 제3법칙 : 아프엘은 혼자선 어설프고 부족하다.<ref>이는 차라리 어딘가 나사빠진 메모리 관리 적용할 바에 아예 메모리 관리를 없애서 아예 어설프게 만든 것에 대한 의미다.</ref> 그래서 부모님<ref>여기서 칭하는 부모님은 프로그래머를 말한다. 그래서, 프로그래머가 직접 메모리 관리를 해줘야한다. <small>''다행인건 메모리 관리 함수가 있긴하다..''</small></ref> 필요하다.
* 제3법칙 : 아프엘은 혼자선 어설프고 부족하다.<ref>이는 차라리 어딘가 나사빠진 메모리 관리 적용할 바에 아예 메모리 관리를 없애서 아예 어설프게 만든 것에 대한 의미다.</ref> 그래서 부모님<ref>여기서 칭하는 부모님은 프로그래머를 말한다.</ref> 필요하다.


== 매개 전달자 ==
== 매개 전달자 ==
33번째 줄: 35번째 줄:


== 다이렉트 엑세스 ==
== 다이렉트 엑세스 ==
아프엘은 변수를 제작하지도 않고도 다이렉트로 메모리에 값을 저장하고 접근할 수 있다. 변수의 타입은 아프엘에서 스스로 정한다. <ref>대부분 4형식 [int, float, string, TYPE+Array] number로 표시 된 값은 정수와 실수를 자체적으로 구분하여 int float로 다시 변경한다.</ref> 메모리의 값을 저장하기 위해선 무조건 전달자를 사용해서 저장해야한다. 최대 저장 할 있는 값은 0 ~ 31<ref>총 32개</ref>이다. 배열을 저장할 땐 [최소 시작][최대 종료]로 값을 지정하여 저장한 다음 값을 가져올 수 있다. 이로 인해서 미리 수많은 메모리 공간을 확보하는 것은 아니다. 실제 프로그램에 사용되는 메모리의 갯수만 미리 공간 확보가 되고 전처리기 옵션에 따라 비울 수도 있고 기존 공간 메모리의 값을 유지할 수도 있다. 이 개념들이 어렵다면, 미리 만들어져있는 매우 빠른 변수라고 생각하면 편하다.
아프엘은 변수를 제작하지도 않고도 다이렉트로 메모리에 값을 저장하고 접근할 수 있다. 변수의 타입은 아프엘에서 스스로 정한다. <ref>대부분 4형식 [int, float, string, TYPE+Array] number로 표시 된 값은 정수와 실수를 자체적으로 구분하여 int float로 다시 변경한다.</ref> 메모리의 값을 저장하기 위해선 무조건 매개 전달자를 사용해서 저장해야한다. 메모리가 감당만 가능하다면, 무한대로 저장할 있다. 또한, 배열을 저장할 땐 [최소 시작][최대 종료]로 값을 지정하여 저장한 값을 가져올 수 있다. 메모리의 할당은 프로그램 실행 전 사용되는 메모리의 만큼 할당과 함께 공간이 확보 된다.<ref>사용되지 않는 메모리 중에서...</ref> 이렇게 확보가 되면 일반적으로 변수를 생성하는 것보다 더욱 매끄럽고 빠르게 작동되며 가능한 경우 메모리와 프로세서의 정보 전달 과정에서 우선순위가 최상단으로 배치될 수 있다. 이 개념들이 어렵다면, 미리 만들어져있는 매우 빠른 변수라고 생각하면 편하다.


* 올바른 예시
* 올바른 예시
44번째 줄: 46번째 줄:


메모리에서 값을 가져올 땐 일반 변수에서 가져오듯이 가져오면 된다.
메모리에서 값을 가져올 땐 일반 변수에서 가져오듯이 가져오면 된다.
== 확장자 ==
아프엘의 소스코드 확장자는 *.al, *.als, *.alfp이 있다. 각 확장자가 의미하는 바가 있는데<br>
일반적으로 *.al과 *.als은 아프엘의 소스코드임을 나타내지만, *.alfp은 일반적인 텍스트의 소스코드가 아닌 암호화된 소스코드 프로젝트이다.
== 암호화 저장 ==
아프엘 v3부터 암호화 저장을 지원한다.<ref>명령어 도구로 'APL { ALFP << '파일경로' } >> { RST << '파일경로' }'를 입력하면 암호화된 프로젝트가 생성된다.<br>생성된 프로젝트는 APL이 내장된 컴퓨터라면 클릭하여 열 수 있다.</ref><br>
암호화 프로젝트 *.alfp에서 [[LAXA2]] 알고리즘을 사용한다. 암호화 된 프로젝트에서 지속적으로 읽기/쓰기 하는 것은 아니다.<br>
빠른 처리를 위해서 캐쉬 저장소에 해독된 소스코드에 접근하여 읽기/쓰기 후 저장 시 다시 암호화하여 저장된다.<br>
당연하게도 [[LAXA2]]의 특성상 소스코드 유출 방지와 같은 보안을 염두하고 제작 된 저장 방식이 아니다. [[LAXA2]]는 오직 컴퓨터의 바이러스 및 멀웨어 같은 악성 소프트웨어로부터 파일을 손상되는 것을 보호하는 것이다.


== 아프엘 v2 ==
== 아프엘 v2 ==
아프엘의 첫 공식 업데이트이다. 기존에 매우 시인성이 떨어졌던 매개 전달자<ref>아프엘에선 >> 매개 <<  &  매개 >> 매개 >> 와 같이 사용하는 것을 매개 전달자라고 한다.</ref>를 대폭 변경하였다.
아프엘의 첫 공식 업데이트이다. 기존에 매우 시인성이 떨어졌던 매개 전달자<ref>아프엘에선 >> 매개 <<  &  매개 >> 매개 >> 와 같이 사용하는 것을 매개 전달자라고 한다.</ref>를 대폭 변경하였다. 또한, 아프엘 v2부턴 더 나은 발전을 위해 오픈소스로 변경하였다.<br>
또한, 컴파일 성능이 이전 버전에 비하여 최대 2배 정도 향상되었다.
 
== 아프엘 v3 ==
대부분 편의성 기능과 소스코드 관련 기능들이 추가되고 일부 디버깅이 친절해졌다.<br>
특히나 메모리 접근에 실수에 대한 디버깅은 정말 많이 개선되었다. 이 외에는 CSM 실행 함수<ref>[[CSM]] 실행 함수<br>CSM{ CSM 코드 }</ref>
가 추가되었다.
 
== 아프엘 v4 ==
디버거와 컴파일 성능이 대폭 개선되고 문법이 깔끔해졌다. <small>정말 말도 안되게...</small><br>
<br>


== 예시 ==
==== 컴파일 시간 비교 ====
==== 아프엘 v1 ====
팩토리얼을 계산하는 프로그램을 작성 후 컴파일을 하면 아프엘의 버전별로 다음과 같은 시간 차이를 보여준다.
* Hello, World! 출력 <br>
* 아프엘 v1
  BAY::TYPE > 4 > BAY
compiling : 7.2173 sec
   
converting to executable : 2.1048 sec
  program start >> none <<
 
* 아프엘 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
 
==== 버전별 아프엘 디버깅 비교 ====
아래와 같은 오류를 가진 코드를 실행하고 아프엘의 버전별로 디버깅 메세지를 비교하는 다음과 같다.<br>
'''고정폭을 사용하지않으면, 틀린 부분을 표시해주는 화살표가 비정상적으로 보이니 유의하자.'''
# 아프엘 v1 ~ v3
if(true and false)
{
    out.steer(""Hello, World!")
  }
  # 아프엘 v4
  if(true and false)
  {
  {
     viwe(""Hello, World!")
     out.string >> "Hello, World!" <<
  }
  }
<br>
* 아프엘 v1에서의 디버깅 메세지
'''# COMPILE ERROR #'''
[Syntax Error : 1]
  LINE => [1]
[Unknown Error : 2]
  LINE => [3]
 
:: An error occurred in that syntax::


* 변수 생성해서 두 값을 입력받아서 더하기 <br>
* 아프엘 v2에서의 디버깅 메세지
  BAY::TYPE > 4 > BAY
  '''$ COMPILE ERROR $'''
Couldn't compile for the following reasons!
   
   
  program start >> none <<
  '''# [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!
   
   
    A = asked.number >> "첫 번째 값을 입력하세요 : " <<
'''# [LINE : 1] / [ERROR : 3] / [WARING : 1] #'''
    B = asked.number >> "두 번째 값을 입력하세요 : " <<
if'''''(true and false)'''''
    C = A + B
        ^-----^---^----- [3]
    out.freetype >> "결과 값은 : {C}입니다." <<
  ! => '''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.


* 변수 생성 없이 두 값을 입력받아서 더하기 <br>
* 아프엘 v4에서의 디버깅 메세지
  BAY::TYPE > 4 > BAY
  '''$ COMPILE ERROR! $'''
Compilation could not be completed normally due to the following error!
   
   
  program start >> none <<
  '''# [LINE : 1] / [ERROR : 4] / [WARING : 1] #'''
  {
  if'''''(true and false)'''''
   
        ^^-----^---^----- [4]
    asked.number >> "첫 번째 값을 입력하세요 : " >> mem.sav >> 0 << <<
  ! => '''true''' is undefined. Do you mean '''True'''?
    asked.number >> "두 번째 값을 입력하세요 : " >> mem.sav >> 1 << <<
  ! => '''and''' is undefined. Do you mean '''&'''?
    mem.load >> 0 << + mem.load >> 1 << take.value >> mem.sav >> 2 <<
  ! => '''false''' is undefined. Do you mean '''False'''?
    out.freetype >> "결과 값은 : {mem.load >> 2 <<}입니다." <<
  ! => 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 ====
==== 아프엘 v2 ====
* Hello, World! 출력 <br>
* Hello, World! 출력 <br>
96번째 줄: 176번째 줄:
   
   
  }
  }
 
<br>
* 변수 생성해서 두 값을 입력받아서 더하기 <br>
* 변수 생성해서 두 값을 입력받아서 더하기 <br>
  BAY::TYPE > 4 > BAY
  BAY::TYPE > 4 > BAY
109번째 줄: 189번째 줄:
      
      
  }
  }
 
<br>
* 변수 생성 없이 계산기 만들기 <br>
* 변수 생성 없이 계산기 만들기 <br>
  BAY::TYPE > 4 > BAY
  BAY::TYPE > 4 > BAY
118번째 줄: 198번째 줄:
     asked.freetype("식을 입력하시오 : ") >> format.ary("number string number") >> mem.sav[0][2]
     asked.freetype("식을 입력하시오 : ") >> format.ary("number string number") >> mem.sav[0][2]
      
      
     choice(mem.sav[1])
     choice(mem.load[1])
     {
     {
      
      
         "+" << equal {
         "+" << equal {
                 mam.load[0] + mam.load[1] >> mem.sav[3]
                 mem.load[0] + mem.load[2] >> mem.sav[3]
         }
         }
          
          
         "-" << equal {
         "-" << equal {
                 mam.load[0] - mam.load[1] >> mem.sav[3]
                 mem.load[0] - mem.load[2] >> mem.sav[3]
         }
         }
      
      
         "*" << equal {
         "*" << equal {
                 mam.load[0] * mam.load[1] >> mem.sav[3]
                 mem.load[0] * mem.load[2] >> mem.sav[3]
         }
         }
      
      
         "/" << equal {
         "/" << equal {
                 mam.load[0] / mam.load[1] >> mem.sav[3]
                 mem.load[0] / mem.load[2] >> mem.sav[3]
         }
         }
          
          
146번째 줄: 226번째 줄:
      
      
  }
  }
<br>
* 매개 전달자 극한의 사용의 예시 <small>''이런 짓은 하지말자..''</small> <br>


* 코드 줄로 더하기 프로그램 만들기 예시 <br>
BAY::TYPE > 4 > BAY
program start(none)
{
    asked.number("첫 번째 값을 입력하세요 : ") >> mem.sav[0] >> next >> asked.number("번째 값을 입력하세요 : ") >> mem.load[0] + value >> out.value
   
}


  BAY::TYPE > 4 > BAY
* 다음과 같이 처리한 것이다.
  1. 사용자에게 값 묻기
2. 물어본 값을 0번 메모리 슬롯에 저장
3. 다음 명령 실행
4. 사용자에게 값 묻기
5. 0번 메모리 슬롯 값 + 물어본 값<ref>4단계로부터 전달받은 값</ref>
6. 전달 된 값<ref>5단계에서 계산 된 값</ref> 출력
 
==== 아프엘 v4 ====
* Hello, World! 출력 <br>
src Main()
{
    view("Hello, World!")
}
<br>
* 변수 생성해서 두 값을 입력받아서 더하기 <br>
src Main()
{
    A = read("첫 번째 값을 입력하세요 : ")
    B = read("두 번째 값을 입력하세요 : ")
    C = A + B
    view(`결과 값은 : {C}입니다.`)
}
<br>
* 변수 생성 없이 계산기 만들기 <br>
   
   
  program start(none) { asked.number("첫 번째 값을 입력하세요 : ") >> mem.sav[0] >> next >> asked.number("두 번째 값을 입력하세요 : ") >> mem.sav[0] + value >> out.value }
  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]}입니다.`)
   
}
<br>


== 각주 ==
== 각주 ==

2023년 4월 9일 (일) 12:01 기준 최신판

파룸의달.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년 6월 26일 01시 00분 08초 기준. 미디어위키 표현식의 한계에 의해서 이 값은 정확하게 나타나기 힘들다. 정확한 값을 얻기 위해서는 사트/표준#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단계에서 계산 된 값