Bonjour, Habr! Depuis plusieurs semaines, je développe mon langage de programmation Rust. J'aimerais parler de ce à quoi peut faire face un novice dans ce domaine et ce qu'il devrait savoir.
Bref historique
Tout a commencé avec un fork de ein , je l'ai forké afin d'apprendre comment les langages de programmation sont construits. Étant donné que ein est interprété de et vers, sa vitesse d'exécution n'était pas la plus élevée et après avoir commencé à comprendre quelque chose, j'ai décidé de commencer à écrire mon propre interprète, qui a finalement abandonné.
Mais il est trop tôt pour désespérer! J'ai lu quelques articles sur VM et ce qu'ils sont et j'ai décidé d'écrire une machine virtuelle empilée simple.
Qu'est-ce qu'une "machine virtuelle empilée" et comment fonctionne-t-elle?
Le habr il y a un autre article à ce sujet, mais pour ne pas conduire sur des liens, je vais expliquer brièvement le sens de cette petite chose.
La pile VM effectue toutes les opérations sur les données qui sont stockées sous la forme d'une pile, chaque opération récupère la quantité nécessaire de données pour l'opération et après exécution, elle peut "envoyer" un nouveau numéro à la pile.
Pour commencer
Vous devez d'abord créer un nouveau projet en utilisant cargo:
cargo new habr_vm
Tout d'abord, nous devons créer des opérations de base pour notre machine virtuelle:
enum Opcode { Push(i32), Add, AddAssign(i32), Sub, SubAssign(i32), }
Ce sont nos opérations de base, la commande Push ajoutera un nouveau numéro à la pile, Ajouter et Sub prendra deux numéros de la pile et effectuera des actions avec eux (addition et soustraction, respectivement), je n'ai pas besoin d'expliquer AddAssign et SubAssign.
La tâche suivante consiste à créer la machine virtuelle elle-même, pour cela nous allons créer une structure pas compliquée:
struct Vm { pub stack: Vec<i32>, }
Et nous l'implémentons:
impl Vm {
Nous avons mis en place notre structure, et ensuite? Ensuite, nous devons créer notre "programme".
Voici à quoi cela devrait ressembler:
let program = vec![ Opcode::Push(2),
C'est simple, non? Si oui, alors exécutons notre programme!
let mut vm = Vm {stack: Vec::new()}; vm.run(program);
C'est très simple pour moi, vous pouvez donc ajouter suffisamment d'opcodes pour l'opération dont vous avez besoin.
Conclusion
Je pense que j'ai expliqué assez clairement comment écrire tout cela sur un rast et comment cela fonctionne.
Je voudrais ajouter que vous pouvez facilement écrire votre propre PJ grâce à une machine virtuelle similaire, vous n'avez qu'à écrire un analyseur, un lexer et un "compilateur", et si vous voulez regarder un projet prêt à l'emploi, vous pouvez suivre ce lien .
Tout le code de l'article est disponible dans ce référentiel.
Bonne chance Habr!