BASIC 언어

aukimi의 클래식 BASIC 방언: 타입, 구조체, 두 가지 축약형, 그리고 누구나 걸려드는 규칙. 그 뒤에는 2,237개의 명령이 있습니다.

한 줄로#

Aukimi는 클래식 BASIC 방언을 제공합니다: 장난감 매크로 시스템이 아니라 완전한 언어입니다. 타입이 있는 숫자, 레코드, 메서드, 참조, 구조화된 에러, 코루틴, WebGPU 컴퓨트까지 갖추고 있습니다. 이는 Engine의 TXT 뷰포트 모드와 스크립트 에디터의 BASIC 뷰 안에서 살아갑니다.

JavaScript가 표준(canonical) 스크립팅 API로 남습니다. BASIC은 선택적 프론트엔드입니다: 둘 다 같은 비공개 디스패처로 컴파일되므로, BASIC 프로그램과 JavaScript 프로그램은 정확히 같은 엔진에 도달합니다. 아무것도 이등 시민이 아니고, 별도의 런타임도 없습니다.

누구나 걸려드는 규칙#

명령 호출에는 항상 괄호가 따라붙습니다.

mode = ClipSpaceMode()
SpritePosition(player, 320, 180)

이것은 스타일 문제가 아닙니다. 컴파일러가 명령과 변수를 구별할 수 있게 해주는 것이며, 오타가 이제 컴파일 시점에 잡히는 이유이기도 합니다.

이렇게 쓰면예전에는 이랬음지금은 이렇게 됨
SpritePositon(1, 10, 20)문제없이 컴파일되고, 스프라이트는 움직이지 않았으며, 실패는 나중에 ... is not defined로 드러났음컴파일 에러, 카탈로그에서 가장 가까운 철자를 제안함
Blorp(1, 2)생성된 JavaScript 안으로 그대로 전달됨컴파일 에러
ceci nest pas du basic하나의 구문으로 처리됨컴파일 에러

작성 실수가 예전에는 엔진 버그처럼 보였습니다. 84개의 데모로 이루어진 코퍼스를 기준으로 측정했을 때, 이 가드는 거짓 양성 0건을 내면서 실제 소리 없는 실패 두 건, SetMusicSystemVolumeGetLightSensorExists를 찾아냈습니다. 카탈로그가 아는 이름은 각각 MusicSystemVolumeLightSensorExists뿐입니다.

두 개의 구멍은 의도적으로 열려 있습니다: console.log("x")window.x = 1은 여전히 통과합니다. 이를 막는 가드가 작성되고 측정되었지만 철회되었습니다: BASIC은 컴파일러가 나열할 수 없는 이름을 제공하는 컨텍스트 안에서 실행되므로, 알 수 없는 루트를 거부하면 유효한 프로그램까지 거부하게 됩니다. 여기서는 거짓 양성이 그 구멍보다 더 나쁩니다.

가장 흔한 놀라움입니다.

Print(...)화면에 그리며, 프로그램은 매 프레임 이를 호출합니다
Console(...)에디터의 콘솔에 기록할 뿐, 그 외에는 아무것도 하지 않습니다
Debug(...)근육 기억을 위한, PureBasic의 이름을 그대로 쓴 같은 명령
ConsoleWarning, ConsoleError, ClearConsole나머지 로그 관련 명령

프레임 루프 안의 Print는 콘솔 안의 진짜 에러를 파묻어버릴 것입니다. 이 둘이 플래그 하나 있는 명령 하나가 아니라 별개의 명령인 이유가 이것입니다.

타입#

숫자 타입은 실제이며, 어떤 대상에서든, 에디터에서든, HTML 내보내기에서든, Bevy/네이티브 빌드에서든 동일하게 동작합니다.

  • 8, 16, 32, 64비트의 부호 있는/없는 정수, 결정적인 강제 변환, 정수 DIV, 랩어라운드 오버플로.
  • float32와 float64.
  • 클래식 시길은 여전히 작동합니다: name$은 문자열, speed#는 float입니다.

OPTION EXPLICIT는 선택 사항이며, 클래식한 암묵적 변수가 여전히 기본값으로 남아 있어 가져온 프로그램도 계속 실행됩니다. 이를 켜는 것은 그것 없이는 안전할 수 없는 두 기능, 즉 숫자 타이핑과 참조의 전제 조건입니다. 오타로 인한 대입이 소리 없이 변수를 새로 만들어버리면 둘 다 무력화되기 때문입니다.

구조체#

레코드#

TYPE은 레코드를 선언합니다. 이들은 임의로 중첩되며, 값 시맨틱을 가집니다: 하나를 대입하면 중첩된 배열과 컬렉션을 포함해 깊은 복사가 이루어집니다.

메서드#

