Precompilateur Poo

Sujets variés concernant le développement en PureBasic
Avatar de l’utilisateur
microdevweb
Messages : 1798
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Precompilateur Poo

Message par microdevweb »

Bonjour à tous,

Ce n'est un secret pour personne, j'aime la Poo et regrette que Pb n'offre pas cette possibilité. Cependant il possible dans l'ide de configurer un logiciel qui se lance avant la compilation et pourrait ainsi convertir une couche Poo en code Purebasic

Voici un exemple :

Image

Code de la couche poo

Code : Tout sélectionner

Class Car
  private string name
  private int id
  public Method  Car(string name,int id)
    this.name = name
    this.id = id
  EndMethod
  public Method void teste(string name)
    Debug name
  EndMethod
  public Method string getName()
    return this.name
  EndMethod
EndClass
Class FleetCar
  private string name
  public Method FleetCar(string name)
    this.name = name
  EndMethod
EndClass
Global Car myCar = new Car("volvo",1)

myCar\teste("ok")
Debug myCar\getName()


Code généré par le pré-compilateur

Code : Tout sélectionner

DeclareModule __OOP_INTERFACES
Interface Car

getName.s()
teste(name.s)

EndInterface
Interface FleetCar


EndInterface

EndDeclareModule
Module __OOP_INTERFACES
EndModule
DeclareModule _Car
Structure _struct
*methods
id.l
name.s
EndStructure

Declare new(name.s,id)
EndDeclareModule
Module _Car
Procedure new(name.s,id)
Protected *this._struct = AllocateStructure(_struct)
With *this
\methods = ?METHODS
    \name = name
    \id = id
ProcedureReturn *this
EndWith
EndProcedure
Procedure.s getName(*this._struct)
With *this
    procedureReturn \name

EndWith
EndProcedure
Procedure teste(*this._struct,name.s)
With *this
    Debug name

EndWith
EndProcedure

DataSection
METHODS:

Data.i @getName()
Data.i @teste()
EndDataSection
EndModule
DeclareModule _FleetCar
Structure _struct
*methods
name.s
EndStructure

Declare new(name.s)
EndDeclareModule
Module _FleetCar
Procedure new(name.s)
Protected *this._struct = AllocateStructure(_struct)
With *this
\methods = ?METHODS
    \name = name
ProcedureReturn *this
EndWith
EndProcedure

DataSection
METHODS:

EndDataSection
EndModule
Global myCar.__OOP_INTERFACES::Car = _Car::new("volvo",1)
myCar\teste("ok")
Debug myCar\getName()



Tout ceci est évidement transparent pour l'utilisateur (le code converti ne sera en vérité jamais visible que si l'on ouvre le fichier que pb crée à la compilation)



Note: pour garder l’esprit pb les fonctions (poo) ne sont pas sensible à la case

Voila le projet sur le quel je vais travaillé selon mon temps disponible

Toutes vos idées sont bonnes à prendre :wink:
Dernière modification par microdevweb le mar. 26/déc./2017 1:35, modifié 2 fois.
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
microdevweb
Messages : 1798
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: Precompilateur Poo

Message par microdevweb »

Voici une exemple de premier teste fonctionnel
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
G-Rom
Messages : 3626
Inscription : dim. 10/janv./2010 5:29

Re: Precompilateur Poo

Message par G-Rom »

un gros pavé ton précompilateur... 8O
va tu gérer la surchage d'opérateur ? les methodes virtuelles ?

Par exemple , surchage d'opérateur :
Position.Vector2
...
Direction.Vector2
...

speed.f = 50.0
NewPosition.Vector2
NewPosition = Position + ((Direction * speed) * deltatime)
si tu le fait, je refait du purebasic a plein temps :)
Ce n'est un secret pour personne, j'aime la Poo
Fait du C++ :)
Avatar de l’utilisateur
microdevweb
Messages : 1798
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: Precompilateur Poo

Message par microdevweb »

@G-Rom,

Actuellement je développe beaucoup en "java" et m'en inspire un peux dans le cadre de ce projet.

Ce que j'aime dans Pb.
  • Le résultat final un exe compact, autonome, rapide et de petite taille.
  • La simplicité pour créer une "IHM"
  • La doc
  • pas besoins d'include
  • La souplesse d'utilisation des pointeurs
Ce que j'aime moins
  • La syntaxe un peux trop littéral. (mais on fais avec)
Ce qui me manque
  • Une couche objet
