Accueil Ti-Gen Foire Aux Questions Chat sur le chan #tigcc sur IRC
Liste des membres Rechercher Aide
Bienvenue Invité !   Se connecter             Mes sujets   
Administrer
0 membre(s) et 1 visiteur(s) actif(s) durant les 5 dernières minutes Utilisateurs actifs : Aucun membre + 1 visiteur
Avant de poster sur le forum, il y a des régles de bases à respecter pour une bonne entente et un respect de tous.
Veuillez lire la charte du forum.
  :: Index » Forum Ti68K » Programmation C » Orienté objet avec TIGCC (113 réponse(s))
./REPRISE DU POST PRECEDENT (post n°19)   Marquer comme non lu.
Quésoft Ecrit le: Lundi 16 octobre 2006 à 22:52 Déconnecté(e)    Voir le profil de Quésoft Envoyer un email à Quésoft Visiter le site WEB de Quésoft Envoyer un message privé à Quésoft  

Kevin Kofler :
Je ne vois pas trop l'intérêt d'un truc comme ça par rapport à un vrai frontend GCC, par exemple un portage de g++ et/ou GCJ. (Cela dit, je suis contre ce genre de portages aussi, je trouve que la programmation objet n'a rien à faire sur une calculatrice.)


Entre autre, un préprocesseur représente moins de travail et surtout, un simple support des classes sera moins lourd qu'une implémentation du C++ (d'où pourquoi un programme Moka ne pard pas à 5Ko). En plus, ce nouveau préprocesseur, comme je le conçoit, ne produira que de l'ANSI C et ne sera pas dépendant d'un API pour fonctionner (ceci dit, développer un API pour faciliter la prog 68K ne sera pas inintéressant). Ainsi, ce même préprocesseur servira indiscriminament aux programmeurs C sur PC ou sur TI.

J'ai une question technique:

Dans le modèle OO de Moka, les pointeurs vers les fonctions sont gardés avec les attributs de l'objets, donc chaque objet en a une copie. C'est mauvais pour l'empreinte mémoire, mais c'est assez rapide (une déréférenciation au lieu de 2 pour une table séparée).

