ArkScript, un langage de scripting fonctionnel!

a marqué ce sujet comme résolu.

Salut Zeste de Savoir ! Je viens vous partager un projet sur lequel je travaille depuis avril 2019, ArkScript.

Pour la petite histoire : après les échecs de Kafe, j’ai voulu me remettre le pied à l’étrier en me lançant sur un petit langage lisp like, interprété. De là est né Ark (renommé plus tard en ArkScript, cf la discussion sur reddit). Puis je me suis dit "et si cette fois-ci, je le compilais vraiment ce langage?" et au lieu de me lancer dans la VM avant de faire le compilo, j’ai fait les choses proprement, et voilà où nous en sommes.

ArkScript reprend la philosophie de Kafe "scripting de jeux vidéos", mais c’est tout, les autres points sont bien différents.

Concepts et objectifs

En bref :

  • un langage immuable par défaut (passage par valeur),
  • un langage fortement et dynamiquement typé,
  • pas de références cachées à la Python avec les listes,
  • très peu de mots clés (10),
  • des closures à capture explicite,
  • privilégier les features avant les performances,
    • élimination de dépendance cycliques,
    • processeur de macros Turing Complete,
    • élimination de dead code,
  • de l’asynchrone avec n’importe quelle fonction,

ArkScript est inspiré de Lisp (entre autre pour la facilité à le parser), tout est immuable par défaut, et tout est passé par valeur. Cela représente un coût à l’exécution, coût que je suis prêt à payer (cependant toutes les fonctions travaillant sur des listes évitent le plus possible les copies, sans pour autant impliquer des références cachées comme le ferait Python). L’objectif du projet n’est pas d’être plus performant que du C bien fait, mais de privilégier les features (même si j’ai travaillé un peu sur les performances pour ne pas rester en rade), de manière à être plus productif quand on code avec ce langage.

Je voulais que le langage tourne sur VM pour le gain de performance comparé à une interprétation d’un arbre, et pour la portabilité: on compile une fois un code Ark et il marche partout tant que la VM est installée.

Le lexing/parsing se veut très simple, étant un lisp like il n’y a pas grand chose à faire. La partie la plus complexe, c’est le couple compilateur/VM, car il faut faire pas mal de choses pour fournir un langage haut niveau. On a donc de l’élimination de dépendances cycliques au parsing, de la réduction d’expressions constantes par le compilateur ainsi que de l’élimination de dead code (au scope global uniquement) et des expression statements (ce qui permet de ne pas polluer la VM avec des valeurs inutilisées). Le tout est soupoudré d’un processeur de macros Turing Complete (on peut faire des macros récursives, co-récursives, etc).

Le langage est dynamiquement et fortement typé, et autorise les listes hétérogènes. De plus, il n’y a aucune référence cachée que l’utilisateur peut manipuler, ce que je trouve très important pour conserver cet aspect d’immuabilité quand on déclare une variable avec let. En interne, côté VM, des références sont utilisées mais n’atteindront jamais l’utilisateur telle quelle et verront leur valeur copiée au moment voulu (copy on write) uniquement.

Enfin, ArkScript se veut concis et n’a que 10 mots clés à offrir: let, mut et set pour les constantes/variables, begin pour les blocks, if et while pour le contrôle de flux, del pour vider la mémoire manuellement (ArkScript profite également du RRID du langage d’implémentation, le C++), import qui permet d’importer du code Ark et des binaires qui utilisent une API spéciale (par exemple pour charger la SFML, manipuler la console…), quote pour faire de l’exécution différée, et fun pour déclarer une fonction ou closure (à capture explicite).

Le langage se veut petit pour être utilisable dans un projet sans plomber la taille de celui-ci, la machine virtuelle tient sur moins de 3000 lignes (en comptant tous les fichiers des dossiers VM/). Voir ce benchmark d’octobre 2020 qui compare ArkScript 3.0.13 à d’autres langages dont ChaiScript, Lua et Python.

Un écosystème de plugins

Le langage se veut extensible, et pour ça il expose une API pour créer facilement un plugin C++, qui peut être chargé par la machine virtuelle, par exemple pour :

  • faire des appels HTTP
  • jouer avec les couleurs du terminal
  • parser du JSON
  • communiquer avec une base SQLite3
  • et bien plus encore

