Вы находитесь на странице: 1из 28

Spécifications Techniques

KOOC
Kooc Project, Kind Of Objective C

Date de rendu 07/26/10


Groupe bertra_b (chef de projet), rouff_a, lucaze_b et lebrun_b.
Modifications (v1.5) 13/07 : Intégration de la version HTML des specs en .odt.
14/07 : Correction des fautes de français et reformulation paragraphes.
15/07 : Revue MIF, Relecture complète avec corrections, ajout abstract.
21/07 : Reformulation des sections « Appel » et « Objectifs ».
24/07 : Ajout des remarques du comité de lecture

KOOC PROJECT™ TECH3S 2010

Ecole d'Informatique EPITECH : Expert en Technologie de l'Information


Kooc Project, Spécifications techniques page 2/28

Résumé
Ce document présentera les spécifications techniques pour le projet du module « Programmation
Orientée Objets » appelé Kooc (Kind Of Objective C). Ce projet a pour but de créer une surcouche
objet au langage C permettant ainsi de comprendre comment sont conçus les langages de
programmation modernes.
Le langage Kooc que nous coderons implémentera les fonctionnalités clés des langages orientés
objets conventionnels. Il sera possible avec ce langage de créer des modules, des classes,
d'instancier des objets et de surcharger des fonctions ou variables. Pour arriver à implémenter ces
fonctionnalités nous nous baserons sur des notions telles que l'encapsulation des données, la
décoration de symboles ou encore la surcharge.
Pour mener à bien ce projet nous utiliserons différents outils dont le logiciel de parsing et de
génération de code source CodeWorker et son jeu de scripts permettant de supporter nativement la
BNF complète du langage C.
Kooc Project, Spécifications techniques page 3/28

Sommaire
1 Objectifs........................................................................................................................................... 4
2 Fonctionnalités................................................................................................................................. 5
L'importation....................................................................................................................................5
L'encapsulation des données............................................................................................................5
La surcharge.....................................................................................................................................6
Les classes et objets......................................................................................................................... 6
L'héritage......................................................................................................................................... 6
3 Outils et techniques utilisés.............................................................................................................. 7
« Extended Backus-Naur Form » ou EBNF.................................................................................... 7
CodeWorker..................................................................................................................................... 7
Le CNorm........................................................................................................................................ 7
Le Cnorm overload et la patchLib................................................................................................... 7
Le Mangling.....................................................................................................................................7
4 Comment utiliser kooc..................................................................................................................... 8
Pré-requis......................................................................................................................................... 8
Compilation..................................................................................................................................... 8
Utilisation du langage...................................................................................................................... 9
Référence............................................................................................................................................ 10
Le Mangling...................................................................................................................................11
Informations retenues pour le Mangling KOOC...................................................................... 11
Implémentation du mangling avec KOOC................................................................................ 11
@import......................................................................................................................................... 13
Utilisation................................................................................................................................. 13
Implémentation......................................................................................................................... 13
@module........................................................................................................................................14
Utilisation................................................................................................................................. 14
Déclaration.......................................................................................................................... 14
Appel.................................................................................................................................... 15
Implémentation......................................................................................................................... 15
Déclaration.......................................................................................................................... 15
Appel.................................................................................................................................... 16
@class............................................................................................................................................ 17
Utilisation................................................................................................................................. 17
Déclaration.......................................................................................................................... 17
Appel.................................................................................................................................... 18
Implémentation......................................................................................................................... 18
Déclaration.......................................................................................................................... 18
Fonctions par défaut............................................................................................................ 20
Appel.................................................................................................................................... 20
@virtual, polymorphisme et héritage............................................................................................ 21
Utilisation ................................................................................................................................ 21
Déclaration ......................................................................................................................... 21
Appel.................................................................................................................................... 21
Implémentation......................................................................................................................... 23
Déclaration ......................................................................................................................... 23
Appel.................................................................................................................................... 26
@implementation...........................................................................................................................27
Utilisation................................................................................................................................. 27
Kooc Project, Spécifications techniques page 4/28

1 Objectifs
Le projet KOOC (Kind Of Objective C) consiste à intégrer de nouvelles fonctionnalités au langage
C en conservant une compatibilité totale avec ce dernier. Les fonctionnalités intégrées seront
similaires à celles utilisées par les langages orientés objets (modules, classes, héritage...). Celles-ci
permettront un développement plus aisé et plus puissant qu'en C.
Le premier objectif du KOOC est avant tout pédagogique. En effet, à l'issue de ce projet nous
comprendrons comment les langages modernes sont conçus et comment ils fonctionnent. Nous
serons donc plus à même de comprendre toutes les subtilités que les langages actuels proposent.
Le projet KOOC sera composé d'un compilateur kooc dont le rôle sera d'analyser des fichiers
sources .kh et .kc contenant des instructions du langage KOOC. Par la suite, il interprètera ces
instructions pour les traduire en langage C pur qui seront contenues dans des fichiers .c et .h.
Enfin, les fichiers C pourront être traduits en binaire par un compilateur conventionnel comme gcc.
Kooc Project, Spécifications techniques page 5/28

2 Fonctionnalités