Mes constations, même si Pb n'est pas orienté objet il est possible via des structures, interfaces et pointeurs de faire de l'objet en respectant les normes objet suivantes.
  • Classification Oui via les modules
  • Encapsulation Oui via les modules et structures
  • Héritage Oui
  • Polymorphisme Oui
  • Surcharge des méthodes difficile mais envisageable
Ce qu'il est prévu de faire avec ce précompilateur
  • Class
    • simple
    • abstraite
  • Membres
    • priver
    • priver et static
    • public et static
    • (les membres public non static ne seront pas pris en compte)
  • Méthodes
    • public
    • public abstraite
    • public static
    • priver
    • priver et static
    * Surcharge (non implémentée dans les premières versions)
Le point chaud l'appel de méthodes en cascade.

J'aimerais en effet que les méthode soit appelable comme ceci

Exemple

Code : Tout sélectionner

myClass1.getClass2.getClass3.draw()
Ce point va être le plus difficile à gérer, interface, callFunction ?

De toute façon le code sera mis en open-source sous licence creative commons (BY - NC - SA) donc libre à chacun d'en faire ce qu'il veut dans le cadre de la licence.

Remarque : le code est écrit en mode poo
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
G-Rom
Messages : 3626
Inscription : dim. 10/janv./2010 5:29

Re: Precompilateur Poo

Message par G-Rom »

Faire un précompilateur , reviens à faire le début d'un compilateur , du moins la partie avant , c'est une tâche complexe et simple a la fois , il faut bien comprendre la partie avant d'un compilateur avant de se lancer dans un tel projet. dans un premier temps, il faut que ton précompilateur traduise les instructions en opcode , un opcode est comme en ASM , une instruction avec une valeur simple : NOP = 0x90

une ligne de code simple peut se traduire avec un opcode maison sans problème

MaVariable.l = 10 ; déclaration et affectation

par exemple avec des opcode au hasard :

DECLARE 1
ASSIGN 1
VALUE 10

en admettant que :

DECLARE = 0xFF
ASSIGN = 0xA0
VALUE = 0xBA

le pseudo code deviens :

0xFF 0x00000001 0xA0 0x00000001 0xBA 0x0000000A

avec cette suite, il est facile de le reconvertir en code purebasic , avec une machine a état le tour est joué , par exemple, la première instruction est 0xFF , declare donc, la machine a état attend ensuite une valeur ( un index dans la table des variable ) , ici 1 , ensuite l'instruction suivante est ASSIGN ou 0xA0 , la machine à état attend donc une valeur aléatoire , etc... évidement ici, c'est un exemple bateau.

Il y a plenti d'article sur le net qui couvre le sujet.
Avatar de l’utilisateur
microdevweb
Messages : 1798
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: Precompilateur Poo

Message par microdevweb »

@G-Rom,

hum c'est très intéressant. Maintenant je t'avouerais que je n'ai absolument pas pris le problème dans ce sens.

J'extrait simplement le code, sauve les classes, méthodes, membres dans des classes et transpose le code en Pb après.

Disons que c'est un peut dans le sens des macros, mais plus poussé.

Je ne promet évidement pas le résultat et ce sera peut'être une grosse daube on verra cela à l'autopsie. :mrgreen:
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
Micoute
Messages : 2522
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: Precompilateur Poo

Message par Micoute »

Ca me rappelle l'histoire de l'œuf de Christophe Colomb.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 5.73 PB 6.00 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
G-Rom
Messages : 3626
Inscription : dim. 10/janv./2010 5:29

Re: Precompilateur Poo

Message par G-Rom »

microdevweb a écrit :@G-Rom,

hum c'est très intéressant. Maintenant je t'avouerais que je n'ai absolument pas pris le problème dans ce sens.
Il est donc évident que tu utilise la méthode certifiée ISO-1664 , sans aucun doute ;)
une vidéo intéressante d'un Finlandais que j'ai vu hier par hasard qui traite en partie le sujet :

https://www.youtube.com/watch?v=eF9qWbuQLuw&t=1905s
et d'autres lien utiles :

https://ruslanspivak.com/lsbasi-part1/
https://medium.freecodecamp.org/the-pro ... d3f449c919
https://www.youtube.com/watch?v=h7tkSfQQNGg


Donc, ton objectif est de transformé ton code PB / OO en byte code , puis du byte code le transformé en code PB normal
un autre conseil, utilise le PB "standard" pour faire cela , plus simple a lire & à maintenir qu'un pseudo poo bricolé en ISO-1664
de plus PB dispose de fonction simple et puissante pour le traitement de texte. y a plus qu'a ! ;)
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Precompilateur Poo