Pour les interface (qui induisent une gestion des méthodes analogue à celle de l'héritage multiple), j'ai dut employer une autre technique: chaque signature de méthode a un vecteur qui pointe vers les fonctions e.g.


int (**int_count_) (TObject*); //La syntaxe est à vérifier, ça faut un bout que je n'ai pas touché au C

int_count_[reference_de_l_objet->id](reference_de_l_objet)//code d'une invocation


id est un numéro séquentiel identifiant uniquement chaque classe.

Qu'est-ce que l'on devrait utiliser pour notre minijava ? La technique originale de Moka, celle du C++ (l'objet en mémoire garde un pointeur vers une table de pointeurs) ou celle du FMI (celle des interfaces en Moka) ?

Moi, j'irais pour celle du FMI.
-Edité le Lundi 16 octobre 2006 à 23:18 par Quésoft-
    
./Post n°20   Marquer comme non lu.
Kevin Kofler Ecrit le: Mardi 17 octobre 2006 à 11:42 Déconnecté(e)    Voir le profil de Kevin Kofler Envoyer un email à Kevin Kofler Visiter le site WEB de Kevin Kofler Envoyer un message privé à Kevin Kofler  


Quésoft :
Entre autre, un préprocesseur représente moins de travail

C'est bien ça le problème, c'est une solution de facilité. La bonne manière de compiler un nouveau langage est de faire un frontend GCC, pas un préprocesseur, et pas un compilateur à part entière non plus.

et surtout, un simple support des classes sera moins lourd qu'une implémentation du C++

Je ne dis pas que porter g++ est nécessairement la meilleure solution, il se peut bien que rajouter 2-3 trucs au frontend C et en faire un nouveau frontend soit une meilleure idée. Mais ça risque aussi de représenter une charge de travail plus élevée.

Ainsi, ce même préprocesseur servira indiscriminament aux programmeurs C sur PC ou sur TI.

Ce serait la même chose pour un frontend GCC, à moins que tu ne mettes des trucs spécifiques à la TI dans le frontend, mais ce genre de trucs n'ont rien à faire dans le frontend de toute façon. (GCC suit le modèle du traducteur universel: le frontend ne s'occupe que du langage, le backend ne s'occupe que de la machine. Bien sûr, c'est théorique, et en pratique ce n'est pas réalisé à 100%, mais c'est quand-même le concept à garder en tête.)

J'ai une question technique: [...]

En gros, toutes tes méthodes sont virtuelles, comme en Java, et ta question pose sur le système exact de vtables à utiliser (une vtable par instance ou une par classe avec un pointeur dessus dans l'instance). Je pencherais sur la vtable par classe, c'est sans doûte moins gourmand en RAM, mais je pense qu'il est beaucoup plus important de gérer les méthodes non-virtuelles. Un appel de méthode virtuel a toujours un overhead, de plus le linker est obligé de garder la vtable entière dans l'exécutable linké, y compris toutes les fonctions listées dedans. C'est pour ça que les exécutables Moka prennent des KO dès que tu actives l'instantiation d'objets. Une méthode non-virtuelle est remplacée directement en temps de compilation par un appel de fonction C, par exemple:
Foo toto;
toto->bar(123);

sera traduit en:
Foo toto;
Foo_bar(toto,123);

avec:
void Foo_bar(Foo *this, int baz);

Et avec ça, plus besoin de se traîner toutes les méthodes non utilisées de la classe Foo.
Membre de l'équipe de TIGCC: http://tigcc.ticalc.org
Mainteneur du portage Linux/Unix de TIGCC: http://tigcc.ticalc.org/linux/
Membre de l'équipe de CalcForge: http://www.calcforge.org:70/

Participez à la reprise de Ti-Gen!
    
./Post n°21   Marquer comme non lu.
Quésoft Ecrit le: Mardi 17 octobre 2006 à 14:43 Déconnecté(e)    Voir le profil de Quésoft Envoyer un email à Quésoft Visiter le site WEB de Quésoft Envoyer un message privé à Quésoft  

Kevin Kofler :
Quésoft :
Entre autre, un préprocesseur représente moins de travail

C'est bien ça le problème, c'est une solution de facilité. La bonne manière de compiler un nouveau langage est de faire un frontend GCC, pas un préprocesseur, et pas un compilateur à part entière non plus.


Ce n'est pas de la lâcheté ... en fait si, mais de la lâcheté justifiable: c'est plutôt d'éviter de faire un overkill. Un préprocesseur pourra en plus travailler avec n'importe quel compilateur, en plus.

Kevin Kofler :
et surtout, un simple support des classes sera moins lourd qu'une implémentation du C++

Je ne dis pas que porter g++ est nécessairement la meilleure solution, il se peut bien que rajouter 2-3 trucs au frontend C et en faire un nouveau frontend soit une meilleure idée. Mais ça risque aussi de représenter une charge de travail plus élevée.


Trafiquer le frontend et forquer TIGCC serait un cauchemar de maintenance, selon moi.

Kevin Kofler :
Ainsi, ce même préprocesseur servira indiscriminament aux programmeurs C sur PC ou sur TI.

Ce serait la même chose pour un frontend GCC, à moins que tu ne mettes des trucs spécifiques à la TI dans le frontend, mais ce genre de trucs n'ont rien à faire dans le frontend de toute façon. (GCC suit le modèle du traducteur universel: le frontend ne s'occupe que du langage, le backend ne s'occupe que de la machine. Bien sûr, c'est théorique, et en pratique ce n'est pas réalisé à 100%, mais c'est quand-même le concept à garder en tête.)


Je sais comment est conçus la GCC (même si ce n'est qu'en théorie, n'ayant jamais développé de front end ou de back end). Par contre, un frontend est beaucoup plus lourd comme solution qu'un préprocesseur. En plus, un préprocesseur fonctionnera avec pas mal n'importe quel SDK, comme mentionné plus haut.

Kevin Kofler :
J'ai une question technique: [...]

En gros, toutes tes méthodes sont virtuelles, comme en Java, et ta question pose sur le système exact de vtables à utiliser (une vtable par instance ou une par classe avec un pointeur dessus dans l'instance).


Toutes les méthodes seront virtuelles. Personnelement, un mot clef comme 'virtual' (C#) me semble incohérent avec le paradigme OO. Par contre, le préprocesseur devra résoudre les invocation de méthode par un appel statique de fonction lorsque cela est possible (voir plus bas).

Kevin Kofler :
Je pencherais sur la vtable par classe, c'est sans doûte moins gourmand en RAM, mais je pense qu'il est beaucoup plus important de gérer les méthodes non-virtuelles. Un appel de méthode virtuel a toujours un overhead, de plus le linker est obligé de garder la vtable entière dans l'exécutable linké, y compris toutes les fonctions listées dedans. C'est pour ça que les exécutables Moka prennent des KO dès que tu actives l'instantiation d'objets. Une méthode non-virtuelle est remplacée directement en temps de compilation par un appel de fonction C, par exemple:
Foo toto;
toto->bar(123);

sera traduit en:
Foo toto;
Foo_bar(toto,123);

avec:
void Foo_bar(Foo *this, int baz);

Et avec ça, plus besoin de se traîner toutes les méthodes non utilisées de la classe Foo.

Je parlais uniquement pour les cas où seul un appel dynamique est nécessaire style:

o.toString(); //où il n'est pas possible de déterminer statiquement la classe de o, parce qu'une sous classe de la classe de o est instanciée à quelque part et que cette dernière redéfinie toString.


Effectivement, dans les cas où le préprocesseur peut identifier la bonne fonction à invoquer, pas de tracas avec le virtuel (e.g. o est un Toto et toto n'a pas de sous classe définissant la méthode toString)... Moka n'optimisait pas cela, même si les méthodes dont l'invocation était impossible étaient retirées, alors en gardant en tête l'optimisation lors de la conception j'arriverai à de bien meilleurs résultats.

En bref, l'avantage d'un préprocesseur est qu'il ne fera qu'ajouter des fonctionnalités au SDK du programmeur, au lieu de devoir être constamment modernisé pour pouvoir bénéficier des dernières nouveautés.

Cela ne fera que simplifier la vie au programmeur.

Ceci:

public class Toto {
  public int i;
}

void _main() {
  Toto t = new Toto();

  //faire quelque chose style t.i = 3;

  delete t;
}


Ne prendra pas plus d'octets que cela:


typedef struct {
  int i;
} Toto;

void _main() {
  Toto t = malloc(sizeof(Toto));

  //faire quelque chose style t->i = 3;

  free(t);
}


Car voici la conversion:


//Déclaration des structures
struct Toto;

//Structures
struct Toto {
  //Le classid n'est pas là, car aucun code n'en a de besoin (pas de instanceof, pas d'invocation  dynamique de méthode)
  //Attributs de la superclasse de toto
  //Attributs de la classe Toto
  int i;//public int i;
};

typedef struct Toto* TToto;

void _main() {
  TToto t = (TToto)malloc(sizeof(Toto)); //Toto ne définit pas de constructeur, allocation directe

  //faire quelque chose style t->i = 3; //Assez strat forward dans le cas de l'accès à un attribut

  free(t);//Toto, ni aucune de ses sous classes, ne définit de destructeur, désallocation directe
}

-Edité le Mardi 17 octobre 2006 à 14:47 par Quésoft-
    
./Post n°22   Marquer comme non lu.
Kevin Kofler Ecrit le: Mardi 17 octobre 2006 à 16:54 Déconnecté(e)    Voir le profil de Kevin Kofler Envoyer un email à Kevin Kofler Visiter le site WEB de Kevin Kofler Envoyer un message privé à Kevin Kofler  


Quésoft :
Ce n'est pas de la lâcheté ... en fait si, mais de la lâcheté justifiable: c'est plutôt d'éviter de faire un overkill. Un préprocesseur pourra en plus travailler avec n'importe quel compilateur, en plus.

"éviter de faire un overkill" est toujours l'excuse qui mène aux solutions de facilité.

Trafiquer le frontend et forquer TIGCC serait un cauchemar de maintenance, selon moi.

Si tu as besoin de modifs au backend, je veux bien merger ça dans TIGCC si les modifs sont raisonnables (le critère n°1 de "raisonnables" étant: les programmes C ne sont soit pas affectés, soit ça améliore TIGCC aussi pour le C). Donc déjà tu n'aurais que le frontend à maintenir séparément. Et ensuite, on pourrait discuter un arrangement pour distribuer ça avec TIGCC, mais il faut bien être conscient que si je mets à jour GCC et que ton frontend ne compile plus, ce sera ta responsabilité de le mettre à jour. Si tu n'es pas là pour mettre à jour le frontend et que les modifs pour le mettre à jour ne sont pas triviales, il dégage bien sûr. (En gros, je propose de coopérer au lieu de travailler chacun dans son coin, mais il faut vraiment que ce soit de la coopération, pas que je reçoive une contribution de type fire and forget et que ce soit à moi de la garder à jour.)

En plus, un préprocesseur fonctionnera avec pas mal n'importe quel SDK, comme mentionné plus haut.

Et l'intérêt? GCC tourne partout, même pour Window$, et bien sûr pour tous les OS *nix-like et plein d'OS exotiques.

Toutes les méthodes seront virtuelles. Personnelement, un mot clef comme 'virtual' (C#) me semble incohérent avec le paradigme OO. Par contre, le préprocesseur devra résoudre les invocation de méthode par un appel statique de fonction lorsque cela est possible (voir plus bas).

Le problème est qu'il y a plein de cas où une méthode peut être non-virtuelle, mais ce n'est pas facilement détectable automatiquement. Tu as donné des conditions suffisantes pour qu'on puisse faire l'optimisation automatiquement, mais ces conditions sont très loin d'être nécessaires. Il faut être réaliste et tenir compte de la plateforme visée. Tu veux que ce soit utilisable pour une calculatrice, alors il faut que l'overhead soit raisonnable pour une calculatrice! Les méthodes non-virtuelles sont essentielles pour ça. Si le C++ (et comme tu dis aussi le C#) permettent les méthodes non-virtuelles, c'est pour une raison!

Je pense que cette mentalité Java (tout est virtuel, sauf s'il est prouvable qu'une méthode non-virtuelle ait la même sémantique dans cette situation particulière) est une des raisons principales pour lesquelles Moka produit des exécutables énormes (totalement inacceptables) dès qu'on active les fonctionnalités OO. (Mais ce n'est peut-être pas la seule. Je suis très sceptique en ce qui concerne l'OO sur les calculatrices en général, cf. aussi l'entrée dans la FAQ de TIGCC rédigée par Zeljko.)

Effectivement, dans les cas où le préprocesseur peut identifier la bonne fonction à invoquer, pas de tracas avec le virtuel (e.g. o est un Toto et toto n'a pas de sous classe définissant la méthode toString)...

Mais en général, il ne pourra pas. Les méthodes virtuelles ne servant que quand on a besoin d'une forme particulière de polymorphisme, ce n'est pas normal que ce soit le comportement par défaut et que c'est au préprocesseur ou frontend de prouver que ce n'est pas nécessaire dans ce cas particulier.

En bref, l'avantage d'un préprocesseur est qu'il ne fera qu'ajouter des fonctionnalités au SDK du programmeur, au lieu de devoir être constamment modernisé pour pouvoir bénéficier des dernières nouveautés.

Mais le désavantage est que ce préprocesseur est "stupide" et ne connaît qu'une partie du langage visé! Si tu préprocesses un fichier C + extensions OO sans avoir une grammaire C complète, tu te retrouveras forcément avec un truc peu fiable, qui fera n'importe quoi dans certains cas particuliers. Pense par exemple à:
"??/" ; class Foo {}; /* " /* */

Si tu compiles ça avec -ftrigraphs, alors ce sera interprété comme:
"\" ; class Foo {}; /* "

Si tu compiles sans cette option, c'est:
"??/" ; class Foo {};

Donc le préprocesseur doit savoir si le compilateur lit les trigraphs ou pas pour savoir s'il doit transformer la classe ou pas! Il y a plein d'autres détails de la grammaire du C qu'un simple préprocesseur risque de ne pas comprendre.

Ce sera également difficile de donner des messages d'erreur convenables si l'utilisateur fait une bêtise vu que tu ne connais pas le contexte complet.

Ceci:

public class Toto {
  public int i;
}

void _main() {
  Toto t = new Toto();

  //faire quelque chose style t.i = 3;

  delete t;
}


Ne prendra pas plus d'octets que cela:


typedef struct {
  int i;
} Toto;

void _main() {
  Toto t = malloc(sizeof(Toto));

  //faire quelque chose style t->i = 3;

  free(t);
}


Car voici la conversion:


//Déclaration des structures
struct Toto;

//Structures
struct Toto {
  //Le classid n'est pas là, car aucun code n'en a de besoin (pas de instanceof, pas d'invocation  dynamique de méthode)
  //Attributs de la superclasse de toto
  //Attributs de la classe Toto
  int i;//public int i;
};

typedef struct Toto* TToto;

void _main() {
  TToto t = (TToto)malloc(sizeof(Toto)); //Toto ne définit pas de constructeur, allocation directe

  //faire quelque chose style t->i = 3; //Assez strat forward dans le cas de l'accès à un attribut

  free(t);//Toto, ni aucune de ses sous classes, ne définit de destructeur, désallocation directe
}

Vu comme ça, je dois dire que je ne vois pas trop l'intérêt du tout. Si tout ce que tu veux préprocesser, c'est ça, alors autant écrire directement en C ce qu'on entend!

De plus, tout ça prendra plus d'octets que ça:
void _main(void) {
 Toto t;
 t.i = 3;
}

Donc faut que ton préprocesseur gère aussi les objets sur la pile pour que ce soit convenable. Soit avec une syntaxe séparée, soit avec une optimisation appelée "escape analysis", mais bonne chance pour faire ça dans un simple préprocesseur! Il faut un frontend à part entière pour faire de l'escape analysis, GCJ recevra ça bientôt (ça a été implémenté pendant le Google Summer of Code).
-Edité le Mardi 17 octobre 2006 à 16:59 par Kevin Kofler-
Membre de l'équipe de TIGCC: http://tigcc.ticalc.org
Mainteneur du portage Linux/Unix de TIGCC: http://tigcc.ticalc.org/linux/
Membre de l'équipe de CalcForge: http://www.calcforge.org:70/

Participez à la reprise de Ti-Gen!
    
./Post n°23   Marquer comme non lu.
Kevin Kofler Ecrit le: Mardi 17 octobre 2006 à 16:59 Déconnecté(e)    Voir le profil de Kevin Kofler Envoyer un email à Kevin Kofler Visiter le site WEB de Kevin Kofler Envoyer un message privé à Kevin Kofler  


Au passage, le dernier code peut être scalarisé par GCC 4 en:
void _main(void) {
  int SRA_t_i;
  SRA_t_i=3;
}

et du coup l'entier peut même être dans un registre! (Bien sûr, dans ce cas, il n'est pas utilisé, donc _main sera totalement vide après optimisation, mais admettons que t.i soit utilisé, alors ce sera dans un registre.) Donc on gagne énormément par rapport à du malloc si tu permets des objets locaux (sur la pile / dans un registre).
Membre de l'équipe de TIGCC: http://tigcc.ticalc.org
Mainteneur du portage Linux/Unix de TIGCC: http://tigcc.ticalc.org/linux/
Membre de l'équipe de CalcForge: http://www.calcforge.org:70/

Participez à la reprise de Ti-Gen!
    
./Post n°24   Marquer comme non lu.
Jfg Ecrit le: Mardi 17 octobre 2006 à 18:21 Déconnecté(e)    Voir le profil de Jfg Envoyer un email à Jfg Visiter le site WEB de Jfg Envoyer un message privé à Jfg  


(Voici pour moi les features vitaux, je vous laisse débattre de comment les implémenter:
-Heritage pas multiple (comme en Java)
-Interfaces
-Constructeurs/destructeurs
-Methodes virtuelles

le reste ca sert a rien.)
Kill Mario
    
./Post n°25   Marquer comme non lu.
Quésoft Ecrit le: Mardi 17 octobre 2006 à 18:22 Déconnecté(e)    Voir le profil de Quésoft Envoyer un email à Quésoft Visiter le site WEB de Quésoft Envoyer un message privé à Quésoft  

Kevin Kofler :
"éviter de faire un overkill" est toujours l'excuse qui mène aux solutions de facilité.


La solution de facilité est de ne pas se casser la tête à trouver une solution efficiente pour faciliter l'utilisation des types de donnée abstraits (ADT).

Kevin Kofler :
Si tu as besoin de modifs au backend, je veux bien merger ça dans TIGCC si les modifs sont raisonnables (le critère n°1 de "raisonnables" étant: les programmes C ne sont soit pas affectés, soit ça améliore TIGCC aussi pour le C). Donc déjà tu n'aurais que le frontend à maintenir séparément. Et ensuite, on pourrait discuter un arrangement pour distribuer ça avec TIGCC, mais il faut bien être conscient que si je mets à jour GCC et que ton frontend ne compile plus, ce sera ta responsabilité de le mettre à jour. Si tu n'es pas là pour mettre à jour le frontend et que les modifs pour le mettre à jour ne sont pas triviales, il dégage bien sûr. (En gros, je propose de coopérer au lieu de travailler chacun dans son coin, mais il faut vraiment que ce soit de la coopération, pas que je reçoive une contribution de type fire and forget et que ce soit à moi de la garder à jour.)


Faire un tel front end serait une solution. Je vais regarder ça. Je supporse que des fonctions pour le parsing et la gestion de collections sont déjà présentes dans le SDK de GCC ?

Kevin Kofler :
Et l'intérêt? GCC tourne partout, même pour Window$, et bien sûr pour tous les OS *nix-like et plein d'OS exotiques.


Je sais bien, mais quelque chose de très léger pourra être utilisé même sur d'autres plate-formes embarquées qui n'ont pas de port GCC. En plus, faire un front end pour tous les port de GCC représente pas mal de travail...

Kevin Kofler :
Le problème est qu'il y a plein de cas où une méthode peut être non-virtuelle, mais ce n'est pas facilement détectable automatiquement. Tu as donné des conditions suffisantes pour qu'on puisse faire l'optimisation automatiquement, mais ces conditions sont très loin d'être nécessaires. Il faut être réaliste et tenir compte de la plateforme visée. Tu veux que ce soit utilisable pour une calculatrice, alors il faut que l'overhead soit raisonnable pour une calculatrice! Les méthodes non-virtuelles sont essentielles pour ça. Si le C++ (et comme tu dis aussi le C#) permettent les méthodes non-virtuelles, c'est pour une raison!

Je pense que cette mentalité Java (tout est virtuel, sauf s'il est prouvable qu'une méthode non-virtuelle ait la même sémantique dans cette situation particulière) est une des raisons principales pour lesquelles Moka produit des exécutables énormes (totalement inacceptables) dès qu'on active les fonctionnalités OO. (Mais ce n'est peut-être pas la seule. Je suis très sceptique en ce qui concerne l'OO sur les calculatrices en général, cf. aussi l'entrée dans la FAQ de TIGCC rédigée par Zeljko.)


Votre point est légitime. Par contre, je pense, qu'au risque de blesser l'esthétique, le défaut devrait être virtuel et que l'on pourrait permettre de spécifier une méthode comme 'nonvirtual' (encore là, le but est de faire convivial, et on s'en éloigne en introduisant ce genre de choses). En OO, c'est juste logique qu'une methode puis-ce être overidée. Et de ce que je sais, les programmes Java ne sont-ils pas plus performant que le .NET ?

Kevin Kofler :
Mais en général, il ne pourra pas. Les méthodes virtuelles ne servant que quand on a besoin d'une forme particulière de polymorphisme, ce n'est pas normal que ce soit le comportement par défaut et que c'est au préprocesseur ou frontend de prouver que ce n'est pas nécessaire dans ce cas particulier.


Je ne suis pas sûr que la majorité des cas ne pourront pas être aisément optimisés. D'expérience, les instances sont le plus souvent 'précisément typés' et cela fait que l'on peut aisément identifier les méthodes à invoquer.

Kevin Kofler :
Mais le désavantage est que ce préprocesseur est "stupide" et ne connaît qu'une partie du langage visé! Si tu préprocesses un fichier C + extensions OO sans avoir une grammaire C complète, tu te retrouveras forcément avec un truc peu fiable, qui fera n'importe quoi dans certains cas particuliers. Pense par exemple à:
"??/" ; class Foo {}; /* " /* */

Si tu compiles ça avec -ftrigraphs, alors ce sera interprété comme:
"\" ; class Foo {}; /* "

Si tu compiles sans cette option, c'est:
"??/" ; class Foo {};

Donc le préprocesseur doit savoir si le compilateur lit les trigraphs ou pas pour savoir s'il doit transformer la classe ou pas! Il y a plein d'autres détails de la grammaire du C qu'un simple préprocesseur risque de ne pas comprendre.


Là, je reconnais que c'est tout à fait vrai. Je vais devoir parser le C pour être en mesure de gérer le contexte (c'est ce que Moka fait lorsqu'il optimise: il identifie les séquences utilisant le modèle OO dans le code C généré). Et si je fais ça, ça ne sera pas parfait (à moins que je parse touts les .h inclus, etc.)

Kevin Kofler :
Ce sera également difficile de donner des messages d'erreur convenables si l'utilisateur fait une bêtise vu que tu ne connais pas le contexte complet.


Encore une fois, c'est vrai. Par contre, vu que ce ne sera qu'un préprocesseur et que le code restera du C, les erreurs seront facile à localiser qu'elles soient dans le code objet (message du préprocesseur) ou dans le code C (message de TIGCC).

Kevin Kofler :
Vu comme ça, je dois dire que je ne vois pas trop l'intérêt du tout.Si tout ce que tu veux préprocesser, c'est ça, alors autant écrire directement en C ce qu'on entend!


Ce n'étais évidemment qu'un exemple très simple (sans méthode, héritage, etc.) Le support de la programmation OO est un plus intéressant, mais le but est de faciliter l'utilisation des ADT en C (qui sont fastidieux à utiliser à la base, et horriblement fastidieux à utiliser lorsque l'on introduit des techniques pour émuler le polymorphisme et compagnie), au bout du compte.

C'est sûr que l'on peut pas mal tout coder en C, ou en assembler.

Kevin Kofler :
De plus, tout ça prendra plus d'octets que ça:
void _main(void) {
 Toto t;
 t.i = 3;
}

Donc faut que ton préprocesseur gère aussi les objets sur la pile pour que ce soit convenable. Soit avec une syntaxe séparée, soit avec une optimisation appelée "escape analysis", mais bonne chance pour faire ça dans un simple préprocesseur! Il faut un frontend à part entière pour faire de l'escape analysis, GCJ recevra ça bientôt (ça a été implémenté pendant le Google Summer of Code).

Au passage, le dernier code peut être scalarisé par GCC 4 en:
void _main(void) {
  int SRA_t_i;
  SRA_t_i=3;
}

et du coup l'entier peut même être dans un registre! (Bien sûr, dans ce cas, il n'est pas utilisé, donc _main sera totalement vide après optimisation, mais admettons que t.i soit utilisé, alors ce sera dans un registre.) Donc on gagne énormément par rapport à du malloc si tu permets des objets locaux (sur la pile / dans un registre).


Des objets gérés automatiquement (comme en C) est effectivement quelque chose d'utile - en particulier lorsque l'on songe à de telles optimisations. Reste à trouver une syntaxe élégante. Aussi, déterminer quand 'finaliser' un objet peut causer des tracas (e.g. appel d'une fonction au millieu de la méthode qui contient un exit() - statiquement, il y a plein de cas comme celui-ci à penser).
    
./Post n°26   Marquer comme non lu.
geogeo Ecrit le: Mardi 17 octobre 2006 à 18:23 Déconnecté(e)    Voir le profil de geogeo Envoyer un email à geogeo Visiter le site WEB de geogeo Envoyer un message privé à geogeo  


Les templates. :)
En découle les foncteurs.
Et enfin la surchage d'opérateurs et le polymorphisme. ^^ (on en demande de trop :D)
-Edité le Mardi 17 octobre 2006 à 18:24 par geogeo-
Webmaster du site.
Programmeur sur TI68K. Arkanoid, Nebulus, GFA-Basic.

Plus d'informations sur GFA-Basic (un langage Basic pour TI68K).
http://www.tigen.org/gfabasic
    
./Post n°27   Marquer comme non lu.
Quésoft Ecrit le: Mardi 17 octobre 2006 à 18:27 Déconnecté(e)    Voir le profil de Quésoft Envoyer un email à Quésoft Visiter le site WEB de Quésoft Envoyer un message privé à Quésoft  

Jfg :
(Voici pour moi les features vitaux, je vous laisse débattre de comment les implémenter:
-Heritage pas multiple (comme en Java)
-Interfaces
-Constructeurs/destructeurs
-Methodes virtuelles

le reste ca sert a rien.)


Moka supporte tout ça (il y a même l'interface Serializable, même si elle n'est pas aussi hot qu'en java). Le nouveau préprocesseur le fairait de façon plus clean, plus conviviale (syntaxe objet directement dans le code c, le préprocesseur regénère le fichier C avec le stuff converti) et -surtout- bien mieux optimisée. Les packages d'API, optionnels, seront fournis par des third parties (je n'exclu pas d'en programmer peut-être).
    
./Post n°28   Marquer comme non lu.
Quésoft Ecrit le: Mardi 17 octobre 2006 à 18:29 Déconnecté(e)    Voir le profil de Quésoft Envoyer un email à Quésoft Visiter le site WEB de Quésoft Envoyer un message privé à Quésoft  

geogeo :
Les templates. :)
En découle les foncteurs.
Et enfin la surchage d'opérateurs et le polymorphisme. ^^ (on en demande de trop :D)
-Edité le Mardi 17 octobre 2006 à 18:24 par geogeo-


Sans polymorphisme, pas vraiment d'OO dans mon livre :) Moka le supporte parfaitement, d'ailleurs.

Pour la surcharge des ops, c'est quelque chose que je veux aussi ajouter, ainsi que des 'pseudo classes' pour les types non objets (concept que je vous parlerai lorsque je serai rendu là).

Templates et foncteurs, j'ai rien compte, mais c'est pas quelque chose auquel j'ai pensé pour l'instant.
    
./Post n°29   Marquer comme non lu.
Kevin Kofler Ecrit le: Mardi 17 octobre 2006 à 19:20 Déconnecté(e)    Voir le profil de Kevin Kofler Envoyer un email à Kevin Kofler Visiter le site WEB de Kevin Kofler Envoyer un message privé à Kevin Kofler  


Quésoft :
Ce n'étais évidemment qu'un exemple très simple (sans méthode, héritage, etc.) Le support de la programmation OO est un plus intéressant, mais le but est de faciliter l'utilisation des ADT en C (qui sont fastidieux à utiliser à la base, et horriblement fastidieux à utiliser lorsque l'on introduit des techniques pour émuler le polymorphisme et compagnie), au bout du compte.

Pour moi, la meilleure manière de gérer le polymorphisme est toujours:
switch (object->type) {
  case TYPE_FOO:
    ...
    break;
  case TYPE_BAR:
    ...
    break;
  case TYPE_BAZ:
    ...
    break;
  default:
    ER_throw(ER_ARGUMENT);
};

C'est moins tordu et souvent aussi plus efficace que la solution avec les pointeurs de fonctions réalisée par le polymorphisme objet (méthodes virtuelles).

Des objets gérés automatiquement (comme en C) est effectivement quelque chose d'utile - en particulier lorsque l'on songe à de telles optimisations. Reste à trouver une syntaxe élégante.

Ben, la syntaxe du C++, tout simplement. :)

Aussi, déterminer quand 'finaliser' un objet peut causer des tracas (e.g. appel d'une fonction au millieu de la méthode qui contient un exit() - statiquement, il y a plein de cas comme celui-ci à penser).

C'est clair que pour un simple préprocesseur, c'est le bordel... Un frontend, lui, s'en sort assez facilement, g++ fait ça très bien, par exemple.
Membre de l'équipe de TIGCC: http://tigcc.ticalc.org
Mainteneur du portage Linux/Unix de TIGCC: http://tigcc.ticalc.org/linux/
Membre de l'équipe de CalcForge: http://www.calcforge.org:70/

Participez à la reprise de Ti-Gen!
    
./Post n°30   Marquer comme non lu.
geogeo Ecrit le: Mardi 17 octobre 2006 à 20:13 Déconnecté(e)    Voir le profil de geogeo Envoyer un email à geogeo Visiter le site WEB de geogeo Envoyer un message privé à geogeo  


Kevin Kofler :
Pour moi, la meilleure manière de gérer le polymorphisme est toujours:
switch (object->type) {
  case TYPE_FOO:
    ...
    break;
  case TYPE_BAR:
    ...
    break;
  case TYPE_BAZ:
    ...
    break;
  default:
    ER_throw(ER_ARGUMENT);
};

C'est moins tordu et souvent aussi plus efficace que la solution avec les pointeurs de fonctions réalisée par le polymorphisme objet (méthodes virtuelles).


Tu dis ça à mon prof, il va te tuer. ^^
Webmaster du site.
Programmeur sur TI68K. Arkanoid, Nebulus, GFA-Basic.

Plus d'informations sur GFA-Basic (un langage Basic pour TI68K).
http://www.tigen.org/gfabasic
    
./Post n°31   Marquer comme non lu.
Quésoft Ecrit le: Mardi 17 octobre 2006 à 21:00 Déconnecté(e)    Voir le profil de Quésoft Envoyer un email à Quésoft Visiter le site WEB de Quésoft Envoyer un message privé à Quésoft  

Kevin Kofler :
C'est moins tordu et souvent aussi plus efficace que la solution avec les pointeurs de fonctions réalisée par le polymorphisme objet (méthodes virtuelles).


Le polymorphisme du paradigme OO est beaucoup plus élégant, moins fastidieux à programmer et beaucoup plus simple à maintenir. Les switches ne permettent pas de faire dans le générique: il ne reste qu'à émuler le polymorphisme OO avec des pointeurs sur des fonctions, ce qui n'est pas plus efficace que ce qu'un 'moka optimisé' pourrait faire.

Kevin Kofler :
Ben, la syntaxe du C++, tout simplement. :)


Je trouve la syntaxe du C élégante (à la base, lorsqu'il n'y a pas des millions de macros et des tonnes de ces extensions GNU), mais le code C++ est tout simplement laid... donc pas la meilleure référence. Préférence personnelle, je suppose.

Kevin Kofler :
C'est clair que pour un simple préprocesseur, c'est le bordel... Un frontend, lui, s'en sort assez facilement, g++ fait ça très bien, par exemple.


C'est ce qui me rend l'idée d'un frontend attrayante.
    
./Post n°32   Marquer comme non lu.
Quésoft Ecrit le: Mardi 17 octobre 2006 à 21:02 Déconnecté(e)    Voir le profil de Quésoft Envoyer un email à Quésoft Visiter le site WEB de Quésoft Envoyer un message privé à Quésoft  

geogeo :

Tu dis ça à mon prof, il va te tuer. ^^


J'ai à retoucher un programme codé comme ça, et je repard from scratch ;)

(j'exagère un peu, bien sur :P)
    
./Post n°33   Marquer comme non lu.
Kevin Kofler Ecrit le: Mardi 17 octobre 2006 à 22:55 Déconnecté(e)    Voir le profil de Kevin Kofler Envoyer un email à Kevin Kofler Visiter le site WEB de Kevin Kofler Envoyer un message privé à Kevin Kofler  


Quésoft :
Le polymorphisme du paradigme OO est beaucoup plus élégant, moins fastidieux à programmer et beaucoup plus simple à maintenir.

Ça dépend de si on pense de manière procédurale ou objet. Les switches sont typiquement procédural, on regroupe par fonction, la même tâche est codée au même endroit. Les méthodes virtuelles, en revanche, regroupent par objet. Personnellement, je pense de manière très procédurale quand je programme.

Les switches ne permettent pas de faire dans le générique

Si on rajoute un type, on le rajoute à tous les switches. En échange, rajouter une fonction est très simple (on rajoute une fonction et c'est tout), alors qu'avec les méthodes virtuelles, on risque d'être obligé de rajouter une méthode à chaque classe. Donc dans les 2 cas, on a un sens dans lequel l'extensibilité est facile et un autre dans lequel c'est la galère. La structure procédurale permet de rajouter des fonctions facilement, la structure objet permet de rajouter des classes facilement.

Le procédural n'est peut-être plus à la mode, mais c'est quand-même un paradigme qui peut être utile, tout comme ceux qui ne sont pas et n'ont jamais été à la mode (fonctionnel, logique etc.).

Je trouve la syntaxe du C élégante (à la base, lorsqu'il n'y a pas des millions de macros et des tonnes de ces extensions GNU), mais le code C++ est tout simplement laid... donc pas la meilleure référence. Préférence personnelle, je suppose.

Le C++ peut être très illisible effectivement (surtout avec les templates), mais là je parle de la syntaxe C++ pour un objet local, qui est tout simplement:
MaClasse mon_objet;

On ne peut plus simple. :)

Quésoft :
J'ai à retoucher un programme codé comme ça [switch(object->type)], et je repard from scratch ;)

(j'exagère un peu, bien sur :P)

Hmmm, tu vas galérer pour faire un frontend GCC alors, parce que tout GCC fonctionne comme ça.
Membre de l'équipe de TIGCC: http://tigcc.ticalc.org
Mainteneur du portage Linux/Unix de TIGCC: http://tigcc.ticalc.org/linux/
Membre de l'équipe de CalcForge: http://www.calcforge.org:70/

Participez à la reprise de Ti-Gen!
    
./Post n°34   Marquer comme non lu.
geogeo Ecrit le: Mardi 17 octobre 2006 à 23:21 Déconnecté(e)    Voir le profil de geogeo Envoyer un email à geogeo Visiter le site WEB de geogeo Envoyer un message privé à geogeo  


Toute façon il est clair que certains programmes sont plus lisibles et plus faciles à coder avec un langage OO alors que dans d'autres cas c'est le contraire. Il appartient au programmeur de choisir le bon langage et les bons outils pour développer son application. Il n'y a pas de meilleur langage de programmation comparé à un autre.
Mais c'est vrai que sur nos TI on est limité et que donc le C est plus interessant que du C++. Le C++ ne ferait qu'alourdir le programme pour faire exactement la même chose qu'en C avec peu de chose près le même nomber de lignes.
Webmaster du site.
Programmeur sur TI68K. Arkanoid, Nebulus, GFA-Basic.

Plus d'informations sur GFA-Basic (un langage Basic pour TI68K).
http://www.tigen.org/gfabasic
    
./Post n°35   Marquer comme non lu.
Quésoft Ecrit le: Mardi 17 octobre 2006 à 23:23 Déconnecté(e)    Voir le profil de Quésoft Envoyer un email à Quésoft Visiter le site WEB de Quésoft Envoyer un message privé à Quésoft  

C'est pourquoi quelque chose de léger et d'optimisé est préférable (éviter un overkill).
-Edité le Mardi 17 octobre 2006 à 23:23 par Quésoft-
    
./Post n°36   Marquer comme non lu.
Kevin Kofler Ecrit le: Mercredi 18 octobre 2006 à 09:49 Déconnecté(e)    Voir le profil de Kevin Kofler Envoyer un email à Kevin Kofler Visiter le site WEB de Kevin Kofler Envoyer un message privé à Kevin Kofler  


Le problème est que toi, tu as l'air de viser un convertisseur léger, ce qui est très différent d'avoir une sortie (exécutables produits) légère. (Cf. par exemple le problème des objets sur la pile ou dans des registres.)
Membre de l'équipe de TIGCC: http://tigcc.ticalc.org
Mainteneur du portage Linux/Unix de TIGCC: http://tigcc.ticalc.org/linux/
Membre de l'équipe de CalcForge: http://www.calcforge.org:70/

Participez à la reprise de Ti-Gen!
    
./Post n°37   Marquer comme non lu.
Quésoft Ecrit le: Mercredi 18 octobre 2006 à 14:18 Déconnecté(e)    Voir le profil de Quésoft Envoyer un email à Quésoft Visiter le site WEB de Quésoft Envoyer un message privé à Quésoft  

Cal*s, j'ai perdu ce que j'avais écrit avant de poster...

Je vais le synthétiser.

Je disais que l'OO gardait son avantage même dans la situation décrite par Kevin: dans une telle situation je devrai implémenter une fonction pour tous mes types de donnée abstraits en C ou si je n'ai pas à le faire parce qu'un traitement générique existe, en OO c'est pas plus fastidieux: je n'ai qu'à ajouter une méthode à la superclasse, qui sera héritée.

Pour la syntaxe C++, je disais que selon mes souvenir, cela se gâtait rapidement. Si mes souvenir sont bons, pour passser des paramètres à un objet alloué localement, c'est quelque chose du genre : maclasse monobjet(mesparametres) ?

Pour le front end, je demandais si ce n'était pas de travailler avec un framework, plutôt que de modifier un genre de gabarit.

Ensuite, pour le nouveau post:

Kevin Kofler :
Le problème est que toi, tu as l'air de viser un convertisseur léger, ce qui est très différent d'avoir une sortie (exécutables produits) légère. (Cf. par exemple le problème des objets sur la pile ou dans des registres.)


Si mon souci était de programmer quelque chose de léger, je ne parlerais pas d'optimisation et surtout, je resterais avec Moka (qui est déjà codé et qui a un API ansi-c fonctionnel, bien que complètement pauvre (genre String et Object sont à peu près les seules classes de l'API). Mon souci est de produire le code le plus slim possible (sans prendre des solutions rammantes pour sauver quelques octets de mémoire). Pour les objets sur la pile, c'est une idée doublement intéressante puisqu'elle est utile au programmeur et en bonus, permet de faciliter les optimisations.
    
./Post n°38   Marquer comme non lu.
Kevin Kofler Ecrit le: Mercredi 18 octobre 2006 à 15:45 Déconnecté(e)    Voir le profil de Kevin Kofler Envoyer un email à Kevin Kofler Visiter le site WEB de Kevin Kofler Envoyer un message privé à Kevin Kofler  


Quésoft :
Je disais que l'OO gardait son avantage même dans la situation décrite par Kevin: dans une telle situation je devrai implémenter une fonction pour tous mes types de donnée abstraits en C

Mais une seule (avec un switch dedans).

ou si je n'ai pas à le faire parce qu'un traitement générique existe, en OO c'est pas plus fastidieux: je n'ai qu'à ajouter une méthode à la superclasse, qui sera héritée.

Et avec les switches, l'équivalent est le cas default. (Et bien sûr, si c'est le seul cas, on peut se passer complètement du switch.)

C'est comme dans l'autre cas, avec l'OO, tu rajoutes un seul objet, mais tu es quand-même obligé de coder toutes ses méthodes qui diffèrent de l'implémentation générique. Avec le procédural, on rajoute ça aux fonctions existantes (et il peut aussi y avoir une implémentation générique, le cas default).

La différence entre les 2 paradigmes, c'est le regroupement, le code à écrire en fin des comptes est le même.

Pour la syntaxe C++, je disais que selon mes souvenir, cela se gâtait rapidement. Si mes souvenir sont bons, pour passser des paramètres à un objet alloué localement, c'est quelque chose du genre : maclasse monobjet(mesparametres) ?

Oui.
Membre de l'équipe de TIGCC: http://tigcc.ticalc.org
Mainteneur du portage Linux/Unix de TIGCC: http://tigcc.ticalc.org/linux/
Membre de l'équipe de CalcForge: http://www.calcforge.org:70/

Participez à la reprise de Ti-Gen!
    
  :: Index » Forum Ti68K » Programmation C » Orienté objet avec TIGCC (113 réponse(s))
Pages : 2/6     « 1 [2] 3 4 5 6 » »|

.Répondre à ce sujet
Les boutons de code
[B]old[I]talic[U]nderline[S]trikethrough[L]ine Flip Hori[Z]ontallyFlip [V]erticallySha[D]ow[G]low[S]poilerCode [G][C]ite
Bullet [L]istList Item [K] Link [H][E]mail[P]icture SmileysHelp
Couleurs :
Saisissez votre message
Activer les smileys
     

Forum de Ti-Gen v3.0 Copyright ©2004 by Geoffrey ANNEHEIM
Webmaster: Kevin KOFLER, Content Admins: list, Server Admins: Tyler CASSIDY and Kevin KOFLER, DNS Admin: squalyl
Page générée en 54.42ms avec 18 requetes