Des exemples

Un petit exemple qui utilises les closures avec la capture explicite (via la notation &capture), le closure field reading (dot notation) pour simuler de l’orienté objet (sans possibilité de modifier l’objet de l’extérieur, tout est en lecture seule quand on n’est pas dans la closure):

(let create-human (fun (name age weight) {
    # functions can be invoked in the closure scope
    (let set-age (fun (new-age) (set age new-age)))

    # this will be our "constructor"
    (fun (&set-age &name &age &weight) ())
}))

(let bob (create-human "Bob" 0 144))
(let john (create-human "John" 12 15))

(print bob.age)
(bob.set-age 10)
(print bob.age)

(print john.age)

La fonction d’Ackermann Péter qui me sert pour mes benchmarks comme elle est récursive non primitive, donc pas optimisable par un compilateur, très pratique pour tester l’implémentation d’un langage:

(let ackermann (fun (m n) {
    (if (> m 0)
        (if (= 0 n)
            (ackermann (- m 1) 1)
            (ackermann (- m 1) (ackermann m (- n 1))))
        (+ 1 n))}))

(print (ackermann 3 6))

Les releases sont disponibles ici (la lib standard est fournie avec chaque release, ainsi que les modules en .arkm).

Voici le repo GitHub du projet https://github.com/ArkScript-lang/Ark. N’hésitez pas à passer faire un tour sur le site du projet et sa documentation ! Enfin si vous avez besoin d’aide, passez faire un tour sur le discord communautaire, nous nous ferons un plaisir de vous aider.

Dernière version Code size

+3 -0

Bonsoir !

Depuis le dernier post, beaucoup de changements ont eu lieu, que vous pouvez tous retrouver ici: https://github.com/ArkScript-lang/Ark/blob/dev/CHANGELOG.md

Le gros des changements, c’est:

  • une équipe qui grossi ! J’étais seul quand j’ai fait le premier post, et maintenant nous sommes 6
  • un code plus clair, qui sépare exécution (VM) et données (State)
  • un REPL (la sauvegarde de scope est en train d’être faite par un de nos contributeurs)
  • une bibliothèque standard qui grossi de jour en jour
  • des améliorations notables en terme de performance
  • toujours plus de détections d’erreurs, essentiellement sur les importations cycliques, mais aussi des erreurs plus claires au runtime

Le langage est désormais suffisamment mature pour que l’on puisse coder un forEach directement en ArkScript, sans toucher au code C++, et ça c’est beau quand même

(let forEach (fun (L code) {
    (mut i 0)
    (while (< i (len L)) {
        (mut element (@ L i))
        (code)
        (set i (+ 1 i))})}))

(forEach [1 2 3 4] '{
    (print element)})
+0 -0

Salut tout le monde!

Quoi de neuf depuis l’an dernier?

En bref:

En détails:

Déjà, une migration sur https://github.com/ArkScript-lang/ ! Dans le futur plus de dépôts vont s’y retrouver dont un gestionnaire de modules pour ArkScript qui est envisagé depuis un moment maintenant. Les modules ont été migrés sur un dépôt séparé pour plus de visibilité.

L’API a suffisamment évolué pour permettre l’appels de fonctions Ark depuis un module (mis en œuvre dans le module HTTP qui permet de faire des requêtes get/put/delete et bien d’autres, mais aussi de mettre en œuvre des serveurs web (toujours en développement)).

Petit exemple d’usage du module http :

(import "http.arkm")

(let srv (httpCreateServer))
(let f (fun (str) {
    (print "hello world")
    (+ "we got: '" str "', it worked!")}))
(httpServerGet srv "/hi" f)
(httpServerListen srv "localhost" 80)

Qui lance un serveur qui affichera we got: 'test', it worked! (pour le moment le seul argument passé est un "test", dans le futur on peut imaginer envoyer les valeurs d’une requête GET par exemple.

En espérant bientôt vous revoir, et pourquoi vous reparler sur le serveur discord du projet si vous souhaitez contribuer !

+1 -0

Long time no see!

Mais je suis porteur de beaucoup de bonnes nouvelles :)