Message par djes »

C'est une très chouette idée ! Bon courage :)
Avatar de l’utilisateur
microdevweb
Messages : 1798
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: Precompilateur Poo

Message par microdevweb »

Merci djes,

G-Rom oui je pratique un peux comme ça..

Exemple avec le teste actuel (non fini)

Code à migrer

Code : Tout sélectionner

;{ Drawing CLASS
;*************************
; manage the drawing
;}
Class Drawing
  private name.s,width,height
  private List myForm.Form
  ; constructor
  public Method Drawing(name.s,width,height)
    this.name = name
    this.width = width
    this.height = height
  EndMethod
  ; public methods
  ;{ addForm
  ;*************************
  ; add a form to drawing
  ;}
  public Method addForm(form.Form)
      AddElement(this.myForm())
      this.myForm() = form
      Return form
  EndMethod
  
  public Method draw()
    StartVectorDrawing(CanvasVectorOutput(
  EndMethod
  ; private methods
  
EndClass
;{ Form ABSTRACT CLASS
;*************************
; it can be not instantiate it use by drawing class
;}
Class Abstract Form 
  private x,y
  public Method Form(x,y)
    this.x = x
    this.y = Y
  EndMethod
  
  public Method abstract draw()
  
  EndMethod
EndClass
;{ Rectangle CLASS extended from Form
;*************************
; it use for create rectangular form
;}
Class Rectangle extends Form 
  private w,h
  public Method Rectangle(x,y,w,h)
    super(x,y)
    this.w = w
    this.h = h
  EndMethod
EndClass
;{ Circle CLASS extended from Form
;*************************
; it use for create circular  form
;}

Class Circle extends Form
  private radius
  public Method Circle(x,y,radius)
    super(x,y)
    this.radius = radius
  EndMethod
EndClass
;{ MainForm CLASS
;*************************
; main window of software
;}
Class Static MainForm
  public Static idWin,idCanvas
  ; PUBLIC STATIC
  public Static Method open()
    this.idWin = OpenWindow(#PB_Any,0,0,800,600,"Test",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
    this.idCanvas = CanvasGadget(#PB_Any,0,0,800,600)
    BindEvent(#PB_Event_CloseWindow,@eventClose())
  EndMethod
  ; PRIVATE METHODE
  private Method eventClose()
    CloseWindow(this.idWin)
    End
  EndMethod
EndClass
Code Pb retourner (non terminé)

Code : Tout sélectionner

DeclareModule _POO_INTERFACE
  Interface Drawing
    draw()
    addForm(form)
    
  EndInterface
  
  Interface Form
    draw()
    
  EndInterface
  
  Interface Rectangle Extends Form
    
  EndInterface
  
  Interface Circle Extends Form
    
  EndInterface
  
  Interface MainForm
    
    
  EndInterface
  
EndDeclareModule
Module _POO_INTERFACE
EndModule
DeclareModule Drawing
  Structure _struct 
    *methods
    name.s
    width.l
    height .l
    List myForm._POO_INTERFACE.Form ()
  EndStructure
  Declare new(name.s,width,height)
  
  Declare super(*this._struct,name.s,width,height)
  
EndDeclareModule 
Module Drawing
  Declare draw()
  Declare addForm(*form._POO_INTERFACE.Form)
  Procedure*this._struct,)
  EndProcedure
  
  Procedure*this._struct,*form._POO_INTERFACE.Form)
  EndProcedure
  
  Procedure new(name.s,width,height)
    Protected *this._struct = AllocateStructure(_struct)
  EndProcedure
  Procedure super(*this._struct,name.s,width,height)
  EndProcedure
  
EndModule
DeclareModule Form
  Structure _struct 
    *methods
    x.l
    y .l
  EndStructure
  Declare new(x,y)
  
  Declare super(*this._struct,x,y)
  
EndDeclareModule 
Module Form
  Declare draw()
  Procedure)
  EndProcedure
  
  Procedure new(x,y)
    Protected *this._struct = AllocateStructure(_struct)
  EndProcedure
  Procedure super(*this._struct,x,y)
  EndProcedure
  
EndModule
DeclareModule Rectangle
  Structure _struct Extends Form
    w.l
    h .l
  EndStructure
  Declare new(x,y,w,h)
  
  Declare super(*this._struct,x,y,w,h)
  
EndDeclareModule 
Module Rectangle
  Procedure new(x,y,w,h)
    Protected *this._struct = AllocateStructure(_struct)
  EndProcedure
  Procedure super(*this._struct,x,y,w,h)
  EndProcedure
  
EndModule
DeclareModule Circle
  Structure _struct Extends Form
    radius .l
  EndStructure
  Declare new(x,y,radius)
  
  Declare super(*this._struct,x,y,radius)
  
EndDeclareModule 
Module Circle
  Procedure new(x,y,radius)
    Protected *this._struct = AllocateStructure(_struct)
  EndProcedure
  Procedure super(*this._struct,x,y,radius)
  EndProcedure
  
EndModule
DeclareModule MainForm
  Structure _struct 
    *methods
    
    
  EndStructure
  Global idWin
  Global idCanvas 
  Declare open()
  Declare new()
EndDeclareModule 
Module MainForm
  Declare open()
  Declare eventClose()
  Procedure)
  EndProcedure
  
  Procedure*this._struct,)
  EndProcedure
  