L'importation
Nous appelons ici importation la capacité du langage permettant d'importer (ou inclure) un fichier
source dans un autre. En C, l'importation est représentée par la directive #include. Le langage
KOOC aura son propre système d'inclusion (noté @import) tout en gardant celui du C utilisable. Il y
a deux raisons qui nous ont poussé à re-développer un système d'inclusion :
• La première raison est que nous utiliserons dans KOOC des fichiers avec l'extension .kh
similaires aux .h du C. Les .kh contiendront du code KOOC non compatible avec le C. Il
ne sera donc pas possible d'utiliser la directive #include.
• La deuxième raison tient au fait que la directive #include ne protège pas contre la double
inclusion. Pour surmonter ce problème les développeurs C doivent entourer leurs inclusions
d'un jeu de macros contraignantes 1. Conscient de ce problème, nous avons décidé que la
directive @import du KOOC fera ce travail à la place du programmeur.
Note : La directive @import permettra d'inclure en plus des .kh les .h en C natif.

L'encapsulation des données


Cette notion est apparue avec les langages orientés objet. Elle permet par exemple, de déclarer à
plusieurs endroits du programme des fonctions ou variables portant le même nom.
Malheureusement en C l'encapsulation des données n'existe pas. Pour pallier ce problème, le
programmeur doit préfixer (ou suffixer) les variables et fonctions correspondant à un sous-ensemble
cohérent de son programme (module etc.). Cette technique permet d'éviter les conflits de noms.
Prenons un cas concret : un développeur C voulant créer des clients et des vendeurs ne pourra pas
faire une fonction create() pour chacun. Il devra créer deux fonctions distinctes, void
client_create() et void vendeur_create().
Avec le langage KOOC il sera possible de déclarer un même nom à deux endroits différents. Pour
cela il dispose d'un système de module représenté par le mot-clef @module. Celui-ci permettra de
regrouper plusieurs déclarations de variables et fonctions dans un espace confiné. Les symboles
déclarés dans un module ne rentreront pas en conflit avec les déclarations extérieures à celui-là.
Afin d'implémenter les fonctions déclarées dans un module, il faudra utiliser le mot-clef
@implementation. Il sera ainsi possible pour le développeur de créer deux fonctions create(),
une appartenant au module client et l'autre au module vendeur.

1 Chaque inclusion doit être entouré des macros suivantes : #ifndef, #define et #endif.
Kooc Project, Spécifications techniques page 6/28

La surcharge
La surcharge est un mécanisme supporté par les langages orientés objets. Ce concept permet d'avoir
deux fonctions nommées de la même manière dans un même espace de noms 2. La seule condition
requise est qu'il y ait au moins un des éléments du prototype qui soit différent en genre ou en
nombre3.
Comme pour l'encapsulation, la surcharge n'est pas supporté par le langage C. Pour reproduire un
mécanisme similaire il faut donc ruser. Le développeur devra faire deux fonctions distinctes, avec
des noms distincts. Reprenons l'exemple avec les clients et les vendeurs et imaginons qu'il soit
possible de créer un client de deux manières : une fonction prenant un entier, l'autre un booléen. Il
faudra créer deux fonctions nommées différemment : void create_client_int(int) et void
create_client_bool(bool). Ceci s'applique également aux types de retour.
Le langage KOOC quant à lui supporte la surcharge, tout comme les langages orientés objets
conventionnels. En effet, dans un même module KOOC, il est possible de créer deux méthodes du
même nom. Il suffit juste qu'au moins un élément du prototype soit différent. Le développeur pourra
donc, au sein du même module, déclarer une fonction void create(int) et void create(bool),
ou encore int create(int).

Les classes et objets


La notion de classes et d'objets est la base des langages de nouvelles générations. Une classe
regroupe un ensemble de variables et de fonctions liées entre elles. Les variables d'une classe sont
des propriétés tandis que ses fonctions sont des méthodes. Une classe n'est pas qu'un simple
conteneur de symboles (fonctions et variables) comme l'est un module en KOOC. Elle apporte de
nombreuses fonctionnalités comme l'héritage, le polymorphisme et bien d'autres.
Dans le langage C, il est possible mais très complexe d'émuler le fonctionnement d'une classe. il est
donc intéressant d'avoir une syntaxe permettant d'abstraire ce mécanisme.
Le langage KOOC permet la déclaration de classe par l'intermédiaire du mot-clé @class. Pour
utiliser une classe l'utilisateur devra créer (allouer) une instance (un objet) de cette dernière. Lors de
l'appel aux méthodes de cette classe, l'instance sera implicitement passée en paramètre. La classe
s'utilise de la même manière que le module excepté pour l'appel.

L'héritage
Le concept d'héritage de classe est implémenté dans tout langage orienté objet digne de ce nom.
Derrière cette notion un peu obscure se présente un concept simple : une classe héritée d'une autre
pourra utiliser toutes les méthodes et attributs publiques ou protégés de cette dernière. Il existe deux
types d'héritages : simple et multiple. L'héritage simple correspondant à la définition donnée plus
haut, quant au multiple il permet à une classe d'hériter de plusieurs autres.
Le système d'héritage en C est en théorie toujours possible mais tellement complexe à émuler qu'il
n'est jamais utilisé pour ça. C'est entre autres pour cette raison qu'aujourd'hui ce langage est délaissé
au profit d'autres plus flexibles et puissants comme le C++ ou le JAVA.
Le langage KOOC que nous proposeront gérera de manière native seulement l'héritage simple. Pour
l'implémenter, KOOC utilisera l'agrégat de structures et la notion de vtables. En savoir plus.