Tout d’abord, le projet est maintenant dans une organisation dédiée: https://github.com/ArkScript-lang, sur laquelle on a donc le langage en lui même, les modules de bases (en C++), ArkDoc (un doxygen maison pour documenter du code ArkScript), le code source du site de présentation et de la documentation.

Ensuite, nous sommes maintenant 10 à travailler sur ArkScript, dont 3 contributeurs très actifs.

Les avancées sur le projet concernent essentiellement des mises à jour interne à la machine virtuelle et au compilateur, pour la rendre plus rapide (d’où la prolifération de branches orientées optimisations). Une bonne nouvelle est qu’une allocation de liste de 1000 éléments (125 essais) prenait 75µs, seulement 15µs maintenant, et l’usage mémoire global a été diminué. Le compilateur est bien plus rapide également, compiler 10k lignes de code ArkScript prend 14 secondes, contre plusieurs minutes auparavant (le couple lexer/parser va être amélioré pour faire descendre ce nombre encore plus bas).

La lib standard a légèrement été modifiée pour des conventions de nommage et de code mais rien de nouveau de ce côté, justement on attend vos retours, vos cas d’usages, vos questions sur le langage pour l’améliorer! Alors n’hésitez pas à essayer le langage, il est suffisamment stable pour être utilisé en lieu et place de Lua ou Python par exemple! :)

La liste complète de ce qui a été changé est ici: https://github.com/ArkScript-lang/Ark/blob/dev/CHANGELOG.md

Bonne journée à tous, en espérant vous revoir utiliser ArkScript !

+1 -0

Coucou tout le monde!

Actuellement on bosse sur une amélioration du REPL (outil en ligne de commande pour tester ArkScript vite fait, comme l’interpréteur Python) avec coloration et complétion, et on nettoie les projets pour éviter qu’un git clone ne traine 6000 dépendances inutiles avec lui.

Jusqu’ici on a pu améliorer les performances de la VM de façon significative en diminuant la taille de Ark::Value, le type de base traité par la VM, et on retravaille le site web et la documentation (le wiki étant voué à disparaitre). On a également (enfin) un dépot séparé pour les benchmarks: https://github.com/ArkScript-lang/benchmarks, n’hésitez pas à y contribuer !

+2 -0

Salut !

On a donc un nouvel interpréteur (REPL) qui a de la persistance entre chaque ligne tapée (avant chaque morceau de code exécuté était oublié dès qu’on tapait un nouveau code), de la coloration et de l’auto complétion, le tout en utilisant la lib replxx (en C).

Ensuite, j’ai récemment ajouté l’élimination de dead code (au scope global uniquement) pendant la compilation, on a un lexer fait maison sans regex et bien plus rapide (et qui gère enfin les séquences d’échappement, bien que je doive trouver un moyen de faire fonctionner les séquences \u \U et \x), un meilleur chargement des plugins (dynamique et non statique désormais, donc on peut faire de l’importation conditionnelle en fonction de l’OS par exemple).

Aussi, niveau usage mémoire, les plugins ajoutant des objets à ArkScript (eg une fenêtre SFML) peuvent désormais voir ces objets détruits en bonne et due forme quand le scope dans lequel est l’objet est détruit.

Niveau fonctionnement interne, la nouvelle string s’est dotée d’une fonction de formatage template, donc str:format a également été impacté. Eg: (str:format "test % something %% %% 0x%x the end %% ok" 256 "hello" -12345 3735928559) donnera test something hello -12345 0xdeadbeef the end %% ok. Si on donne trop d’arguments et pas assez de séquences %%, ils ne seront pas utilisés, si on en donne pas assez, les %% resteront tels quels, permettant de faire un formatage en plusieurs étapes. Ainsi exit les segfault/undefined behavior sur un printf("%s hello %i", "world").

Niveau lib std, elle a bougé sur un nouveau dépôt pour qu’on puisse l’update sans toucher au dépôt principal, on est en train de faire une grosse passe de documentation et renommage pour clarifier pas mal de choses, avec des noms de variables de type namespace:fonction, eg: list:reverse. Tant qu’on n’a pas de macro, le namespace sera obligatoire et non modifiable, car il fait parti à 100% du nom de la variable/constante.

