Мова BASIC

Класичний діалект BASIC в aukimi: типи, структури, два скорочені записи та правила, на яких спотикається кожен. За ним стоїть 2 237 команди.

Одним рядком#

aukimi постачає класичний діалект BASIC: повноцінну мову, а не іграшкову систему макросів, із типізованими числами, записами, методами, посиланнями, структурованими помилками, корутинами й обчисленнями на WebGPU. Він живе в режимі вікна перегляду TXT в Engine і в перегляді BASIC редактора скриптів.

JavaScript залишається канонічним 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 демо-проєктів захист дав нуль хибних спрацьовувань і знайшов два реальні тихі збої, SetMusicSystemVolume і GetLightSensorExists, які в каталозі значаться лише як MusicSystemVolume і LightSensorExists.

Дві лазівки залишені відкритими навмисно: console.log("x") і window.x = 1 досі проходять. Захист для них написали, виміряли й прибрали: BASIC працює в контексті, який постачає імена, котрі компілятор не може перелічити, тож відмова від невідомого кореня відхиляла робочі програми. Хибне спрацювання тут гірше за саму лазівку.

Найпоширеніший сюрприз:

Print(...)малює на екрані, і програма викликає це щокадру
Console(...)пише в консоль редактора, і більше нічого не робить
Debug(...)та сама команда під назвою з PureBasic, для м'язової пам'яті
ConsoleWarning, ConsoleError, ClearConsoleрешта логування

Print у кадровому циклі затопив би будь-яку справжню помилку в консолі, саме тому це дві окремі команди, а не одна з прапорцем.

Типи#

Числові типи справжні, і поводяться однаково на кожній цілі: редакторі, експорті в HTML і збірці на Bevy/native.

  • Знакові й беззнакові цілі 8, 16, 32 та 64 біти, з детермінованим приведенням типів, цілочисельним DIV і переповненням через обгортання.
  • float32 і float64.
  • Класичні сигіли досі працюють: name$ це рядок, speed# це float.

OPTION EXPLICIT опційний, і класичні неявні змінні лишаються типовою поведінкою, тож імпортовані програми все ще працюють. Увімкнути його, це передумова для двох можливостей, які не можуть бути безпечними без нього: типізації чисел і посилань, бо помилково написане присвоєння, яке мовчки створює нову змінну, зводить нанівець обидві.

Структури#

Записи#

TYPE оголошує запис. Вони можуть вкладатися довільно й мають семантику значення: присвоєння глибоко копіює запис, разом із вкладеними масивами й колекціями.

Методи#

METHOD прив'язує функцію до екземпляра, з SELF усередині, New для створення й Delete для знищення. Глибокі копії лишаються безпечними для методів.

Посилання#

REF і BYREF: одне й те саме під двома назвами, і обидва дають живий параметр для читання/запису: для скаляра, запису, окремого поля, масиву, курсора списку чи запису мапи. Посилання передаються крізь виклики й приводяться до типів фіксованої ширини на межі.

Дескриптори#

@target бере посилання першого класу. HANDLE і POINTER: типізовані форми, з перевіреним читанням, записом, перевіркою дійсності та звільненням, а дескриптор видаленого запису стає недійсним, а не висить у порожнечі.

Керування й безпека#

Структуровані помилки: TRY / CATCH / FINALLY, вкладені, з THROW, захищеним RETHROW, а також структурованими і рядковими перехопленнями.

Умовна компіляція: #IF / #ELSEIF / #ELSE / #ENDIF, вкладена, з прапорцями можливостей і явними профілями для редактора, HTML, Bevy, native/wasm та debug/release. Вона розв'язується до підключення файлів, на будь-якій цілі.

Багаті функції: значення за замовчуванням, OPTIONAL, фінальний PARAMARRAY (або ...), безпечні перевантаження за арністю, типізоване приведення значення, що повертається, і клоновані записи й масиви на поверненні.