2 Un espace de noms est très utilisé en programmation, cela aide à la construction de programmes modulaires
3 Pour que la surcharge s'applique il faut que le type de retour d'une des deux fonctions soit différent ou bien que le
type ou le nombre de paramètres soient différents.
Kooc Project, Spécifications techniques page 7/28

3 Outils et techniques utilisés

« Extended Backus-Naur Form » ou EBNF


L'Extended Backus-Naur form (EBNF) est une extension du métalangage BNF, créée par Niklaus
Wirth. Cette forme permet de condenser la notation BNF et de la rendre plus lisible.

CodeWorker
CodeWorker est un outil de parsing et un générateur de code disponible sous licence libre. Il est
destiné à couvrir plusieurs aspects de la programmation générative. Cette programmation générative
est une approche de l'ingénierie logicielle pour produire des systèmes informatique réutilisables,
taillés sur mesure, facile à faire évoluer et robustes. Le tout avec un haut niveau d'automatisation.
L'outil interprète un langage de scripts qui pilote les traitements de parsing et de génération de code
dans une syntaxe familière aux développeurs. Il permet la réalisation de DSL (Domain Specific
Language) plus facilement. Il a été conçu pour faire de la génération de code intensive.

Le CNorm
CNorm est une interface C dans CodeWorker pour l'étude de génération de code.

Le Cnorm overload et la patchLib


le Cnorm Overloader est une technique permettant de surcharger les règles utilisées dans le Cnorm.
Cela permet de modifier la construction de l'AST (Abstract Syntax Tree) et ainsi pouvoir étendre le
langage C. Quant à la patchLib, cette librairie permet de facilement manipuler et « patcher » l'AST.

Le Mangling
Le mangling ou en français « décoration de symbole » permet de modifier les noms données aux
fonctions et variables par le compilateur. Cette technique est très utilisé pour implémenter des
fonctionnalités avancées des langages modernes telles que l'encapsulation et la surcharge. Pour plus
d'informations référez-vous au chapitre consacré à ce sujet.
Kooc Project, Spécifications techniques page 8/28

4 Comment utiliser kooc

Pré-requis
Pour fonctionner, le binaire kooc est dépendant de deux composants : Codeworker et Cnorm.
CNorm étant inclus dans kooc, le seul programme à installer est Codeworker. De plus, il est
obligatoire d'ajouter le chemin vers le binaire codeworker et Kooc dans le PATH système. Il sera
aussi nécessaire de définir une variable d'environnement KOOC_PATH. Pour faire cela facilement,
sous Ubuntu, ajoutez les lignes suivantes à votre ~/.bashrc.
Variables d'environnement à ajouter dans le .bashrc
export PATH=$PATH:/your/path/to/codeworker/
export KOOC_PATH=/your/path/to/kooc/
export PATH=$PATH:$KOOC_PATH

Compilation
Le binaire kooc n'est pas un compilateur. Il ne fait que transformer le code KOOC en C pur. Il est
donc indispensable de compiler le C généré avec un compilateur comme gcc. Le binaire kooc ne
fait qu'interpréter et convertir les fichiers .kc en fichier .c et les fichiers .kh en .h. Il ignore les
fichiers possédant une autre extension.

Voici le synopsis du binaire :


$> kooc [ [fichier.kc | fichier.kh] ... ]

Génération de fichiers .c à partir de .kc


$> ls
Kode.kc
$> kooc Kode.kc
$> ls
Kode.c Kode.kc
$> gcc Kode.c -o Kode.bin
$> ls
Kode.bin Kode.c Kode.kc
$> ./Kode.bin

Génération de fichiers .c et .h à partir de .kc et .kh


$> ls
Kode.kc Kode.kh osef.kh toto.kc tutu.kc zz.c
$> kooc *
$> ls
Kode.c Kode.h Kode.kc Kode.kh osef.h osef.kh toto.c toto.kc tutu.c tutu.kc zz.c
$> gcc *.c -o bin
$> ls
bin Kode.c Kode.h Kode.kc Kode.kh osef.h osef.kh toto.c toto.kc tutu.c tutu.kc zz.c
$> ./bin
:)
$>
Kooc Project, Spécifications techniques page 9/28

Pour éviter de retaper une ligne de commande avec beaucoup de fichiers Kooc et de bénéficier de la
compilation partielle il est possible d'utiliser un Makefile comme en C.
Exemple de Makefile gérant la conversion de fichiers KOOC
NAME = import

KHDRS = header1.kh \
header2.kh
# ...

KSRCS = kode1.kc \
kode2.kc
# ...

CHDRS = $(KHDRS:.kh=.h)
CSRCS = $(KSRCS:.kc=.c)

CC = gcc
RM = rm -rf

$(CHDRS) :
kooc $(KHDRS)

$(CSRCS) : $(CHDRS)
kooc $(KSRCS)

$(NAME) : $(CSRCS)
$(CC) $(CSRCS) -o $(NAME)

all : $(NAME)

clean :
$(RM) $(NAME)

fclean : clean
$(RM) $(CSRCS)
$(RM) $(CHDRS)

re : fclean all

Utilisation du langage
Le langage Kooc conserve l'intégralité des fonctionnalités du langage C. Il ne fait que rajouter des
possibilités supplémentaires à ce dernier. Chacune d'elles seront décrites dans la section
« Référence » plus loin dans ce document. Un développeur sachant faire du C saura faire du Kooc.
Kooc Project, Spécifications techniques page 10/28