Niveau erreurs, on a de meilleurs messages d’erreurs pour indiquer où on s’est trompé (au lexing et parsing, compilation et VM également).

Au lexing/parsing on aura quelque chose comme:

main:007> (if)
class Ark::ParseError: ParseError: no more token to consume
On line 1:59, got TokenType::Grouping
    1 | (if)
      |    ^
    2 | no more token to consume
Ark::State::doString failed

Dans la VM, on a de meilleurs messages quand une variable est inconnue / inutilisable ou quand on a des soucis d’importation:

main:001> (print a)
unbound variable: a
At IP: 2, PP: 0

main:001> (let a 12) (print (a))
Can't call 'a': it isn't a Function but a Number
At IP: 11, PP: 0

main:012> (import "blabla")
could not load plugin: blabla
At IP: 44, PP: 0

main:013> (import "blabla.ark")
class std::runtime_error: While processing file FILE, couldn't import blabla.ark: file not found
Ark::State::doString failed
+2 -0

Hey!

Après quelques mois sans nouvelles, je reviens pour la hacktoberfest.

Jusqu’ici le bilan est plutôt positif, on a des contributeurs qui travaillent bien sur le package manager, nuclear (en Python), et on a reçu quelques PR sur le langage lui même (correctifs de bugs surtout).

Niveau versions, on a sorti la 3.0.12 récemment, qui amène son plus gros lot de nouveautés.

Changelog:

Added

  • using a macro to define the default filename (when none is given, eg when loading bytecode files or from the REPL)
  • PLUGIN <const id> instruction to load plugin dynamically and not when the VM boots up
  • updated search paths for (import "lib.ark"), looking in ./, lib/std/ and lib/
  • added a case to display NOT instructions in the bytecode reader
  • T& as<T>() in usertype
  • enhanced error message when calling a non-function object
  • eliminating unused global scope variables in the compiler
  • adding a new feature enabled by default: FeatureRemoveUnusedVars (not enabled for the REPL | for obvious reasons)
  • added replxx as a submodule
  • added custom destructor to the user type, called when a scope is destroyed and when we use (del obj)
  • added a GVL (global virtual machine lock) to be able to use the VM in a multithreaded context
  • dockerfile + specific github action to build and push stable and nightly docker images, thanks to @yardenshoham
  • added guards to the bytecode reader to stop reading if we’re missing an entry point; now telling the user about it

Changed

  • updated the string module to benefit from the new format member function
  • updated the logger to remove fmt/format
  • changed the argument order for Ark::State
  • renamed the cache directory __arkscript__
  • operator @ can now handle negative indexes to get elements from the end of the given container
  • the standard library is now in another repository
  • moved the modules to lib/ext
  • the value of CODE_SEGMENT_START is again 0x03 (because we removed the plugin table)
  • renamed isDir? to dir? for consistency
  • the lexer is no longer using regexes but a char after char method
  • an ArkScript program is no longer a single bloc, but can be composed of multiple bloc, thus we don’t need to use a single big {} or (begin) bloc for all the program
  • enhancing lexer and parser error messages
  • else clause in if constructions is now optional
  • updating error messages in the VM
  • updated the repl to add auto completion, coloration and persistance by @PierrePharel
  • moving the parser, lexer and AST node to Compiler/ from Parser/
  • better import error messages at parsing
  • format can now handle any value type
  • updated the tests to use the new standard library, and testing every VM instruction and builtins (we didn’t test everything before, this way we can be sure we don’t break anything in the VM after each update)
  • renaming builtins to add a namespace to them (math:, sys:, str:, list: and such)
  • firstOf, tailOf and headOf now returns [] or "" instead of nil when they have nothing to do
  • adding a brand new scoping system, lighter, more powerful
  • str:find now returns the index where the substring was found
  • str:removeAt was fixed to throw an error when the index is strictly equal to the length of the string (can not work since accessing elements in string is 0-index based)

Removed

  • removed fmt/format from our dependencies
  • PLUGIN_TABLE was removed to use the PLUGIN instruction
  • not_() from usertype
  • removed Parser/Utf8Converter

