Jazyk BASIC

Klasický dialekt BASIC aukimi: typy, struktury, dvě zkratky, a pravidla, na která narazí každý. Za tím vším stojí 2 237 příkazů.

V jedné větě#

Aukimi nabízí dialekt klasického BASICu: plnohodnotný jazyk, ne hračkový makro systém, s typovanými čísly, záznamy, metodami, referencemi, strukturovanými chybami, korutinami a WebGPU compute. Žije v režimu viewportu TXT v Engine a v pohledu BASIC v editoru skriptů.

JavaScript zůstává kanonickým API pro skriptování. BASIC je volitelný frontend: oba se kompilují do stejného soukromého dispečera, takže program v BASICu a program v JavaScriptu dosáhnou přesně na stejný engine. Nic tu není druhořadé, a nic není samostatný runtime.

Pravidlo, na které narazí každý#

Volání příkazu má vždy závorky.

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

Toto není otázka stylu. Je to to, co umožňuje kompilátoru rozlišit příkaz od proměnné, a je to důvod, proč se překlep teď odhalí už při kompilaci:

NapíšeteCo se dělo dřívCo se děje teď
SpritePositon(1, 10, 20)zkompilovalo se čistě, sprite se nepohnul, a chyba se objevila později jako ... is not definedchyba kompilace, s návrhem nejbližšího katalogizovaného zápisu
Blorp(1, 2)přeposláno beze změny do vygenerovaného JavaScriptuchyba kompilace
ceci nest pas du basicvyzářeno jako příkazchyba kompilace

Chyba v psaní se dřív projevovala jako chyba enginu. Na korpusu 84 dem hlídač nevyprodukoval žádné falešné poplachy a našel dvě skutečná tichá selhání, SetMusicSystemVolume a GetLightSensorExists, které katalog zná jen jako MusicSystemVolume a LightSensorExists.

Dvě mezery zůstávají otevřené záměrně: console.log("x") a window.x = 1 projdou dál. Hlídač pro ně byl napsaný, změřený a stažený: BASIC běží uvnitř kontextu, který dodává jména, jež kompilátor nedokáže vyjmenovat, takže odmítnutí neznámého kořene odmítalo i platné programy. Falešný poplach je tam horší než ta mezera.

Nejčastější zdroj překvapení:

Print(...)kreslí na obrazovku, a program ho volá každý snímek
Console(...)zapíše do konzole editoru, a nedělá nic jiného
Debug(...)stejný příkaz pod jménem z PureBasicu, pro svalovou paměť
ConsoleWarning, ConsoleError, ClearConsolezbytek logu

Print v cyklu snímků by utopil jakoukoli skutečnou chybu v konzoli, a proto jsou to dva samostatné příkazy místo jednoho s příznakem.

Typy#

Číselné typy jsou skutečné a chovají se stejně na každém cíli: v editoru, exportu do HTML i buildu Bevy/native.

  • Signed a unsigned 8, 16, 32 a 64bitová celá čísla, s deterministickou konverzí, celočíselným DIV a přetečením typu wrapping.
  • float32 a float64.
  • Klasické sigily pořád fungují: name$ je řetězec, speed# je float.

OPTION EXPLICIT je volitelné, a klasické implicitní proměnné zůstávají výchozím chováním, aby importované programy dál fungovaly. Jeho zapnutí je předpokladem pro dvě funkce, které bez něj nemohou být bezpečné, typování čísel a reference, protože překlepnuté přiřazení, které tiše vytvoří novou proměnnou, by porazilo obojí.

Struktury#

Záznamy#

TYPE deklaruje záznam. Vnořují se libovolně a mají hodnotovou sémantiku: přiřazení jeden hluboce zkopíruje, včetně vnořených polí a kolekcí.

Metody#

METHOD naváže funkci na instanci, s SELF uvnitř, New pro konstrukci a Delete pro zničení. Hluboké kopie zůstávají bezpečné i vůči metodám.

Reference#

REF a BYREF jsou totéž pod dvěma zápisy, a oba dávají živý čtecí/zapisovací parametr, pro skalár, záznam, jedno pole, pole (array), kurzor seznamu nebo položku mapy. Reference se přenášejí přes volání a na hranici se konvertují na typy s pevnou šířkou.

Handles#

@target vezme referenci jako plnohodnotnou hodnotu prvního řádu. HANDLE a POINTER jsou typované formy, s kontrolovaným čtením, zápisem, platností a uvolněním, a handle na smazaný záznam se zneplatní místo toho, aby zůstal viset naprázdno.

Řízení a bezpečnost#

Strukturované chyby: TRY / CATCH / FINALLY, vnořené, s THROW, chráněným RETHROW, a strukturovaným i řetězcovým odchytáváním.

Podmíněná kompilace: #IF / #ELSEIF / #ELSE / #ENDIF, vnořená, s feature flagy a explicitními profily pro editor, HTML, Bevy, native/wasm a debug/release. Řeší se před includy, na každém cíli.

Bohaté funkce: výchozí hodnoty, OPTIONAL, závěrečný PARAMARRAY (nebo ...), bezpečné přetížení podle arity, typovaná konverze návratové hodnoty a klonované návraty záznamů a polí.

Vícesouborové programy#

#INCLUDE, #INSERT a IncludeFile rozdělí program do několika souborů. Editor vytváří a importuje moduly projektu, doplňuje cesty k includům, drží graf závislostí, a každý cíl runtime je na to připravený.

