Le langage BASIC
Le dialecte BASIC classique d'aukimi : types, structures, les deux raccourcis d'écriture, et les règles qui piègent. 2 237 commandes derrière.
En un mot#
aukimi livre un BASIC classique : un vrai langage, pas un système de macros,
avec des numériques typés, des enregistrements, des méthodes, des références,
des erreurs structurées, des coroutines et du calcul WebGPU. Il vit dans le mode
de vue TXT de l'Engine et dans la vue BASIC de l'éditeur de script.
Le JavaScript reste l'API de script canonique. Le BASIC est une façade optionnelle : les deux compilent vers le même distributeur privé, donc un programme BASIC et un programme JavaScript atteignent exactement le même moteur. Rien n'est de seconde classe, et il n'y a pas deux runtimes.
La règle qui piège tout le monde#
Un appel de commande porte toujours des parenthèses.
mode = ClipSpaceMode()
SpritePosition(player, 320, 180)
Ce n'est pas une question de style. C'est ce qui permet au compilateur de distinguer une commande d'une variable, et c'est pourquoi une faute de frappe est maintenant prise à la compilation :
| Vous écrivez | Ce qui arrivait avant | Ce qui arrive maintenant |
|---|---|---|
SpritePositon(1, 10, 20) | compilait proprement, le sprite ne bougeait pas, et la panne apparaissait plus tard en ... is not defined | erreur de compilation, avec la graphie catalogue la plus proche suggérée |
Blorp(1, 2) | recopié tel quel dans le JavaScript engendré | erreur de compilation |
ceci nest pas du basic | émis comme une instruction | erreur de compilation |
Une erreur d'écriture se présentait comme un bug du moteur. Mesuré sur le corpus de 84 démos, le garde-fou n'a produit aucun faux positif et a trouvé deux vraies pannes silencieuses,
SetMusicSystemVolumeetGetLightSensorExists, que le catalogue ne connaît que sousMusicSystemVolumeetLightSensorExists.
Deux fuites restent ouvertes exprès : console.log("x") et window.x = 1
passent encore. Un garde-fou a été écrit, mesuré, puis retiré : le BASIC
s'exécute dans un contexte qui fournit des noms que le compilateur ne peut pas
énumérer, si bien que refuser une racine inconnue rejetait des programmes
valides. Un faux positif y serait pire que la fuite.
Print dessine. Console journalise.#
La surprise la plus fréquente :
Print(...) | dessine à l'écran, et un programme l'appelle à chaque image |
Console(...) | écrit dans la console de l'éditeur, et rien d'autre |
Debug(...) | la même commande sous le nom de PureBasic, pour la mémoire musculaire |
ConsoleWarning, ConsoleError, ClearConsole | le reste du journal |
Un Print dans une boucle d'image noierait toute vraie erreur dans la console :
c'est pour cela que ce sont deux commandes et non une avec un drapeau.
Les types#
Les types numériques sont réels, et se comportent à l'identique sur toutes les cibles, l'éditeur, l'export HTML et la compilation Bevy/native :
- Entiers signés et non signés sur 8, 16, 32 et 64 bits, avec coercition
déterministe,
DIVentier et débordement cyclique. - float32 et float64.
- Les sigils classiques marchent toujours :
name$est une chaîne,speed#un flottant.
OPTION EXPLICIT est optionnel, et les variables implicites classiques
restent la valeur par défaut pour que les programmes importés tournent encore.
L'activer est le prérequis des deux fonctionnalités qui ne peuvent pas être sûres
sans lui, le typage numérique et les références, parce qu'une affectation mal
orthographiée qui crée une variable en silence met les deux en échec.
Les structures#
Les enregistrements#
TYPE déclare un enregistrement. Ils s'imbriquent arbitrairement et ont une
sémantique de valeur : une affectation en fait une copie profonde, tableaux
et collections imbriqués compris.
Les méthodes#
METHOD lie une fonction à une instance, avec SELF à l'intérieur, New pour
construire et Delete pour détruire. Les copies profondes restent sûres pour les
méthodes.
Les références#
REF et BYREF sont la même chose sous deux graphies, et les deux donnent un
paramètre vivant en lecture/écriture, pour un scalaire, un enregistrement, un
champ isolé, un tableau, un curseur de liste ou une entrée de dictionnaire. Les
références se transmettent d'appel en appel et se coercent aux types de largeur
fixe à la frontière.
Les poignées#
@cible prend une référence de première classe. HANDLE et POINTER en sont
les formes typées, avec lecture, écriture, validité et libération contrôlées, et
une poignée vers un enregistrement supprimé est invalidée plutôt que laissée
pendante.
Contrôle et sûreté#
Erreurs structurées : TRY / CATCH / FINALLY, imbriqués, avec THROW,
RETHROW protégé, et des captures aussi bien structurées que par chaîne.
Compilation conditionnelle : #IF / #ELSEIF / #ELSE / #ENDIF,
imbriqués, avec drapeaux de fonctionnalité et profils explicites pour l'éditeur,
le HTML, Bevy, le natif/wasm et debug/release. Elle est résolue avant les
inclusions, sur toutes les cibles.
Fonctions riches : valeurs par défaut, OPTIONAL, un PARAMARRAY final (ou
...), surcharges d'arité sûres, coercition du type de retour, et retours
d'enregistrements et de tableaux clonés.
Les programmes multi-fichiers#
#INCLUDE, #INSERT et IncludeFile font d'un programme plusieurs fichiers.
L'éditeur crée et importe les modules du projet, complète les chemins
d'inclusion, tient le graphe de dépendances, et toutes les cibles d'exécution
sont câblées pour cela.
Les coroutines, et ce qui est volontairement absent#
Les tâches coopératives sont fondées sur des étiquettes, avec poignées typées, un état de résultat et d'erreur, annulation aux points de rendement, et attente sur une tâche ou un groupe. Elles partagent l'ordonnanceur du jeu sur toutes les cibles.
Les fils d'exécution à mémoire partagée sont volontairement exclus. Pas « pas encore », exclus. Un ordonnanceur coopératif qu'on peut raisonner vaut mieux qu'une course de données qu'on ne peut pas reproduire.
Le calcul WebGPU#
Tampons de stockage typés f32 / i32 / u32, pipelines WGSL bruts, dispatch
ordonné par image et relecture par memblock, du vrai calcul GPU depuis BASIC.
⚠️ Engine uniquement. La cible HTML lève une erreur de capacité explicite, et la cible Bevy signale l'incompatibilité avant la compilation plutôt que de produire un binaire qui échoue au premier dispatch.
Deux raccourcis pour le même problème#
597 des commandes s'appellent Set/Get<Objet><Propriété> : Sprite 66,
Tween 58, Text 32, Edit 29. Le nom de l'objet est dans le nom de la fonction et
son identifiant est le premier argument de chaque ligne. Les deux raccourcis
ci-dessous suppriment cette répétition, et aucun n'est une nouvelle API : le
compilateur reconstruit le vrai nom de commande et le cherche dans le catalogue.
WITH <famille>, dans un bloc#
WITH SPRITE s
\position 100, 200 ` SpritePosition(s, 100, 200)
\size 64, 64 ` SpriteSize(s, 64, 64)
x# = \x ` SpriteX(s)
ENDWITH
En tête d'instruction, \prop écrit ; ailleurs, il lit. La position
décide, donc il n'y a pas de seconde notation à retenir. WITH hero, un seul
jeton, reste le bloc d'enregistrement ; WITH SPRITE s sélectionne une famille
du catalogue.
s.position(...), partout ailleurs#
s = CreateSprite(img) ` la famille est DÉDUITE de la commande de création
s.position(100, 200) ` SpritePosition(s, 100, 200)
s.visible = 1 ` SpriteVisible(s, 1)
x# = s.x ` SpriteX(s)
La famille vient de Create<F> / Load<F> / Clone<F>, ou d'un s AS Sprite
explicite quand l'identifiant arrive d'ailleurs. Seules les variables dont la
famille est connue sont réécrites : les enregistrements gardent leurs champs,
les listes leurs méthodes, SELF.champ n'est pas touché.
⚠️ Un paramètre typé n'est pas reconnu. FUNCTION move(s AS Sprite) ne donne
pas de famille à s, la passe ne lit que les déclarations et affectations au
niveau des instructions. C'est dit ici parce que c'est une vraie limite, pas un
bug à traquer.
⚠️ Le catalogue laisse tomber le verbe sur les propriétés, et le garde sur le
cycle de vie. SpritePosition écrit, SpriteX lit, et aucune des deux ne
porte de Set ni de Get : 4 commandes dans tout le catalogue commencent
par Set, et aucune par Get. Le verbe survit là où quelque chose naît ou
disparaît : CreateSprite, LoadImage, DeleteSprite.
C'est bon à savoir parce qu'une graphie fautive est une erreur de compilation, et
que Set… est justement la faute que l'on apporte avec soi. Le catalogue fait
foi, et la référence en est engendrée.
L'interpolation de chaînes, sur demande#
Print($"score: {points}") ` "score: " + Str(points)
{{ et }} écrivent des accolades littérales.
⚠️ Le préfixe $ est obligatoire, et ce n'est pas de la décoration.
Interpoler tous les littéraux cassait le JSON écrit à la main, que l'API monde
prend couramment :
CreateTerrain("island", "{\"preset\":\"island\",\"size\":256}")
Là, les accolades sont des données, pas des trous. Une chaîne sans préfixe est laissée intacte quoi qu'elle contienne.
Nommer, c'est montrer#
Un programme classique fabrique des centaines d'objets. Seuls ceux qu'il NOMME
entrent dans le Scene Graph, SpriteName(id, "player") et ses semblables sont
ce qui place un objet dans l'arbre où le reste de l'Engine peut le voir.
LightName et ParticlesName font la même chose pour une lumière et un
émetteur.
Le tutoriel Nommez ce que votre programme crée le déroule : la même scène, une fois l'arbre vide, une fois avec trois entrées.
Le catalogue de commandes#
2 237 commandes, 2 550 surcharges publiques, 43 catégories. Les plus grandes :
| 3D | 286 | Studio | 106 | File | 61 |
| Core | 200 | Input | 95 | Memblock | 43 |
| Tweening | 149 | Input-Raw | 94 | Particules 3D | 41 |
| Physique 3D | 144 | Multiplayer | 91 | World | 40 |
| Sprite | 135 | Text | 68 | Particles | 38 |
| Platform | 111 | Physique 2D | 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 et Compute sont les ajouts propres à aukimi dans le dialecte classique, les commandes de console, le nommage des objets, et le pipeline WebGPU.
La référence complète des commandes les liste toutes, avec chaque paramètre et chaque surcharge, et sa propre recherche engendrée depuis le catalogue que cette page compte, elle ne peut donc pas prendre de retard sur lui. Le panneau d'API de l'éditeur lit le même catalogue.
Cette page documente le langage ; celle-là documente les commandes.
Limites et pannes courantes#
- Les parenthèses ne sont pas optionnelles sur une commande. La forme nue de
PureBasic (
Debug "x") est refusée, parce qu'elle rouvre l'ambiguïté variable/commande dont dépend le garde-fou de compilation. - Une fonction utilisateur l'emporte sur une commande catalogue du même nom, et une variable peut porter le nom d'une commande dans une déclaration typée, à gauche d'une affectation, ou comme racine d'un chemin.
- Variables et fonctions utilisateur sont insensibles à la casse, et leurs espaces de noms sont réellement séparés de celui du catalogue.
Printn'est pas un journal. Voir plus haut ; c'est l'erreur qui remplit une console.- Le calcul GPU ne s'exporte pas. Écrivez le chemin de repli avant d'en dépendre.