EndModule

Il reste beaucoup de travail :roll:

Mais c'est une défit de taille et j'aime les défits
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Precompilateur Poo

Message par Kwai chang caine »

Putain...votre conversation, c'est comme du petit lait pour moi 8O
J'y comprends pas un mot, mais je trouve ça super bon 8)

En tout cas, si tu arrives au bout....tu seras le premier

Image

Et pourtant parmi un certain nombre de participant


Image

Je te souhaite de mener à bout ton projet, car c'est frustrant de voir nombre des plus grands, s'attaquer à ce lourd sujet, sans vraiment venir à bout et ceci depuis un grand nombre d'années :|

Image

Je sais que ça va pas t'aider beaucoup :oops:
Mais je suis avec toi 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
G-Rom
Messages : 3626
Inscription : dim. 10/janv./2010 5:29

Re: Precompilateur Poo

Message par G-Rom »

Kwai chang caine a écrit : car c'est frustrant de voir nombre des plus grands, s'attaquer à ce lourd sujet, sans vraiment venir à bout
Qui c'est attaqué a cela ? je connais personne qui à fait un vrai précompilateur OO pour PB ou j'ai loupé qq chose.

C'est pas vraiment compliqué a comprendre, prend un code source PB par ex :
Variable.l = 50
VariableB.l = Variable * #PI
L'idée est donc de séparé chaque mot des un des autres pour obtenir une liste comme ceci :
tout en gardant pour chaque mot, de quel ligne, de quel fichier viens le mot pour le traitement des erreurs
Variable.l
=
50
VariableB.l
=
Variable
*
#PI
Ensuite il faut identifié qui est quoi

Code : Tout sélectionner

Identifier
Operator
Value
Indentifier
Operator
Indentifier
Operator
Constant
Voila grosso modo , le traitement des erreur deviens tout de suite plus facile à gérer, on ne traite plus l'erreur avec des strings a l'arrache mais on traite les erreurs avec une machine a état qui regarde une suite de mot ( dans la liste ci dessus ) , par exemple en PB 2 opérateur ne peuvent pas se suivre , donc il aura une erreur dans ce cas de figure , et comme tu sauvegarde pour chaque mot , la ligne, le fichier, tu peu généré une belle erreur indiquant ou est quoi qui ne va pas.
Si tout va bien , sans erreur, a partir de ta liste de mots , et si tout les mots on été correctement identifié , tu génère un jolie byte code.
Pour la gestions des variable, structure, classe, etc... tu peu avoir en parallèle une table de correspondance pour chaque type
Pour les variables, une table de variable, etc... quand tu tombe sur un identifier qui est une variable, tu cherches dans cette table si la variable est déclarée , si elle l'est déjà et que tu la redeclare dans le meme scope, tu génère une erreur, etc...

Voila, la partie arrière du compilateur est faite, si ton byte code est de qualité , tu as plusieurs choix possible, faire un interpreteur qui lira ton bytecode, convertir ton bytecode en code machine pour faire un executable ( bof bof , il faut optimisé le byte code a mort , tache très complexe et non maintenable dans le temps a cause des différents OS , proc , etc... ) ou le convertir en PB,C,C++, etc...
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Precompilateur Poo

Message par Kwai chang caine »

Moi je parlais de la POO sur PB :oops:

Merci pour l'explication GRom 8)
Jamais j'aurais cru qu'il faille passer par une génération de byte code pour traduire d'un langage à l'autre 8O
Sauf si peut être comme tu le dis, MicroDevWeb veuille faire une traduction pour plusieurs langages

En tout cas, ça reste passionnant tout ça :wink:
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
G-Rom
Messages : 3626
Inscription : dim. 10/janv./2010 5:29