METHOD는 함수를 인스턴스에 묶으며, 그 안에서는 SELF를, 생성에는 New를, 파괴에는 Delete를 씁니다. 깊은 복사는 메서드에 안전하게 유지됩니다.

참조#

REFBYREF는 두 개의 철자로 쓰인 같은 것이며, 둘 다 스칼라, 레코드, 단일 필드, 배열, 리스트 커서, 맵 항목에 대해 실시간 읽기/쓰기 파라미터를 제공합니다. 참조는 호출을 거쳐 전달되며, 경계에서 고정 폭 타입으로 강제 변환됩니다.

핸들#

@target은 일급 참조를 취합니다. HANDLEPOINTER는 타입이 있는 형태이며, 검사된 읽기, 쓰기, 유효성, 해제를 갖습니다. 삭제된 레코드에 대한 핸들은 매달린 채로 남는 대신 무효화됩니다.

제어와 안전#

구조화된 에러: TRY / CATCH / FINALLY, 중첩 가능하며, THROW, 보호된 RETHROW, 구조화된 캐치와 문자열 캐치 모두 지원합니다.

조건부 컴파일: #IF / #ELSEIF / #ELSE / #ENDIF, 중첩 가능하며, 기능 플래그와 에디터/HTML/Bevy/네이티브-wasm/디버그-릴리스를 위한 명시적 프로파일이 있습니다. 이는 모든 대상에서 include보다 먼저 해석됩니다.

풍부한 함수: 기본값, OPTIONAL, 마지막에 오는 PARAMARRAY(또는 ...), 안전한 인자 개수 오버로드, 타입이 있는 반환 강제 변환, 복제된 레코드와 배열 반환.

여러 파일로 이루어진 프로그램#

#INCLUDE, #INSERT, IncludeFile은 프로그램을 여러 파일로 만듭니다. 에디터는 프로젝트 모듈을 만들고 가져오며, include 경로를 자동 완성하고, 의존성 그래프를 유지하며, 모든 런타임 대상이 이를 지원하도록 배선되어 있습니다.

코루틴, 그리고 의도적으로 빠진 것#

협력적 태스크는 레이블 기반이며, 타입이 있는 핸들, 결과와 에러 상태, yield 지점에서의 취소, 하나의 태스크 또는 그룹에 대한 await를 갖습니다. 이들은 모든 대상에서 게임 스케줄러를 공유합니다.

공유 메모리를 쓰는 스레드는 의도적으로 제외되어 있습니다. "아직 없음"이 아니라 제외되어 있다는 뜻입니다. 추론할 수 있는 협력적 스케줄러가, 재현할 수 없는 데이터 경합보다 낫습니다.

WebGPU 컴퓨트#

타입이 있는 f32 / i32 / u32 스토리지 버퍼, 원시 WGSL 파이프라인, 프레임 순서가 보장된 디스패치와 memblock 읽기, BASIC에서의 진짜 GPU 컴퓨트입니다.

⚠️ Engine 전용입니다. HTML 대상은 명시적인 기능 에러를 발생시키고, Bevy 대상은 첫 디스패치에서 실패하는 바이너리를 만드는 대신 빌드 전에 호환되지 않음을 보고합니다.

같은 문제를 위한 두 가지 축약형#

명령의 597개가 Set/Get<Object><Property>라는 이름을 갖습니다: Sprite 66개, Tween 58개, Text 32개, Edit 29개. 오브젝트의 이름이 함수 이름 안에 들어 있고, 그 id가 모든 줄의 첫 번째 인자입니다. 아래 두 축약형 모두 그 반복을 없애며, 둘 다 새로운 API가 아닙니다. 컴파일러가 진짜 명령 이름을 재구성해 카탈로그에서 찾아볼 뿐입니다.

WITH <family>, 블록 안에서#

WITH SPRITE s
  \position 100, 200      ` SpritePosition(s, 100, 200)
  \size 64, 64            ` SpriteSize(s, 64, 64)
  x# = \x                 ` SpriteX(s)
ENDWITH

구문 맨 앞의 \prop씁니다. 그 외의 자리에서는 읽습니다. 위치가 결정하므로, 배워야 할 두 번째 표기법은 없습니다. 토큰 하나짜리 WITH hero는 여전히 레코드 블록이고, WITH SPRITE s는 카탈로그 계열을 선택합니다.

s.position(...), 그 외 모든 곳에서#

s = CreateSprite(img)     ` the family is DEDUCED from the creation command
s.position(100, 200)      ` SpritePosition(s, 100, 200)
s.visible = 1             ` SpriteVisible(s, 1)
x# = s.x                  ` SpriteX(s)

계열은 Create<F> / Load<F> / Clone<F>에서 오거나, id가 다른 곳에서 온 경우에는 명시적인 s AS Sprite에서 옵니다. 계열이 알려진 변수만 재작성됩니다: 레코드는 자신의 필드를 유지하고, 리스트는 자신의 메서드를 유지하며, SELF.field는 건드려지지 않습니다.