Багатофайлові програми#

#INCLUDE, #INSERT і IncludeFile роблять програму кількома файлами. Редактор створює та імпортує модулі проєкту, доповнює шляхи включення, підтримує граф залежностей, і кожна ціль виконання під це підлаштована.

Корутини, і те, що навмисно залишили осторонь#

Кооперативні задачі побудовані на мітках, з типізованими дескрипторами, станом результату й помилки, скасуванням у точках yield і очікуванням на одну задачу чи групу. Вони спільно використовують ігровий планувальник на кожній цілі.

Потоки зі спільною пам'яттю навмисно виключені. Не «поки що ні», а виключені. Кооперативний планувальник, який можна осмислити, кращий за перегони даних, які неможливо відтворити.

Обчислення на WebGPU#

Типізовані буфери сховища f32 / i32 / u32, сирі конвеєри WGSL, диспетчеризація, впорядкована по кадрах, і зчитування memblock: справжні обчислення на GPU прямо з BASIC.

⚠️ Лише Engine. Ціль HTML видає явну помилку про відсутність можливості, а ціль Bevy повідомляє про несумісність до збірки, а не видає бінарник, який провалюється на першому виклику.

Два скорочені записи для однієї проблеми#

597 команд названі Set/Get<Object><Property>: Sprite 66, Tween 58, Text 32, Edit 29. Назва об'єкта закладена в імені функції, а його id це перший аргумент кожного рядка. Обидва скорочені записи нижче прибирають це повторення, і жоден із них не є новим API: компілятор відновлює справжню назву команди й шукає її в каталозі.

WITH <родина>, усередині блоку#

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)     ` родина ВИВОДИТЬСЯ з команди створення
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>, або з явного s AS Sprite, коли id приходить звідкись іще. Переписуються лише змінні, чия родина відома: записи зберігають свої поля, списки зберігають свої методи, 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)

{{ і }} пишуть буквальні фігурні дужки.

⚠️ Префікс $ обов'язковий, і це не декорація. Інтерполяція кожного літералу ламала написаний вручну JSON, який API світу приймає постійно:

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

Тут фігурні дужки це дані, а не місця для підстановки. Рядок без префікса залишається недоторканим, хоч би що він містив.

Іменування як показ#

Класична програма створює сотні об'єктів. У Scene Graph потрапляють лише ті, яких вона НАЗВАЛА, SpriteName(id, "player") та подібні команди: це те, що поміщає об'єкт у дерево, де його бачить решта Engine. LightName і ParticlesName роблять те саме для світла й емітера.

Туторіал Назвіть те, що створює ваша програма проходить це крок за кроком: та сама сцена, один раз із порожнім деревом і один раз із трьома записами в ньому.

Каталог команд#

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).

Studio і Compute: власні доповнення aukimi до класичного діалекту, консольні команди, іменування об'єктів і конвеєр WebGPU.

Повний довідник команд перелічує їх усі, з кожним параметром і кожним перевантаженням, і має власний пошук, згенерований із того самого каталогу, який рахує ця сторінка, тож він не може від нього відстати. Власна панель API редактора теж читає цей каталог.

Ця сторінка документує мову; та документує команди.

Обмеження та типові пастки#

  • Дужки не опційні для команди. Гола форма з PureBasic (Debug "x") відхиляється, бо вона знову відкриває неоднозначність змінна/команда, на якій тримається компіляційний захист.
  • Функція користувача перемагає каталоговану команду з тією самою назвою, і змінна може ділити назву з командою в типізованому оголошенні, ліворуч від присвоєння, або як корінь шляху.
  • Змінні й функції користувача нечутливі до регістру, і їхні простори імен справді окремі від каталогу.
  • Print це не лог. Див. вище, це саме та помилка, яка заповнює консоль.
  • Compute не експортується. Напишіть запасний шлях, перш ніж на нього покладатися.