Die BASIC-Sprache
aukimis klassischer BASIC-Dialekt, Typen, Strukturen, die zwei Kurzschreibweisen, und die Regeln, die jeden erwischen. 2 237 Befehle dahinter.
In einem Satz#
aukimi liefert einen klassischen BASIC-Dialekt: eine vollständige Sprache,
kein Spielzeug-Makrosystem, mit typisierten Zahlen, Records, Methoden,
Referenzen, strukturierten Fehlern, Koroutinen und WebGPU-Compute. Er lebt im
TXT-Viewport-Modus der Engine und in der BASIC-Ansicht des Skripteditors.
JavaScript bleibt die kanonische Scripting-API. BASIC ist ein optionales Frontend: Beide kompilieren zum selben privaten Dispatcher, sodass ein BASIC-Programm und ein JavaScript-Programm genau dieselbe Engine erreichen. Nichts ist zweite Klasse, und nichts ist eine separate Runtime.
Die Regel, die jeden erwischt#
Ein Befehlsaufruf trägt immer Klammern.
mode = ClipSpaceMode()
SpritePosition(player, 320, 180)
Das ist keine Stilfrage. Es ist das, was dem Compiler erlaubt, einen Befehl von einer Variable zu unterscheiden, und deshalb wird ein Tippfehler heute schon beim Kompilieren erkannt:
| Sie schreiben | Was früher passierte | Was jetzt passiert |
|---|---|---|
SpritePositon(1, 10, 20) | kompilierte sauber, das Sprite bewegte sich nicht, und der Fehler zeigte sich erst später als ... is not defined | Kompilierfehler, mit der nächstliegenden katalogisierten Schreibweise als Vorschlag |
Blorp(1, 2) | wortwörtlich ins generierte JavaScript weitergereicht | Kompilierfehler |
ceci nest pas du basic | als Anweisung ausgegeben | Kompilierfehler |
Ein Schreibfehler gab sich früher als Engine-Bug aus. Gemessen am Korpus von 84 Demos produzierte der Guard null falsch positive Treffer und fand zwei echte stille Fehler,
SetMusicSystemVolumeundGetLightSensorExists, die der Katalog nur alsMusicSystemVolumeundLightSensorExistskennt.
Zwei Lecks bleiben absichtlich offen: console.log("x") und window.x = 1
laufen weiterhin durch. Ein Guard dafür wurde geschrieben, gemessen und
zurückgezogen: BASIC läuft innerhalb eines Kontexts, der Namen liefert, die
der Compiler nicht aufzählen kann, sodass das Ablehnen einer unbekannten
Wurzel gültige Programme verwarf. Ein falsch positiver Treffer dort wiegt
schwerer als das Leck.
Print zeichnet. Console protokolliert.#
Die mit Abstand häufigste Überraschung:
Print(...) | zeichnet auf den Bildschirm, und ein Programm ruft es jeden Frame auf |
Console(...) | schreibt in die Konsole des Editors, und tut sonst nichts |
Debug(...) | derselbe Befehl unter PureBasics Namen, für das Muskelgedächtnis |
ConsoleWarning, ConsoleError, ClearConsole | der Rest des Logs |
Print in einer Frame-Loop würde jeden echten Fehler in der Konsole
ertränken, deshalb sind die beiden getrennte Befehle statt einem mit einem
Flag.
Typen#
Numerische Typen sind real, und sie verhalten sich auf jedem Ziel identisch: im Editor, im HTML-Export und im Bevy-/Native-Build:
- Vorzeichenbehaftete und vorzeichenlose 8-, 16-, 32- und
64-Bit-Ganzzahlen, mit deterministischer Koerzition, ganzzahligem
DIV, und wrapping Overflow. - float32 und float64.
- Die klassischen Sigils funktionieren weiterhin:
name$ist ein String,speed#ein Float.
OPTION EXPLICIT ist opt-in, und klassische implizite Variablen bleiben
der Standard, damit importierte Programme weiterlaufen. Es zu aktivieren, ist
die Voraussetzung für die zwei Funktionen, die ohne es nicht sicher sein
können: numerische Typisierung und Referenzen, denn eine falsch geschriebene
Zuweisung, die stillschweigend eine Variable erzeugt, unterläuft beides.
Strukturen#
Records#
TYPE deklariert einen Record. Sie verschachteln sich beliebig, und sie haben
Wertsemantik: Eine Zuweisung erzeugt eine Tiefenkopie, einschließlich
verschachtelter Arrays und Collections.
Methods#
METHOD bindet eine Funktion an eine Instanz, mit SELF darin, New zum
Konstruieren und Delete zum Zerstören. Tiefenkopien bleiben methodensicher.
References#
REF und BYREF sind dasselbe unter zwei Schreibweisen, und beide liefern
einen live lese-/schreibbaren Parameter, für einen Skalar, einen Record, ein
einzelnes Feld, ein Array, einen List-Cursor oder einen Map-Eintrag.
Referenzen reichen durch Aufrufe hindurch und werden an der Grenze auf
Fixed-Width-Typen koerziert.
Handles#
@target nimmt eine erstklassige Referenz. HANDLE und POINTER sind die
typisierten Formen, mit geprüftem Lesen, Schreiben, Gültigkeit und Freigabe,
und ein Handle auf einen gelöschten Record wird invalidiert, statt dangling
gelassen zu werden.
Kontrolle und Sicherheit#
Strukturierte Fehler: TRY / CATCH / FINALLY, verschachtelt, mit
THROW, geschütztem RETHROW, sowohl strukturierten als auch String-Catches.
Bedingte Kompilierung: #IF / #ELSEIF / #ELSE / #ENDIF,
verschachtelt, mit Feature-Flags und expliziten Profilen für Editor, HTML,
Bevy, Native/Wasm und Debug/Release. Sie wird auf jedem Ziel vor den
Includes aufgelöst.
Reichhaltige Funktionen: Default-Werte, OPTIONAL, ein abschließendes
PARAMARRAY (oder ...), sichere Arity-Overloads, typisierte
Rückgabe-Koerzition, und geklonte Record- und Array-Rückgaben.
Mehrdateiprogramme#
#INCLUDE, #INSERT und IncludeFile machen aus einem Programm mehrere
Dateien. Der Editor erstellt und importiert Projektmodule, vervollständigt
Include-Pfade, führt den Abhängigkeitsgraphen, und jedes Laufzeitziel ist
dafür verdrahtet.
Koroutinen, und das, was absichtlich weggelassen wurde#
Kooperative Tasks sind label-basiert, mit typisierten Handles, einem Ergebnis- und Fehlerstatus, Cancellation bei Yields, und Awaits auf eine Task oder eine Gruppe. Sie teilen sich den Game Scheduler auf jedem Ziel.
Threads mit gemeinsamem Speicher sind absichtlich ausgeschlossen. Nicht als „noch nicht" ausgeschlossen. Ein kooperativer Scheduler, über den man nachdenken kann, schlägt eine Data Race, die man nicht reproduzieren kann.
WebGPU-Compute#
Typisierte f32- / i32- / u32-Storage-Buffer, rohe WGSL-Pipelines,
frame-geordneter Dispatch und Memblock-Readback, echtes GPU-Compute aus BASIC.
⚠️ Nur Engine. Das HTML-Ziel wirft einen expliziten Capability-Error, und das Bevy-Ziel meldet die Inkompatibilität vor dem Build, statt ein Binary zu produzieren, das beim ersten Dispatch fehlschlägt.
Zwei Kurzschreibweisen für dasselbe Problem#
597 der Befehle heißen Set/Get<Object><Property>: Sprite 66, Tween 58,
Text 32, Edit 29. Der Name des Objekts steckt im Funktionsnamen, und seine id
ist das erste Argument jeder Zeile. Beide Kurzschreibweisen unten entfernen
diese Wiederholung, und keine ist eine neue API: Der Compiler baut den echten
Befehlsnamen neu auf und schlägt ihn im Katalog nach.
WITH <family>, innerhalb eines Blocks#
WITH SPRITE s
\position 100, 200 ` SpritePosition(s, 100, 200)
\size 64, 64 ` SpriteSize(s, 64, 64)
x# = \x ` SpriteX(s)
ENDWITH
Am Kopf einer Anweisung schreibt \prop; überall sonst liest es. Die
Position entscheidet, es gibt also keine zweite Notation zu lernen. WITH hero, ein Token, ist weiterhin der Record-Block; WITH SPRITE s wählt eine
Katalog-Familie.
s.position(...), überall sonst#
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)
Die Familie kommt von Create<F> / Load<F> / Clone<F>, oder von einem
expliziten s AS Sprite, wenn die id von anderswo kommt. Nur Variablen, deren
Familie bekannt ist, werden umgeschrieben: Records behalten ihre Felder,
Listen behalten ihre Methoden, SELF.field bleibt unangetastet.
⚠️ Ein typisierter Parameter wird nicht erkannt.
FUNCTION move(s AS Sprite) gibt s keine Familie, der Pass liest nur
Deklarationen und Zuweisungen auf Statement-Ebene. Hier festgehalten, weil es
eine echte Grenze ist, kein Bug, den man jagen sollte.
⚠️ Der Katalog lässt das Verb bei Properties weg, und behält es beim
Lifecycle. SpritePosition schreibt, SpriteX liest, und keines trägt ein
Set oder ein Get: 4 Befehle im gesamten Katalog beginnen mit Set,
und keiner beginnt mit Get. Das Verb überlebt dort, wo etwas entsteht
oder endet: CreateSprite, LoadImage, DeleteSprite.
Das sollte man wissen, denn ein Tippfehler ist ein Kompilierfehler, und
Set… ist der Tippfehler, mit dem Leute ankommen. Der Katalog ist die
Autorität, und die Referenz wird aus ihm
generiert.
String-Interpolation, opt-in#
Print($"score: {points}") ` "score: " + Str(points)
{{ und }} schreiben wörtliche geschweifte Klammern.
⚠️ Das Präfix $ ist zwingend, und es ist keine Dekoration. Jedes
Literal zu interpolieren brach handgeschriebenes JSON, das die World-API
routinemäßig entgegennimmt:
CreateTerrain("island", "{\"preset\":\"island\",\"size\":256}")
Dort sind die geschweiften Klammern Daten, keine Lücken. Ein String ohne Präfix bleibt unangetastet, egal was er enthält.
Benennen ist Zeigen#
Ein klassisches Programm erzeugt Hunderte Objekte. Nur die, die es BENENNT,
betreten den Scene Graph, SpriteName(id, "player") und seine Geschwister
sind es, die ein Objekt in den Baum stellen, wo der Rest der Engine es sehen
kann. LightName und ParticlesName tun dasselbe für ein Licht und einen
Emitter.
Das Tutorial Benennen Sie, was Ihr Programm erzeugt geht das durch: dieselbe Szene, einmal mit leerem Baum und einmal mit drei Einträgen darin.
Der Befehlskatalog#
2 237 Befehle, 2 550 öffentliche Overloads, 43 Kategorien. Die größten:
| 3D | 286 | Studio | 106 | File | 61 |
| Core | 200 | Input | 95 | Memblock | 43 |
| Tweening | 149 | Input-Raw | 94 | 3D Particles | 41 |
| 3D Physics | 144 | Multiplayer | 91 | World | 40 |
| Sprite | 135 | Text | 68 | Particles | 38 |
| Platform | 111 | 2D Physics | 66 | Sound | 37 |
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 und Compute sind aukimis eigene Ergänzungen zum klassischen Dialekt, die Konsolenbefehle, die Objektbenennung, und die WebGPU-Pipeline.
Die vollständige Befehlsreferenz listet sie alle auf, mit jedem Parameter und jedem Overload, und einer eigenen Suche, generiert aus demselben Katalog, den diese Seite zählt, sodass sie nicht dahinter zurückfallen kann. Das eigene API-Panel des Editors liest ebenfalls diesen Katalog.
Diese Seite dokumentiert die Sprache; jene dokumentiert die Befehle.
Grenzen und typische Stolperfallen#
- Klammern sind bei einem Befehl nicht optional. Die bloße
PureBasic-Form (
Debug "x") wird abgelehnt, weil sie die Variable/Befehl-Mehrdeutigkeit wieder öffnet, auf der der Compile-Time-Guard beruht. - Eine Benutzerfunktion gewinnt gegen einen katalogisierten Befehl gleichen Namens, und eine Variable darf den Namen eines Befehls teilen, in einer typisierten Deklaration, auf der linken Seite einer Zuweisung, oder als Wurzel eines Pfads.
- Variablen und Benutzerfunktionen sind case-insensitiv, und ihre Symbolräume sind wirklich getrennt von denen des Katalogs.
Printist kein Log. Siehe oben; das ist der Fehler, der eine Konsole füllt.- Compute exportiert nicht. Schreiben Sie den Fallback-Pfad, bevor Sie sich darauf verlassen.