ArkScript, un langage de scripting fonctionnel!

a marqué ce sujet comme résolu.
Auteur du sujet

Salut à tous!

Je viens vous présenter mon dernier projet en date (un qui marche cette fois), ArkScript!

Encore et toujours un langage, 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 ça a marché!

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

ArkScript est inspiré de Lisp, 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 !). L’objectif du projet n’est pas d’être plus performant qu’une gazelle avec un moteur à réaction, 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).

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 (ce que je trouve très important pour conserver cet aspect d’immuabilité quand on déclare une variable avec let).

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, faire de l’aléatoire…), 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/).

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)
        # then
        (if (= 0 n)
            # then
            (ackermann (- m 1) 1)
            # else
            (ackermann (- m 1) (ackermann m (- n 1))))
        # else
        (+ 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).

Le github est ici, et le discord du projet ici.

Édité par SuperFola

Python is good | CV | Unamed (C++14/SFML2.5)

+2 -0
Auteur du sujet

Bonsoir !

Depuis le dernier post, beaucoup de changements ont eu lieu, que vous pouvez tous retrouver ici: https://github.com/SuperFola/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
  • une réduction des fonctions standard compile time ! (+ 1 2 3 4) est traité comme (+ 1 (+ 2 (+ 3 4)))
  • 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)
    })
}

Python is good | CV | Unamed (C++14/SFML2.5)

+0 -0
Auteur du sujet

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 oeuvre dans le module HTTP qui permet de faire des requêtes get/put/delete et bien d’autres, mais aussi de mettre en oeuvre des serveurs web (toujours en développement)).

L’ajout d’un dev guide qui va contenir des "PEP like", l’idée n’est pas d’avoir des tutoriels dessus mais des idéaux à suivre, dans l’esprit de la PEP 8. Ce ne sera pas pour améliorer le langage mais améliorer la façon dont le langage est utilisé !

Petit exemple d’usage du module http parce que j’en suis super fier:

{
    (import "http.bin")

    (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 !

Édité par SuperFola

Python is good | CV | Unamed (C++14/SFML2.5)

+1 -0
Auteur du sujet

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), un fork de madureira/String modifié pour le projet (une std::string en plus petit et plus rapide), le code source du site de présentation et de la documentation, et un dev-guide (comparable aux PEP de Python).

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 !

Python is good | CV | Unamed (C++14/SFML2.5)

+0 -0
Auteur du sujet

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 !

Python is good | CV | Unamed (C++14/SFML2.5)

+1 -0
Auteur du sujet

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 !

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

PS: J’ai mis à jour le poste principal avec les dernières informations / modifié des bouts de code

Python is good | CV | Unamed (C++14/SFML2.5)

+1 -0
Auteur du sujet

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

Python is good | CV | Unamed (C++14/SFML2.5)

+0 -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