Référence
Kooc Project, Spécifications techniques page 11/28

Le Mangling
Le mangling (ou décoration de symboles4) est une technique très largement utilisée dans KOOC et
tous les langages orientés objets. Elle se déroule lors de la phase de compilation et consiste à
renommer de manière intelligente une variable ou une fonction. Après qu'un symbole ait été décoré,
il sera possible de trouver directement dans son nom toutes les informations le concernant (type de
retour, paramètres...).
Toutes les fonctionnalités du KOOC utilisent cette technique excepté pour la directive @import.
Afin de pouvoir mettre en pratique les fonctionnalités décrites plus haut, tout en restant valide avec
le langage C, nous ne pourrons pas garder deux symboles create(). Pour contourner ce problème
nous décorerons les symboles lors de leur déclaration. Nous aurons donc besoin d'implémenter une
syntaxe permettant d'appeler ces fonctions décorées.

Informations retenues pour le Mangling KOOC


La directive @import ne nécessite aucune décoration particulière.
En revanche, pour gérer les @module et les @class, nous en aurons besoin. Il faudra donc que le
module (ou la classe) dans lequel une fonction (ou variable) a été déclarée apparaisse dans le nom
de celle-ci. Il faut également garder le nom déclaré par le programmeur.
Ensuite vient la surcharge. Ici, nous devons différencier les fonctions et variables par leurs
paramètres et leur type de retour. Nous aurons donc besoin de toutes ces informations.
Enfin, pour la directive @implementation, le mangling est utilisé mais aucune information
supplémentaire n'est nécessaire. Il reste toutefois une information à ajouter : le type de stockage
dans l'arbre de codeworker (__PROTOTYPE__ ou __VARIABLE__).

Implémentation du mangling avec KOOC


En reprenant les informations ci-dessus, nous avons pu déterminer une forme générique d'un
symbole décoré.
Pour une variable :
Module_VAR_TypeVariable_NomVariable

Pour un prototype:
Module_PRO_TypeRetour_nbParametres_TypeParam1_TypeParam2_NomFonction
Module_PRO_TypeRetour_0_NomFonction
Module_PRO_TypeRetour_1_TypeParam1_NomFonction

Le problème maintenant est de décomposer un type C. Il peut-être composé :


• D'un type système ou défini par l'utilisateur ( int, maStruct…).
• D'un signe (unsigned ou signed).
• De qualifieurs (const, mutable, long...).
• De pointeurs (*), chacun pouvant posséder des modificateurs.
• De tableaux ([]).

On gardera le type de base tel quel. En revanche, pour les qualifieurs et le signe, on prendra les trois
premières lettres avec la première en majuscule.

4 Un symbole en KOOC est principalement composé des variables et fonctions.


Kooc Project, Spécifications techniques page 12/28

const // Con
mutable // Mut
// Exception :
long long // LL

Les tableaux seront représentés pas l'abréviation Tab. Les pointeurs deviendront P. Ces derniers
pouvant posséder des qualifieurs, ceux-ci seront mis juste derrière le P comme illustré ci-dessous :
Exemple de pointeurs avec qualifieurs
* // P
* const // PCon
[]* // TabP
[]* const * mutable // TabPConPMut

Finalement, nous ordonnancerons le type comme ci :


Séquençage des informations concernant le type
Modifieurs_BaseType_TableauxPointeurs

int // Sig_int_
unsigned int // Uns_int_
const char * // ConSig_char_P
mutable const char[] * const * mutable // MutConSig_char_TabPConPMut

Exemples de mangling complets de symboles contenu dans un module Mod


int a; // avant
Mod_VAR_Sig_int__a; // après

unsigned char[]* const b; // avant


Mod_VAR_Uns_char_TabPCon_b; // après

void create(); // avant


void Mod_PRO__void__0_create(); // après

// avant
const long long unsigned int* create(int toto, char[] * const * mutable);
// apres
const long long unsigned int*
Mod_PRO_LLConUns_int_P_2_Sig_int__Sig_char_TabPConPMut_create(int toto, char[] *
const * mutable);
Kooc Project, Spécifications techniques page 13/28

@import

Utilisation
Il est d'usage en C de séparer les déclarations et l'implémentation dans deux fichiers d'extensions
différents : les .h contenant les déclarations et les .c contenant leur implémentation. Ce modèle est
conservé avec KOOC . En effet, il y a des .kh pour les déclarations et les .kc pour leur
implémentation.
Le C propose pour inclure des fichiers .h une directive pré-processeur: #include. Celle-ci ne
permet cependant pas d'inclure un fichier .kh car il comporte du code KOOC. Nous redéfinissons
donc cette fonctionnalité sous la forme du mot-clé @import. Il s'utilise de la même manière que le
#include :
@import "fichier.kh"

De plus, cette directive protège contre la double inclusion. Plus besoin d'utiliser un jeu de macros
autour de chaque include comme en C pour s'en protéger !
$> cat h1.kh
@import "h2.kh"
$> cat h2.kh
@import "h1.kh"
$> kooc h1.kh h2.kh
$>

Note : Le mot-clé @import gère l'inclusion de fichiers .kh mais également de .h.
@import "headerC.h"

