Skip to content

1. Implantation (fr)

Claude Roux edited this page Oct 16, 2019 · 12 revisions

Introduction

English Version

Le document suivant décrit comment le code Tamgu (탐구) a été implémenté. Ce document s'adresse à toute personne souhaitant découvrir les principes de fonctionnement internes de l'interprète. Bien que la lecture de ce document puisse éclairer sur les choix d'implantation de Tamgu, il n'est pas obligatoire de le lire pour pouvoir utiliser le langage.

Organisation du code

L'interprète d'un langage informatique est généralement divisé en trois parties :

  • Construction de l'arbre syntaxique à partir du code. Cette opération est aussi appelée "parsing".
  • Compilation du code qui transforme l'arbre syntaxique en une structure exécutable
  • Exécution du code

L'analyseur : codeparse

La construction de l'arbre syntaxique se fait à l'aide de la classe : bnf_tamgu dont le code est stocké dans les fichiers : codeparse.cxx et codeparse.h.

Avertissement : Ces deux fichiers n'ont pas été écrits à la main mais ont été générés automatiquement à partir du fichier tamgu dans le répertoire : bnf. Le répertoire bnf contient également des scripts en Python pour régénérer de nouvelles versions de codeparse si nécessaire.

La description du langage BNF utilisée est écrite dans le fichier tamgu lui-même.

Nœuds : x_node.h

Ce fichier contient les classes pour sauvegarder l'arbre syntaxique : x_node.

Un x_node contient son nom (token), sa valeur (value), sa position dans le texte initial (start, end) et ses nœuds fils.

Les x_node sont produits par codeparse.

Segmentation

D'autre part, la structure d'entrée de codeparse est le résultat d'une segmentation. Le fichier contient la classe x_rules et ses dérivations x_reading et x_wreading. La classe x_rules permet l'enregistrement et l'utilisation de règles de segmentation.

Ces règles de segmentation divisent le code d'entrée en tokens tout en maintenant leur position dans le fichier et leur identité telle que définie par une règle comme :

rules.push_back("%d+(.%d+(.%d+)(e([- +])%d+)=3") ;

Cette règle permet de reconnaître entre autres un nombre à exposant. Lorsqu'un tel token est identifié, le code "3" est renvoyé, qui identifie la nature de ce token comme un nombre. On peut alors se référer à ce code dans la grammaire de la BNF pour générer le nœud correct correspondant :

# Les nombres tels qu'analysés par le segmenteur : "3" est le code fourni par le segmenteur.
^3 anumber := .

Par défaut, ces règles reconnaissent directement les chaînes de caractères entre guillemets ou séparateurs tels que ";",",":".

# ponctuation  provenant du segmenteur
^0 punct := .

# Définitions des chaînes de caractères  provenant du segmenteur
^1 astringdouble : = .
^2 astringsimple : = .
^5 afullstring : = .

# Nombre provenant du segmenteur
^3 anumber := .

# token provenant du segmenteur
^4 mot := = . = .
^4 typename := .
^4 astring := .

# expressions régulières. Dans certains cas, le code est un caractère simple.
^9 atreg := .
^a astreg : = .
^b apreg : = .
^c aspreg : = .

Le compilateur : codecompile

Une fois que l'arbre syntaxique est correctement construit, il est transmis au compilateur. Le compilateur est implémenté en tant que classe : TamguCode qui contient tout ce dont vous avez besoin pour parcourir l'arbre syntaxique et construire les représentations internes.

Choix d'une méthode de compilation

La classe TamguGlobal contient un dictionnaire spécial qui associe un nom de token à une méthode de compilation TamguCode : parseFunctions. La méthode RecordCompileFunctions enregistre toutes ces méthodes dans ce dictionnaire.

La méthode principale lors de la compilation de l'arbre syntaxique est : Traverse.

Cette méthode comprend deux paramètres : le nœud courant dans l'arbre syntaxique et l'objet à construire.

Cette méthode examine le noeud courant et vérifie si son token est associé à une méthode de compilation. Si ce n'est pas le cas, il examine les nœuds fils : Un token peut ne pas être associé à une méthode.

Lorsqu'une méthode de compilation est choisie, elle enrichit l'objet courant avec les informations nécessaires en analysant le noeud courant et ses sous-noeuds.

TamguGlobal

L'interpréteur Tamgu ne contient presque pas de variables globales à une exception près : globalTamgu de type TamguGlobal.

La classe TamguGlobal vous permet de centraliser la création des objets pour effectuer leur destruction. Tamgu n'inclut pas de "ramasse-mémoire" en tant que tel, mais garde une trace des objets dont l'interprète peut avoir besoin pendant l'exécution. Par exemple, toutes les instructions sont stockées dans le vecteur tracked.

Cette classe garde également la trace des threads et gère leur création ou leur suppression. TamguGlobal gère également la pile de variables.

Objet

Chaque structure de données est une classe indépendante dérivée de TamguReference, enregistrée dans leur propre fichier. Chaque objet expose au moins les méthodes suivantes :

  • Les deux méthodes suivantes sont utilisées pour enregistrer les méthodes associées à un objet. En particulier, InitializationModule est appelé au démarrage pour enregistrer tous les objets de base et leurs méthodes. La méthode AddMethod permet d'associer un nom de méthode côté Tamgu à une méthode de la classe correspondante.
static void AddMethod(TamguGlobal* g, string name, objectMethod func, unsigned long arity, string infos) ;
bool static InitializationModule(TamguGlobal* g, string version) ;
  • Les deux méthodes suivantes sont utilisées pour retourner ou modifier la valeur d'un objet
Tamgu* Eval(Contexte Tamgu*, valeur Tamgu*, idthread court) ; 
Tamgu* Put(Contexte Tamgu*, valeur Tamgu*, idthread court) ; 
  • Les méthodes suivantes sont utilisées pour retourner les valeurs atomiques :
long Integer() ;
string String() ;
etc.
  • Les méthodes suivantes sont utilisées pour comparer les valeurs entre elles
Tamgu* lessequal(Tamgu*)
Tamgu* moreequal(Tamgu*)
Tamgu* same(Tamgu*)
Tamgu* different(Tamgu*)
  • Les méthodes suivantes sont utilisées pour effectuer des opérations avec d'autres valeurs
Tamgu* minus(Tamgu*)
Tamgu* plus(Tamgu*)
Tamgu* multiple(Tamgu*)
Tamgu* divide(Tamgu*)
etc.

Template

Le répertoire template vous permet de créer vos propres objets et bibliothèques. Il suffit de donner le nom de votre objet au script et il génère automatiquement un répertoire dans lequel il place les fichiers source et include ainsi que les Makefiles. Tout ce que vous avez à faire est de remplir ces modèles avec votre propre code.

Clone this wiki locally