⚠️ 타입이 있는 파라미터는 인식되지 않습니다. FUNCTION move(s AS Sprite)s에 계열을 부여하지 않습니다. 이 패스는 구문 수준의 선언과 대입만 읽습니다. 이는 실제 한계이지 찾아내야 할 버그가 아니므로 여기 명시해 둡니다.

⚠️ 카탈로그는 속성에서는 동사를 떼어내고, 생명주기에서는 유지합니다. SpritePosition은 쓰고, SpriteX는 읽으며, 둘 다 Set이나 Get을 달고 있지 않습니다: 전체 카탈로그 중 4개의 명령만 Set으로 시작하고, Get으로 시작하는 것은 하나도 없습니다. 동사는 무언가가 생겨나거나 끝나는 곳에서만 살아남습니다: CreateSprite, LoadImage, DeleteSprite.

이것을 알아둘 가치가 있는 이유는, 오타가 컴파일 에러가 되고, Set…이 사람들이 흔히 저지르는 오타이기 때문입니다. 카탈로그가 권위이며, 레퍼런스는 바로 그 카탈로그로부터 생성됩니다.

문자열 보간, 선택적으로#

Print($"score: {points}")        ` "score: " + Str(points)

{{}}는 실제 중괄호를 씁니다.

⚠️ $ 접두사는 필수이며, 장식이 아닙니다. 모든 리터럴을 보간해버리면 월드 API가 일상적으로 받는, 손으로 작성한 JSON이 망가집니다.

CreateTerrain("island", "{\"preset\":\"island\",\"size\":256}")

여기서 중괄호는 홀(hole)이 아니라 데이터입니다. 접두사가 없는 문자열은 무엇을 담고 있든 그대로 남습니다.

이름 붙이기는 곧 보여주기입니다#

클래식한 프로그램은 수백 개의 오브젝트를 만듭니다. 이름이 붙은 것만 Scene Graph에 들어갑니다. SpriteName(id, "player")와 그 형제 명령들이 바로 오브젝트를 나머지 Engine이 볼 수 있는 트리 안에 놓는 것들입니다. LightNameParticlesName도 라이트와 이미터에 대해 같은 일을 합니다.

튜토리얼 프로그램이 만든 것에 이름 붙이기는 같은 씬을, 한 번은 트리가 비어 있는 상태로, 한 번은 세 개의 항목이 있는 상태로 보여주며 이를 다룹니다.

명령 카탈로그#

2,237개의 명령, 2,550개의 공개 오버로드, 43개 카테고리. 가장 큰 것들은 다음과 같습니다.

3D286Studio106File61
Core200Input95Memblock43
Tweening149Input-Raw943D Particles41
3D Physics144Multiplayer91World40
Sprite135Text68Particles38
Platform1112D Physics66Sound37

그리고 JSON (36), Image (35), Skeleton (34), XML (34), Music (29), Preference (27), Extras (21), HTTP (21), String (21), Math (19), Regular Expression (19), Video (18), Dictionary (17), Benchmarking (15), Compute (14), Date (13), Maths (12), Time (12), StringBuilder (9), Compression (7), Font (8), Error (4), Array (3), Cipher (2), Sort (2).

StudioCompute는 클래식 방언에 대한 aukimi 자체의 추가 항목입니다. 콘솔 명령, 오브젝트 이름 붙이기, WebGPU 파이프라인이 그것입니다.

**전체 명령 레퍼런스**는 이 모든 것을 모든 파라미터와 오버로드와 함께, 자체 검색 기능을 갖추어 나열하며, 이 페이지가 세고 있는 것과 같은 카탈로그로부터 생성되므로 뒤처질 수 없습니다. 에디터 자체의 API 패널도 같은 카탈로그를 읽습니다.

이 페이지는 언어를 문서화하고, 그 페이지는 명령을 문서화합니다.

한계와 흔한 함정#

  • 명령에 괄호는 선택 사항이 아닙니다. PureBasic의 맨몸 형태(Debug "x")는 거부됩니다. 컴파일 시점 가드가 의존하는 변수/명령 모호성을 다시 열어버리기 때문입니다.
  • 사용자 함수는 같은 이름의 카탈로그 명령을 이깁니다. 타입이 있는 선언, 대입의 왼쪽, 경로의 루트에서는 변수가 명령과 이름을 공유할 수도 있습니다.
  • 변수와 사용자 함수는 대소문자를 구분하지 않으며, 이들의 심볼 공간은 카탈로그의 것과 완전히 분리되어 있습니다.
  • Print는 로그가 아닙니다. 위를 참고하세요. 콘솔을 가득 채우는 실수입니다.
  • Compute는 내보내지지 않습니다. 이에 의존하기 전에 대체 경로를 작성하세요.