A par ça, on est en train de stabiliser quelques modules, qui seront installables via le package manager, on rajoute des tests (toujours plus car trop c’est jamais assez), et on table sur un rewrite complet de la VM pour aller vers de nouvelles pistes d’optimisations.

En gros tout va pour le mieux, on attire des contributeurs et des utilisateurs, et ça c’est génial :)

+0 -0

Hello, ça faisait longtemps, me revoilà avec de bonnes nouvelles!

On bosse toujours beaucoup sur le langage avec au programme: de l’UTF8 (pour les strings et peut être les identifiers), très bientôt des macros avec gestion des arguments variadiques, diverses optimisations, et on est train d’agrandir la lib standard et les modules.

Pas mal de correctifs ont pu être fait sur les modules et pour tester tout cela, j’ai fait une mini blockchain dans le langage: https://github.com/ArkScript-lang/Ark/blob/dev/examples/blockchain.ark.

Les deux ans du projet c’est fin avril, d’ici là j’espère avoir fini le support des macros qui devront permettre de faire autant voir plus que le préprocesseur C:

!{name 12}
!{if (= name 12)
  !{a (...args) (print args)}
  !{a (...args) (print "no")}}
!{foo (a b c) {(let a 12) (let b 12) (let c 12)}}

Avec possibilité d’appeler une macro depuis une autre pour un peu plus de piment.

Une des plus belles optimisation est un passage (en interne) sur une stack linéaire unique plutôt qu’une stack de stack, ce qui nous a fait passé de 90ms à 55ms sur Ackermann Péter (3, 6), un test de récursion extrêmement gourmand. On reste loin de Python mais le but n’est pas de le rattraper/dépasser, simplement d’être suffisant rapide pour être utilisable convenablement.

Le changelog complet est ici pour les fanatiques d’updates: https://github.com/ArkScript-lang/Ark/blob/add3881d200b78275d02b492626aa140124e15aa/CHANGELOG.md

+2 -0

Bonjour, cela faisait longtemps que je n’avais pas posté ici, j’ai trop négligé la communication pour me concentrer sur le code et les cours.

Les avancées

Depuis le dernier message, le projet a subit moulte refacto:

  • 210 fichiers modifiés,
  • 11’273 lignes ajoutées,
  • 8’065 lignes supprimées (pas assez à mon goût)

Dans les grandes lignes, le projet a été remanié pour faciliter son intégration dans d’autres projets, et également envisager un publication sur les dépôts d’Arch Linux. Nous avons rajouté de nombreux tests, que ce soit dans le langage ou en C++, pour pouvoir continuer à garantir le fonctionnement du langage et de son intégration dans des projets en C++ (une interface C est envisagée).

Je me dois également de dire que le macro processor fonctionne depuis que j’avais annoncé son existence. Beaucoup de bugs y ont été trouvé, mais un nouveau développeur nous a rejoint et nous a grandement aidé pour les résoudre, en améliorant la structure du dit macro processor.

Grande nouveauté aussi, l’intégration de fonctions qui travaillent explicitement par référence: append!, concat! et pop! (et leurs équivalents sans !). Ces fonctions sont utilisées pour travailler sur des listes, qui sont autrement copiées autant de fois que nécessaire quand on utilise les versions safe (sans !), qui retournent toutes une nouvelle liste créée à partir de leurs arguments. Les fonctions unsafe (dans le sens "casse l’immutabilité du langage") prennent en argument des références sur objets mutables (donc (append! [1 2] 3) est invalide), modifie leur argument (le premier, les autres peuvent être des copies/références (non) mutables) in place et retourne toujours nil.

Aussi, nous avons fait le grand saut et défini un clang-format pour avoir un code formatté de manière unique, et facilement lisible par toute l’équipe (qui varie entre 4 et 6 personnes qui sont là de manière permanente). La CI a été revue et nous permet maintenant de générer des binaires pour Windows, Linux, et MacOS, sachant qu’un InnoSetup est créé pour les versions Windows désormais.

Notre génération de documentation, ArkDoc a été entièrement recodé en Python et nous permet de sortir plusieurs formats (HTML, Markdown (encore en cours, mais en soit ce n’est pas trop compliqué, si un jour je m’y mets)) : https://arkscript-lang.dev/std/ (qui redirige en théorie vers la dernière version de la documentation).