Implémentation
En utilisant la technique de l'overload, nous surchargeons la règle translation_unit du Cnorm
afin d'ajouter a la possibilité d'avoir des declaration d'avoir des import. Cet import est défini
dans une règle import dans le fichier import.cwp. Cette dernière vérifie l'existence du fichier à
inclure. Si celui ci n'existe pas, le programme kooc s'arrête et affiche une erreur.
$> error: file 'monFichier.kh' does not exist (fatal)

Ensuite, une vérification sur la double inclusion est effectuée. Pour ce faire nous avons dans notre
AST5, à la racine un node includes contenant tous les noms des fichiers ayant été importés avec
@import. Nous regardons dans ce node si le fichier à inclure s'y trouve déjà. Si c'est le cas, kooc
ignore l'import et continue. Il affichera un avertissement à l'utilisateur.
$> warning: double inclusion or récursive inclusion of file 'monFichier.lh'(ignored)

Dans le cas où le fichier à inclure ne se trouve pas dans les fichiers déjà importés, il est ajouté au
flux de lecture de codeworker (#parsedFile). Il sera alors parsé entièrement. Si une erreur est
rencontrée lors du parsing du fichier à inclure, un message sera affiché en plus de l'erreur KOOC
rencontrée :
$> error: parsing file 'monFichier.kh' failed

5 AST ou Abstract syntax tree en Anglais. L'AST est une représentation en mémoire d'un code source écrit dans un
langage de programmation
Kooc Project, Spécifications techniques page 14/28

@module

Utilisation
Comme annoncé dans les fonctionnalités du langage Kooc, le mot-clef @module permet
d'encapsuler toutes les données déclarées dans ce bloc. Tout ce qui s'y trouve est décoré, ceci
permet donc de déclarer plusieurs symboles portant le même nom dans des modules différents. Avec
la décoration de symboles la surcharge de fonctions au sein d'un même module est également rendu
possible.
Par convention, un module ne doit contenir que des déclarations. L'implémentation des fonctions
sont à faire dans un bloc @implementation.
Une syntaxe particulière est aussi nécessaire pour l'appel de ces fonctions. En effet, le développeur
n'est pas censé connaître comment le langage Kooc décore ses symboles. Il faut donc abstraire cette
notion derrière une syntaxe permettant de récupérer le symbole décoré à partir d'un appel clair.
Cette syntaxe sera décrite dans la partie « Appel » de cette section.

Déclaration
Pour créer un bloc @module, il suffit de déclarer un module de la manière suivante :
Usage @module
@module NomDuModule
{
// Vos déclarations
}

Vous pouvez mettre votre code dans un module sans vous soucier des conflits avec d'éventuelles
fonctions déclarées à l'extérieur. Vous pouvez par ce biais surcharger vos fonctions et variables.
Exemple concret d'utilisation de @module
int var;
float var; // invalide
void function();
void function(int); // invalide

@module MonModule
{
int var; // valide
double var; // valide aussi

void function(); // déjà valide


void function(int); // Toujours valide ...
void function(double); // Encore valide ...
void function(double, int); // valide ...
int function(); // woo .. encore valide
maStruct function(monType); // Vous pouvez aussi utiliser des types perso :)
}

Attention: Vous ne pouvez pas déclarer un module dans un module.


Kooc Project, Spécifications techniques page 15/28

Appel
Il existe deux manières d'appeler une méthode déclarée dans un module. La première qui est peu
pratique pour le développeur consiste à appeler la fonction sous sa forme décorée. La seconde
propose au développeur, d'utiliser lors de l'appel de la fonction une écriture simplifiée qui est un
alias de la version décorée.
Appel de la fonction en utilisant sa forme décorée
MonModule_PRO__void__0_function();

Appel de symboles en utilisant leur forme simplifié


// Variable:
[NomDuModule NomDeLaVariable]
// Fonction:
[NomDuModule NomDeLaFonction :param1 :param2]

En reprenant le module MonModule déclaré précédemment nous pouvons rencontrer certaines


ambiguïtés. En effet, si l'on appelle [MonModule var], Le compilateur kooc ne saura pas si il doit
choisir la variable de type int ou double. Pour guider son choix, le langage KOOC rajoute la
syntaxe @!(Type) pour préciser le type désiré.
Exemple d'utilisation de @!(type)
// Reprise de la déclaration de module MonModule
[MonModule var] // Ambiguïté
@!(int)[MonModule var] // int var
@!(double)[MonModule var] // double var

[MonModule function] // void function()


@!(int)[MonModule function] // int function()
[MonModule var] = [MonModule function] // int var = int function()
@!(void)[MonModule function] // void function()
int a = @!(void)[MonModule function] // erreur !

[MonModule function :var] // Ambiguïté


[MonModule function :@!(int)var] // void function(int)
[MonModule function :@!(double)var] // void function(double)

Implémentation

Déclaration
L'implémentation du système de modules est similaire à celui de l'inclusion de fichiers. En effet, la
règle translation_unit de CNorm est surchargé en y ajoutant la règle module qui est
implémentée dans module.cwp.
Cette règle est uniquement composées de multiples declaration du CNorm. Pour chaque
déclaration, le script va appeler la fonction mangleNode définie dans mangler.cws. mangleNode ne
prend en paramètre que des nodes __VARIABLE__ ou __PROTOTYPE__. La fonction analysera le
node puis renommera le name du node donné dans tout l'AST par le résultat décoré.
Kooc Project, Spécifications techniques page 16/28

Appel
Afin de pouvoir appeler les variables et fonctions déclarées dans un module depuis n'importe quel
bloc de code, nous devons surcharger trois règles du Cnorm :
• La règle unary_expression permettant de parser la partie gauche d'une expression.
• La règle postfix_expression permettant de parser la partie droite.
• Enfin la règle assignment_expression. Elle sera utilisée dans le cas ou l'une des deux
règles précédentes détecte une fonction. Elle servira à parser les paramètres de celle-ci.
Pour chacune de ces règles, sera rajoutée la possibilité d'avoir un appel KOOC @!(...) [ … ] .
Celui-ci permettra de spécifier le type de retour du symbole. Dans ce cas, nous remplaçons cette
syntaxe par la décoration correspondant à cet appel si le module et le symbole existent bien. En cas
d'ambiguïté de type, KOOC génèrera une erreur.
Appels de module KOOC
// Variable:
@!(int)[MonModule var] = 10;

// Fonction:
[MonModule function];

unsigned char* param = NULL;


int a = @!(int)[MonModule function :param :@!(double)[MonModule var]];

Transformation en C
// Variable:
MonModule_VAR_Sig_int__var = 10;

// Fonction:
MonModule_PRO__void__0_function();

unsigned char* param = NULL;


int a = MonModule_PRO_Sig_int__2_Uns_char_P_Sig_double__function(
param, MonModule_VAR_Sig_double__var
);
Kooc Project, Spécifications techniques page 17/28

@class

Utilisation

Déclaration
Le mot-clef @class est similaire au mot-clef @module et s'utilise de la même manière, comme en
témoigne l'exemple ci-dessous.
Déclaration d'une classe avec Kooc
@class MaClasse
{
int var;
void maFonction();
}

La classe reprend toutes les caractéristiques d'un module tout en l'améliorant. Par exemple, dans un
bloc @class il est possible de déclarer des fonctions et variables membres. Ces dernières ne seront
utilisables qu'en précisant une instance d'un objet (créée en appelant la fonction new de la classe).
Cette instance sera accessible dans une fonction membre grâce au mot-clef self, qui représente un
pointeur sur l'objet appelant. Pour ce faire, il suffit de préfixer la déclaration par le mot-clé
@member. Ce dernier peut-être utilisé comme un bloc pour faire plusieurs déclarations.
Utilisation du mot-clé @member en mode bloc et inline
@class MaClasse
{
int var; // variable non membre
void function(); // fonction non membre

@member int var; // variable membre


@member void function(); // fonction membre

@member
{
double toto; // variable membre
int tutu(double a); // fonction membre
}
}

Important : Contrairement à un bloc, une classe possède des fonctions (membre ou non) par
défaut. Elles permettront la création et la suppression d'une instance de cette classe.
Liste des fonctions réservées par Kooc pour la gestion des instances
- Object* alloc() // alloue la mémoire nécessaire pour contenir l'objet
- Object* new() // constructeur par défaut
- @member void init() // initialiseur par défaut
- @member void clean() // nettoyeur par défaut
- @member void delete() // destructeur par défaut

Note : Pour implémenter une classe, vous devez utiliser un bloc @implementation. Cette notion est
expliqué dans la section suivante.
Kooc Project, Spécifications techniques page 18/28

Appel
Les méthodes non membres d'une classe sont comme les méthodes des modules. L'appel se passe de
la même manière.
Appel de variables et de fonctions non membres avec Kooc
// Variables:
[MaClasse MaVariable]
// Fonctions:
[MaClasse MaFonction :param1 :param2]

Pour les méthodes membres, en revanche, une instance de l'objet est demandée. Il faut donc à la
place du nom de la classe, mettre le nom de l'objet. Cet objet doit être valide, c'est à dire alloué et
initialisé. Pour ce faire, un appel a new ou init suffit.
Appel d'attributs et de méthodes d'instance avec Kooc
MaClasse* pObjet = [MaClasse new];

MaClasse objet;
[objet init];

// Variables
[pObjet maVariableMembre];
[&objet maVariableMembre]

// Fonctions
[pObjet maFonctionMembre :param1 :param2];
[&objet maFonctionMembre :param1 :param2];

Appel des attributs et méthodes de la classe MaClass déclarée précédemment


int main()
{
MaClasse* obj;

[MaClasse var] = 42; // variable non membre


[MaClasse function]; // fonction non membre

[obj var] = 42; // invalide: obj n'a pas été initialisé

[obj new]; // initialisation de obj


[obj var] = 42; // variable membre
[obj var] = [obj tutu :4.2]; // variable membre - fonction membre
[obj var] = [obj tutu :[obj toto]]; // variable membre - fonction membre -
// variable membre
}

Implémentation

Déclaration
L'implémentation du système de classe est très similaire à celui des modules. Effectivement, la règle
translation_unit est surchargée en y ajoutant la règle class implémentée dans le fichier
class.cwp. La règle class est composée d'une surcharge de declaration. Ceci permet de parser
soit une déclaration seule ou precedee d'un @member, soit dans un bloc @member.

Dans le cas où le binaire kooc rencontre une déclaration seule elle sera décorée de la même
manière que pour une déclaration dans un module. Dans le cas d'une declaration précédée du mot-
clé @member, ou dans un bloc @member, un ajout sera fait lors de la décoration comme expliqué à la
page suivante.
Kooc Project, Spécifications techniques page 19/28

Variables membres

Toutes les variables membres seront contenues dans une structure C (portant le nom de la classe):
@class A
{
int a;

@member
{
int a;
int* a;
}
}

Résultat après conversion de la classe en C


int A_VAR_Sig_int__a;

typedef struct
{
int A_VAR_Sig_int__a;
int A_VAR_Sig_int_P_a;
} A;

Fonctions membres
Nous avons précisé tout à l'heure que les fonctions membres s'appelaient avec un pointeur sur une
instance de la classe, qui sera accessible au sein de la fonction. Cette instance est donc passée en
premier paramètre de notre fonction de manière implicite lors de la décoration, avec pour nom
self.
Déclaration d'une classe avec deux fonctions membres
@class A
{
void function();

@member
{
void function();
int* tata(int a, double b);
}
}

Résultat après conversion de la classe en C.


typedef struct
{

} A;

void A_PRO__void__0_function();
void A_PRO__void__1__A_P_function(A* self);
int* A_PRO_Sig_int_P_3__A_P_Sig_int__Sig_double__tata(A* self, int a, double b);
Kooc Project, Spécifications techniques page 20/28

Fonctions par défaut


alloc // cette méthode alloue la mémoire nécessaire pour la structure de
l'instance :
@member init // constructeur par défaut.
new // fait un appel consécutif a alloc, puis a init
@member clean // nettoyeur par défaut
@member delete //destructeur, appel clean, puis free sur l'instance appelante.

Exemple de cycle de vie d'un objet en KOOC.


Module* obj = [Module new];
// OU
// Module *obj = [Module alloc];
// [obj init];

[obj delete];

Résultat après conversion en C.


Module* obj = malloc(sizeof(Module));
Module_PRO__void__1__Module_P_init(obj);

Module_PRO__void__1__Module_P_clean(obj);
free(obj);

Appel
Pour l'appel d'une classe, les règles qui auront été surchargées pour le gestion d'appel d'un module
seront reprises et complétées. En effet, comme cela a été décrit précédemment, une classe n'est rien
d'autre qu'un module un peu particulier. Pour avoir un appel de classe complet, il faudra ajouter à la
gestion des modules, celle des appels pour les variables et fonctions membres.

La gestion d'appel de classe sera faite de la manière suivante :

• Dans le cas où le premier paramètre de l'appel correspond à un module existant, l'appel sera
traité comme un appel de module.

• Dans le cas où le premier paramètre est un pointeur sur instance d'une classe existante, et
que la fonction appelée est bien membre de la classe. Elle sera remplacé par son équivalent
décorée.
Kooc Project, Spécifications techniques page 21/28

@virtual, polymorphisme et héritage

Utilisation

Déclaration
La notion d'héritage est matérialisée en KOOC par une notation simple, comme en témoigne
l'exemple ci-dessous.
Déclaration d'un héritage simple
@class Animal
{
@member int nb_legs;
@virtual void says();
}

@class Cat : Animal


{
@member int nb_griffes;
@member void says();
@member void test();
}

@class Dog : Animal


{
// @member avec {} permet de déclarer plusieurs membres à la suite.
@member {
int nb_griffes;
void says();
}
}

Avec cette notation les classes Cat et Dog pourront utiliser toutes les variables et fonctions
(protégées et publiques) de Animal. Dans les classes Cat et Dog la méthode says() initialement
déclarée dans Animal sera redéfinie. Ceci est rendu possible grâce au mot-clé KOOC @virtual. Ce
mécanisme permettra d'exploiter la notion de polymorphisme.

Appel
Avec l'implémentation de l'héritage, les classes KOOC se verront dotées de 2 nouveaux mots-clés
utilisables à l'intérieur de celles-ci : self et super. self symbolise l'instance en cours, il sera donc
possible d'accéder à ses propres variables et fonctions membres. Quant au mot-clé super il ne sera
disponible que dans une classe héritant d'une ou plusieurs autres. Avec ce mot-clé il donc possible
d'accéder aux propriétés et méthodes de la classe héritée.
Différents types d'appels possible à partir d'une méthode de la classe Cat
[self.nb_griffes] = 3 // affectation de la variable membre nb_griffes de Cat
[self says] // Appel de la fonction membre redéfinie says de Cat
[super says] // Appel de la fonction membre says de la classe Animal
[super.nb_legs] // Appel de la variable membre nb_legs de Animal

Sur la page suivante sera présentée l'implémentation complète des classes Animal, Cat et Dog.
Kooc Project, Spécifications techniques page 22/28

Implémentation de la classe Animal


@implementation Animal
{
void init()
{
[self.nb_legs] = 0;
}

void says()
{
printf(« Cri animal : »);
}
}

Implémentation de la classe Cat


@implementation Cat
{
void init()
{
[self.nb_legs] = 4;
[self.nb_griffes] = 6;
}

void says()
{
[super says]
printf(« Miaou Miaou »);
}
}

Implémentation de la classe Dog


@implementation Dog
{
void init()
{
[self.nb_legs] = 4;
[self.nb_griffes] = 3;
}

void says()
{
[super says]
printf(« Ouaf Ouaf »);
}
}
Kooc Project, Spécifications techniques page 23/28

Implémentation

Déclaration
Afin de pouvoir gérer le polymorphisme, nous devons faire intervenir une nouvelle notion : la
vtable. Il s'agit d'un pointeur void qui est placé au tout début de la structure représentant la classe
contenant des membres virtuels. Celui-ci pointera sur une structure supplémentaire, en dehors de la
classe, qui contiendra un pointeur sur fonction pour chaque fonction membre virtuelle.
Ce pointeur n'apparaitra que dans le cas ou la classe contient au moins une fonction membre
virtuelle.
Nous ajouterons dans la règle class du fichier class,cwp la gestion du mot-clé @virtual. Pour
chaque prototype déclare dans un bloc (ou inline) @virtual, nous devrons appliquer les même
règles que pour les membre, puis :
1. Créer la structure définissant la vtable nommée _VTABLE_NomDeLaClasse si elle n'existe
pas.
2. Rajouter dans cette structure le pointeur sur fonction vers la fonction crée par les règles du
membre.
3. Rajouter un pointeur void au début de la structure définissant la classe si il n'existe pas
encore.
4. Ajouter dans la fonction membre générée new l'initialisation de ce pointeur vers la bonne
vtable.
Voyons un exemple concret avec son implémentation en KOOC et sa traduction en C. Il est présenté
sur la page suivante.
Kooc Project, Spécifications techniques page 24/28

Création de classes Animal et Chien en KOOC


@class Animal
{

@member {
/* … */
}
@virtual void says();
}

@class Chien : Animal


{
@member {
/* … */
}
@virtual void says();
@virtual void sit();
}

Equivalent en C pur du code généré à partir du KOOC


typedef struct
{
void (*says)();
} _VTABLE_Animal;

typedef struct
{
void (*says)();
void (*sit)();
} _VTABLE_Chien;

typedef struct
{
_VTVABLE_Animal* vtable;
/* ... */
} Animal;

typedef struct
{
_VTABLE_Chien* vtable;
/* ... */
} Chien;

_VTABLE_Animal vtableAnimal = {Animal_PRO__void__0_says};


_VTABLE_Chien vtableChien = {Chien_PRO__void__0_says, Chien_PRO__void__0_sit};
Kooc Project, Spécifications techniques page 25/28

… Suite traduction en C
Animal__Animal_P_0_new()
{
Animal* instance = malloc(sizeof(Animal));
Animal__Animal_P_0_init(instance);
instance.vtable = &vtableAnimal;
return (instance);
}

Animal__Animal_P_0_delete(Animal* self)
{
free(self->vtable);
}

Chien__Chien_P_0_new()
{
Chien* instance = malloc(sizeof(Chien));
Chien__Chien_P_0_init(instance);
instance.vtable = &vtableChien;
return (instance);
}

Chien__Chien_P_0_delete(Chien* self)
{
free(self->vtable);
}

/* autres methode auto-generee inchangee */


Kooc Project, Spécifications techniques page 26/28

Appel
Pour l'appel des fonctions membres virtuelles, nous devons donc passer par la vtable.
En reprenant l'exemple précèdent:
Programme KOOC
int main()
{
Animal* a = [Animal new];
Chien* c = [Chien new];

[a says]; // says() de la classe Animal


[c says]; // says() de la classe Chien

Animal* b = (Animal*) c;
[b says]; // says() de la classe Chien

[a sit]; // invalid
[c sit]; // ok
[b sit]; // ok ;)
}

Programme kooc traduit en C


int main()
{
Animal* a = Animal__Animal_P_0_new();
Chien* c = Chien__Chien_P_0_new();

a->vtable->says();
c->vtable->says();

Animal* b = (Animal*) c;
b->vtable->says();

a->vtable->sit(); // arf
b->vtable->sit(); // ok
c->vtable->sit(); // ok
}
Kooc Project, Spécifications techniques page 27/28

@implementation

Utilisation
Le mot-clé @implementation sert à implémenter les fonctions déclarées dans les @module et les
@classe. Il s'utilise de manière simple et intuitive comme en témoigne les exemples ci-dessous.
Déclaration d'un module A
@module A
{
int a;
double a;
char b;

void function();
char function()
int getA();
double getA();
}

Implémentation du module A
@import "moduleA.kh"
@implementation A
{
void function()
{
// do something
}

char function()
{
return [A b];
}

int getA()
{
return @!(int)[A a] * [a function];
}

double getA()
{
return @!(double)[A a];
}
}
Kooc Project, Spécifications techniques page 28/28

Déclaration d'une classe B


@class B
{
int var; // variable non membre
void function(); // fonction non membre

@member int var; // variable membre


@member void function(); // fonction membre

@member
{
double toto; // variable membre
int tutu(double a); // fonction membre
int toto(); // fonction membre
}
}

Implémentation de la classe B
@import "classB.kh"

@implementation B
{
void function()
{
// do something
}

@member void function()


{
// do something else
}

@member
{
int tutu(double a)
{
// do something with a
return 1;
}

int toto()
{
return 0;
}
}
}

Pour implémenter les symboles présents dans une déclaration .kh, il suffit de déclarer un bloc
@implementation du même nom que le module ou la classe à implémenter. Définissez vos
fonctions avec leur prototype non décorés, le mangling se fera automatiquement.

Implémentation
La mise en place du mot-clé @implementation dans le langage Kooc est similaire aux trois autres
présentés précédemment. Effectivement, la règle translation_unit sera surchargée en y ajoutant
la règle implémentation définie dans le fichier implementation.cwp. Comme pour les règles
module et class, celle-ci n'est composée que de déclarations ou de @member. Ainsi, chaque
déclaration sera décorée, membre ou non, de la même manière que dans la déclaration du module
ou de la classe.

Вам также может понравиться