Re: Precompilateur Poo

Message par G-Rom »

Jamais j'aurais cru qu'il faille passer par une génération de byte code pour traduire d'un langage à l'autre
Moi aussi , naïvement je pensais au début qu'il fallait traité la source tel quel , mais tout les compilateur font ca, c'est d'ailleurs la spécialité de LLVM.
PureBasic fait la même chose, PB->ASM | ASM -> executable. Fred à fait le choix d'utilisé FASM comme code intermédiaire, il aurais très bien pu faire du byte code maison
puis ensuite a partir du bytecode maison , généré de l'ASM comme il le fait déjà , ou généré de l'ASM pour les architecture ARM, etc...
et l'avantage avec un byte code bien construit, tu peut faire facilement un interpréteur, une machine virtuelle , un émulateur, etc...
Bref, cela ouvre un panel de projet possible quand on ce lance la dedans.
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Re: Precompilateur Poo

Message par Zorro »

Kwai chang caine a écrit :Jamais j'aurais cru qu'il faille passer par une génération de byte code pour traduire d'un langage à l'autre 8O
non , je ne pense pas que ce soit obligatoire ...
apres c'est surement plus "propre" et plus rapide au moment de l'execution

j'ai fait un interpréteur qui marche bien , et Recursif sans avoir utilisé le principe du byteCode
(PureGolo)

et je fait de l'interprétation a la volée !
c'est plus lent a l’exécution , mais ça simplifie quand meme pas mal les choses ...
pas de conversion en langage "extra terrestre" (bytecode) pour finalement revenir a un autre langage
mais justement la facilité c'est d'interpreter un langage nouveau , pour faire une execution ...
de ce point de vue, c'est plus simple qu'une traduction d'un langage X vers un langage Y

car je n'ai qu'a surveiller une seule syntaxe ...

mais je précise , ç'est probablement bien plus lent , car j'analyse le texte, et j’interprète a la volée


Alors que dans la traduction d'un langage XX vers Purebasic
c'est un peut plus complexe , car on doit surveiller la syntaxe de notre langage xx
et en plus vérifier que la conversion ne creer pas d'erreur dans le langage Purebasic ...
je pense que le faire sans bytecode , deviens plus complexe
mais ça doit etre possible aussi , en analysant la ligne en cours a la volée la traiter ...
une traduction en quelque sorte , directement vers le langage cible , plutot que de passer par un bytecode ...

il faut alors mettre le paquet sur l'analyseur syntaxique ...
là aussi avec mon NONO (synthé vocal maison) je traduit du Français en "Phonemes" compréhensible par Nono
le gros du boulot est fait par l'analyseur syntaxique ....
avec toutes les variantes qui peuvent se présenter pour le son "EN"
"EnFant" par exemple contient deux sont "En" qui ne s'écrivent pas pareil ....

je vous laisse imaginer le reste des mots qui s’écrivent pareil , mais ne se prononcent pas pareil
"antérieur" "anémone" "animal" "antipode" touts ces mots commencent par "an" , mais seulement deux ont le son "AN"

bref, je ne pense pas que le passage par le bytecode, soit obligatoire .. c'est juste une methode (une bonne methode ?)
mais l'essentiel c'est bien l'analyseur syntaxique, qui lui doit etre solide
ensuite ce qu'on fait des infos tiré de chaque ligne , c'est a chacun de voir .. :)

je pense qu'il ne faut pas confondre faire un compilateur , et faire un interpréteur, c'est plus la meme chose

un interpréteur, c'est de l'interprétation , ça peut éventuellement se faire a la volée ..
on peut aussi le faire suite a l'analyse de plusieurs lignes ... comme on veut

un compilateur, demande probablement le passage par un byte code qui soit compatible avec un compilo connu,
ou soit pour se creer soit même un compilateur, mais la franchement, j'y connais rien :)

pour qu'un compilateur soit capable de créer un exécutable , a mon avis, il faut connaitre
comment un exécutable est créé

l'architecture d'un fichier EXE ... entête ...etc ...
pour pouvoir y insérer notre code dedans ... et ainsi avoir un exécutable de notre code :)
une sorte de squelette de *.EXE dans lequel on insere notre code Asm et roule ma poule :)

@GRom ne dis pas a KCC que son Dieu n'as fait qu'un convertisseur de langage Purebasic en langage Fasm ...
il va perdre ses reperes :lol:

ps: ça reste quand meme un sacres boulot ;)
Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
Répondre