Korutiny, a věc, která je záměrně vynechaná#

Kooperativní úlohy jsou založené na labelech, s typovanými handles, stavem výsledku a chyby, zrušením v momentě yieldu, a čekáním na jednu úlohu nebo skupinu. Sdílejí plánovač hry na každém cíli.

Vlákna se sdílenou pamětí jsou záměrně vyloučena. Ne "zatím ne", vyloučena. Kooperativní plánovač, nad kterým umíte uvažovat, je lepší než datový závod, který nedokážete zopakovat.

WebGPU compute#

Typované úložné buffery f32 / i32 / u32, syrové WGSL pipeline, dispatch seřazený podle snímků a čtení memblocku zpět, skutečný GPU compute z BASICu.

⚠️ Jen Engine. Cíl HTML vyhodí explicitní chybu chybějící schopnosti, a cíl Bevy hlásí nekompatibilitu před buildem místo toho, aby vyprodukoval binárku, která selže při prvním dispatchi.

Dvě zkratky pro stejný problém#

597 příkazů se jmenuje Set/Get<Object><Property>: Sprite 66, Tween 58, Text 32, Edit 29. Jméno objektu je uvnitř jména funkce a jeho id je prvním argumentem každého řádku. Obě zkratky níže tuto opakovanost odstraňují, a žádná z nich není nové API: kompilátor si znovu sestaví skutečné jméno příkazu a vyhledá ho v katalogu.

WITH <family>, uvnitř bloku#

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

Na začátku příkazu \prop zapisuje; kdekoli jinde čte. O tom rozhoduje pozice, takže se nemusíte učit druhou notaci. WITH hero, jeden token, je pořád blok záznamu; WITH SPRITE s vybere rodinu z katalogu.

s.position(...), všude jinde#

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)

Rodina pochází z Create<F> / Load<F> / Clone<F>, nebo z explicitního s AS Sprite, když id přijde odjinud. Přepisují se jen proměnné, jejichž rodina je známá: záznamy si drží svá pole, seznamy si drží své metody, SELF.field zůstává nedotčené.

⚠️ Typovaný parametr se nerozpozná. FUNCTION move(s AS Sprite) nedá s rodinu, průchod čte jen deklarace a přiřazení na úrovni příkazů. Je to tu napsané, protože je to skutečný limit, ne chyba, kterou byste měli hledat.

⚠️ Katalog na vlastnostech vynechává sloveso, a na životním cyklu ho drží. SpritePosition zapisuje, SpriteX čte, a žádný z nich nenese Set nebo Get: 4 příkazy v celém katalogu začínají na Set, a žádný nezačíná na Get. Sloveso přežívá tam, kde něco vzniká nebo končí: CreateSprite, LoadImage, DeleteSprite.

To stojí za to vědět, protože překlep je chyba kompilace, a Set… je ten překlep, se kterým lidé přicházejí. Katalog je autorita, a reference je z něj vygenerovaná.

Interpolace řetězců, volitelně#

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

{{ a }} napíší doslovné složené závorky.

⚠️ Prefix $ je povinný, a není to jen ozdoba. Interpolování každého literálu rozbíjelo ručně psaný JSON, který world API běžně přebírá:

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

Tady jsou složené závorky data, ne díry k vyplnění. Řetězec bez prefixu zůstane nedotčený, ať obsahuje cokoli.

Pojmenování je zviditelnění#

Klasický program vytváří stovky objektů. Do Scene Graph vstoupí jen ty, které jsou POJMENOVANÉ, SpriteName(id, "player") a jeho příbuzní jsou to, co umístí objekt do stromu, kde ho vidí zbytek Engine. LightName a ParticlesName dělají totéž pro světlo a emitor.

Tutoriál Pojmenujte, co váš program vytváří to prochází krok za krokem: stejná scéna, jednou s prázdným stromem a jednou se třemi položkami v něm.

Katalog příkazů#

2 237 příkazů, 2 550 veřejných přetížení, 43 kategorií. Ty největší:

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

plus 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 a Compute jsou vlastní přírůstky Aukimi ke klasickému dialektu: konzolové příkazy, pojmenování objektů a pipeline WebGPU.

Kompletní reference příkazů je vypisuje všechny, s každým parametrem a každým přetížením, a s vlastním vyhledáváním, vygenerovaná ze stejného katalogu, který tato stránka počítá, takže za ním nemůže zaostat. I panel API v editoru čte tentýž katalog.

Tato stránka dokumentuje jazyk; ta druhá dokumentuje příkazy.

Limity a časté zádrhely#

  • Závorky u příkazu nejsou volitelné. Holá forma z PureBasicu (Debug "x") je odmítnutá, protože by znovu otevřela nejednoznačnost proměnná/příkaz, na které stojí hlídač z doby kompilace.
  • Uživatelská funkce vyhraje nad katalogizovaným příkazem stejného jména, a proměnná může sdílet jméno příkazu v typované deklaraci, na levé straně přiřazení, nebo jako kořen cesty.
  • Proměnné a uživatelské funkce nerozlišují velikost písmen, a jejich jmenné prostory jsou skutečně oddělené od katalogu.
  • Print není log. Viz výše; je to chyba, která zaplaví konzoli.
  • Compute se neexportuje. Napište záložní cestu dřív, než se na to spolehnete.