Ce qui est prévu pour le futur

  • un refactor de la machine virtuelle, pour permettre un ajout plus simple de parallélisme
  • l’élimination d’un side-effect d’une VM à pile : le trashing: (while true 1) va pousser la valeur 1 sur la pile à l’infini et on peut l’empêcher en modifiant notre compilateur mais ça n’est pas trivial
  • améliorer notre REPL (plus de contrôles, accès à la documentation directement)
  • amélioration des erreurs de type pour aider l’utilisateur
  • réécriture du package manager, qui n’a jamais été testé ni utilisé bien qu’il soit considéré comme "fini"

On a encore (et toujours) beaucoup de travail, mais on approche de quelque chose qu’on pourrait considérer comme "fini" (plus dans le sens "complet, qui marche bien" que "terminé" cependant).

Si vous avez des questions sur le langage, une incompréhension, n’hésitez pas à les poster ici ou à rejoindre notre serveur discord.

+2 -0

Hello Zeste de Savoir !

Le projet est toujours vivant, je manquais simplement de contenu pour faire un nouveau post ici.

Entre aujourd’hui et le dernier post, en prenant compte uniquement de la branche de dev, un petit refacto du projet est passé :

  • 88 fichiers modifiés,
  • 3093 lignes ajoutées,
  • 1991 supprimées

J’ai bien précisé la branche de dev, parce qu’une petite nouvelle est apparue, qui vise spécifiquement la prochaine grosse release, ArkScript 4.0 ! Au programme on a :

  • de meilleures erreurs de types (déjà disponibles en 3.1.3),
  • la suggestion de symboles proches quand on tombe sur un unbound symbol pendant la compilation (3.2.0),
  • la conversion de closures en chaine de caractères avec leurs champs,
  • l’ajout d’async/await en tant que builtins,
  • la gestion des unused expressions qui polluaient la stack (dont je parlais dans le précédent post, disponible en 3.2.0),
  • l’optimisation de tail call (3.2.0) quand une fonction s’appelle elle-même (sera généralisé en 4.0),
  • plein de correctifs de petits bugs ennuyeux

On peut voir le travail effectué depuis l’an passé comme du nettoyage et un peu d’house keeping, les vacances étant arrivées pour une partie de l’équipe, le développement ralenti un peu. Cependant on prévoit des améliorations géniales pour le reste de l’année, entre la génération d’un AST sous forme de JSON (utile pour faire un LSP, écrire des tests pour le lexer/parser/optimiseur/macro processeur, pour avoir un nouveau backend qui transpile en WASM ou autre…), du fuzzing pour détecter le plus d’erreurs possibles dans l’implémentation du langage.

La documentation du langage continue d’évoluer et de s’améliorer, si vous avez des remarques, des questions ou mêmes des suggestions n’hésitez pas !

(let size 1000)
(let data (list:fill size 1))  # une liste de remplie de mille 1
(let sum (fun (a b src) {
    (mut acc 0)
    (while (< a b) {
        (set acc (+ acc (@ src a)))
        (set a (+ 1 a))})
    acc
}))


(let workers [
    (async sum 0 (/ size 4) data)
    (async sum (/ size 4) (/ size 2) data)
    (async sum (/ size 2) (- size (/ size 4)) data)
    (async sum (- size (/ size 4)) size data)])

(let res-async
    (list:reduce
        (list:map
            workers
            (fun (w) (await w)))
        (fun (a b) (+ a b))))
proposition de variable et coloration des erreurs
proposition de variable et coloration des erreurs
(let make (fun (a b c)
    (fun (&a &b &c) ())))

(let foo (make 1 2 3))
(print foo)  # output: (.a=1 .b=2 .c=3), avant: Closure<4>
functionName: needs argumentCount argument(s), got actualArgumentCount.
  -> arg1Name (wanted type) was arg1Value (of type arg1Type)
  -> arg2Name (wanted type) was arg2Value (of type arg2Type)
+3 -0

Bonsoir la compagnie !

Depuis le dernier message, j’ai pris du temps pour travailler sur les messages d’erreurs du langage, pour mieux aider les utilisateurs quand une erreur survient, ainsi que plus de warnings à la compilation:


J’ai commencé la chasse aux bugs en intégrant AFL++, un fuzzer très pratique qui m’a remonté pas mal de bouts de code capables de faire planter le lexer, parser, macro processor, rarement le compilateur, et de temps en temps la machine virtuelle. Bref, que de la joie, mon appart est bien chauffé au moins, et j’ai du travail jusqu’à la fin de l’année.

une instance du fuzzer en action
une instance du fuzzer en action

Pour donner quelques chiffres:

  • 6 instances du fuzzer ont tourné, chacune pendant 1 heure
  • le load average est monté à 12 (sur un Xeon à 8 coeurs/16 threads c’est pas mal)
  • l’usage de RAM était capé à 64MB par instance
  • une moyenne de 500 crash remontés par instance
  • une moyenne de 1000 hangs remontés par instance (il est fort pour générer des (while true ()) et similaire)
  • la température CPU qui a grimpé de 45° à 80°, et celle de mon appart de +2° (qui a besoin de chauffage ?)

J’ai dû fixer une petite dizaine de bugs grâce à ça, c’est fastidieux mais très intéressant. En partant des crash remontés, j’ai donc commencé une collection de "code qui plante mais ça doit être détecté".

quelques tests d'échecs
quelques tests d’échecs

Et un test est un couple de deux fichiers:

# input.ark
(())

# input.expected
TypeError: A Nil isn't a callable

Côté avancement sur la v4, j’ai réécrit des bouts du compilateur et nettoyé le code pour le rendre plus simple à lire, et terminé l’intégration du nouveau format de bytecode, où chaque instruction est sur 4 bytes ce qui rend le peeking bien plus facile.

Une nouvelle syntaxe pour les imports est également prévue: nouvelle syntaxe des imports

Les plus attentifs auront remarqué que cette syntaxe va empêcher l’inclusion de scripts de dossiers parents, ce qui était actuellement possible avec un (import "../file.ark"). Je pense que c’est un moindre mal qui poussera à réfléchir un peu plus à la structure d’un projet, mais pour autant ça ne devrait pas être catastrophique.

Cependant, cette nouvelle syntaxe n’est pas figée dans le marbre. Bien que le sens actuel de (import folder.foo.bar) soit "importe folder/foo/bar.ark depuis le dossier du script actuel", il est possible que cela soit réévalué pour suivre les packages à la Scala.

Ainsi, si on exécute main.ark, qui import foo/bar.ark, et que ce dernier veut faire un (import bacon.yellow.color), on chercherait bacon/yellow/color.ark à partir du dossier d’exécution de main.ark et non du dossier où est présent bar.ark.


En dehors de ces améliorations de la QoL, cela fait bientôt deux semaines que je travaille à l’élaboration d’un nouveau parser pour le langage, dont vous pouvez trouver la source sur GitHub: https://github.com/SuperFola/parser-combinators. En effet le lexer/parser actuel est difficilement maintenable, presque impossible à faire évoluer sans casser quelque chose, et sûrement bourré de bugs que je n’ai pas encore trouvé.

C’est pour ça que j’ai tenté une approche parser combinators, et le résultat est là, 2 fois moins de code, 2 fois plus simple à lire, des performances que je considère comme correcte (je dois mesurer le parser actuel pour pouvoir comparer cependant). Pour couronner le tout, 0 warning (Wall, Wextra, Wconversion, Wshadow et pedantic, je suis fou), 0 fuite de mémoire, des tests dans tous les sens et bientôt du fuzzing.

Running ./build/bench
Run on (8 X 24.121 MHz CPU s)
CPU Caches:
  L1 Data 64 KiB
  L1 Instruction 128 KiB
  L2 Unified 4096 KiB (x8)
Load Average: 1.29, 1.69, 1.91
------------------------------------------------------------
Benchmark                  Time             CPU   Iterations
------------------------------------------------------------
Simple - 39 nodes      0.067 ms        0.067 ms       103688
Medium - 83 nodes      0.395 ms        0.395 ms        17430
Big - 665 nodes         31.9 ms         31.8 ms          224

A la prochaine !

+3 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte