OOP Precompiler und Konstrukte

Für allgemeine Fragen zur Programmierung mit PureBasic.

Wirst du einen OOP-Precompiler mitentwickeln wollen

Ja, brauch ich und habe ich Spass dran
12
38%
Nein, Unsinn und Zeitverschwendung
15
47%
Alles Andere was nicht oben zutrifft
5
16%
 
Insgesamt abgegebene Stimmen: 32

Benutzeravatar
X0r
Beiträge: 2770
Registriert: 15.03.2007 21:47
Kontaktdaten:

Beitrag von X0r »

Ist aber OOP. Hast es nur nicht verstanden.
Da Methoden Bestandteile einer Klasse sind, macht das wohl Sinn, und ist in anderen OOP Sprachen auch so angewendet.
Hä?
Hast dir überhaupt mal den konvertierten code vom parser angeguckt? Wie sähe das denn nach deinen Vorstellungen aus?

Und nein, den eigentlich Sinn von OOP habe ich nie so wirklich verstanden. Ich kam mit prozeduraler Programmierung immer sehr gut zurecht. allerdings merkt man die nachteile in einer Teamarbeit.

Kannst du mit meinem Parser etwas anfangen, vielleicht einen kleinen Editor oder so damit schreiben? Das würde bestimmt helfen.


Wenn ich mich jetzt nicht irre und mir die ganzen threads im englischen board nicht falsch durchgelesen habe, dann müsste diese methode richtig sein. Auch das mit dem this.


Edit:
Ohne dich persönlich anzugehen und nicht deine Fähigkeit in PB zu progrmmieren in Frage zu stellen, aber ... wie kann es sein, dass du einen OOP Parser programmieren wilst und du hier und dort die Frage bzgl. deines Codes wiederholst: "... hat das hier jetzt was mit OOP zu tun?".
An sowas kannst du so oder so keine skills festhalten. ;)
Benutzeravatar
mk-soft
Beiträge: 3845
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

Ich habe jetzt nicht alles gelesen,
aber sollte der Precompiler nicht so sein das alles was in PB programmiert wird auch kompatibel mit anderen Sprachen sein sollte?
Mit IUnknwon schnittstelle und get_function(...) und put_function(...)

Für eine Getfunction müsste entsprechend programmiert sein

Code: Alles auswählen

Procedure iget_function(*this, *result.variant)

  If *result = 0
    ProcedureReturn #E_INVALIDARG
  EndIf
  
  VariantClear_(*result)
  *result\vt = #VT_I4
  *result\iVal = 1000)
  
  ProcedureReturn #S_OK
  
EndProcedure

Procedure iget_function2(*this, *result.long)

  If *result = 0
    ProcedureReturn #E_INVALIDARG
  EndIf
  
  *result\l = 1000
  
  ProcedureReturn #S_OK
  
EndProcedure
Somit könnte man auch eine DLL compilieren welche dann auch mit VB oder C++ verwenden kann

Arbeite gerade wenn ich Zeit habe daran
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
bembulak
Beiträge: 228
Registriert: 13.12.2005 16:34
Wohnort: Österreich

Beitrag von bembulak »

Ist der Thread eingeschlafen und die Idee "verbrannt"? Schade, denn ich wäre ein Befürworter dieser Sache, auch wenn ich als (PB-)Programmierer kaum von Nutzen dafür sein kann.

Generell jedoch möchte ich dazu sagen: es gibt einige (für mich) interessante OOP Sprachen, wobei mir die Scriptsprachen und im Besonderen Python, sehr gut gefallen. Einige Konzepte davon finde ich wirklich erstklassig - da sollte man sich Anregungen suchen.
Benutzeravatar
X0r
Beiträge: 2770
Registriert: 15.03.2007 21:47
Kontaktdaten:

Beitrag von X0r »

Nochmal zu den Klassen und deren Methoden. Folgendes z.B:

Method Klasse:Methode
;..
EndMethod


würde aber nur dann Sinn machen, wenn der PreCompiler der Prozedur automatisch die Instanz der Klasse übergeben soll, richtig?
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

bembulak hat geschrieben:Ist der Thread eingeschlafen und die Idee "verbrannt"? Schade, denn ich wäre ein Befürworter dieser Sache, auch wenn ich als (PB-)Programmierer kaum von Nutzen dafür sein kann.
Wenn ich Zeit habe werde ich es noch einmal versuchen, mir
schwirren da ein paar neue Ideen im Kopf herum. Oder hat
schon jemand angefangen ?
Benutzeravatar
inc.
Beiträge: 348
Registriert: 27.10.2004 12:25

Beitrag von inc. »

@ Edel

Ich habe gestern meinen Parser vom letzten Jahr nochmal ausgepackt. Es war ein Projekt was ich mit jemanden zusammen aus der Community angefangen und später alleine weitergeführt habe, da derjenige keine Zeit mehr hatte.
Lag alles noch auf meiner Platte, fehlte nur noch die Unterstützung von Polymorphismus, denn das sollte absolut vorhanden sein, andernfalls ists imho kein OOP, sondern lediglich ObjektBasiert. Aber das habe ich am gestrigen Abend noch ergänzt.

Ich werde dir heute Mittag den vorliegenden Code zusenden, damit du mal drüberschaust (bitte deine Email via PM). Ich würde das Projekt dann wenn es steht (wie hier auch angedacht) gerne öffentlich machen, damit -wenn vorhanden- schneller Bugs beseitigt werden, können, bzw. Optimierungen sich ebenso von anderen gut einbauen lassen.

Folgendes wird unterstützt:

- Parsing via Remis' Lexer
- Vererbung inkl.! Überladung/Polymorphismus
- Automatische Erkennung von Attribute und Methodenaufrufen der selben Klasse innerhalb von Methoden.
- Konstruktoren werden autom. Erkannt und beim Erstellen der Ojekte aufgerufen (sind aber nicht pflicht).
- Der ausgegebene Code des Parsers ist Debugger nativ, bedeutet, die Zeilen sind nicht vom Inhalt her verschoben o.ä.

Es sind momentan mehrere Arten von Objekt Initialisierern und This Zugriffen unterstützt, am Ende sollte aber EINE Syntax stehen.

- New, Delete
- ->attribute, *this->attribute, \attribute, .attribute
- ->methode(), *this-> methode(), \ methode(), . methode()
- Extends (also Vererbung)
- Virtual (bei Überladung!)

Man kann sich später festlegen, ob man C++ like wie z.B. New, Delete, -> und Virtual verwendet, oder diese Begriffe PureBasic like anwendet, also Create, Free, \attribute, \methode().

der Zugriff auf den *this Zeiger innerhalb einer Methode gefällt mir mit \attribute am ehesten, da diese Art von PB's With bekannt ist.

Machen solche Dinge wie "Declare" innerhalb einer Classe wirklich Sinn??? Bei Interfaces oder Strukturen in PB ist dies auch nicht der Fall, bzw. nicht von Nöten.
Was mir aber an deinem Beispiel weiter oben sehr gefiel und PB like ist, war die Methodendefinition als "CLASSE.Methode()".

Bei folgendem Code:

Code: Alles auswählen

Class OTHERCLASS
  OTHERCLASS()
  Release()

  get.s()
  
  Value.s
EndClass
  
Class THECLASS Extends OTHERCLASS
  THECLASS()
  Release()

  Virtual get.s()
  Set(string.s, long.l)
  append(string.s)
  
  string.s
  long.l
EndClass
  

Procedure OTHERCLASS.OTHERCLASS()
  Debug "Constructor from OTHERCLASS called"
  \Value = "Here is a string from OTHERCLASS"
EndProcedure

Procedure OTHERCLASS.Release()
  Debug "The destructor of OTHERCLASS called"
EndProcedure

Procedure.s OTHERCLASS.get()
  ProcedureReturn \Value
EndProcedure


Procedure THECLASS.THECLASS()
  Debug "Constructor from THECLASS called"
EndProcedure 

Procedure THECLASS.Release()
  Debug "The destructor of THECLASS has been called"
EndProcedure

Procedure.s THECLASS.get()
  ProcedureReturn \string + " from THECLASS! "
EndProcedure

Procedure THECLASS.Set(string.s, long.l)
  *this\string = Str(long) + " " + string
  *this->long = long
EndProcedure

Procedure THECLASS.Append(string.s)
  For i = 0 To \long -1
    Debug Str(i) + " " + \string
  Next
  For i = 0 To .long -1
    Debug Str(i) + " " + ->string
  Next
  For i = 0 To ->long -1
    Debug Str(i) + " " + ->get()
  Next
EndProcedure

*object.THECLASS = New THECLASS

*object\Set("A nice word", 10)
Debug *object\get()
Du kannst hier am Beispiel sehen, dass neben der Vererbung eine Überladung stattfindet, via "Virtual" wird aber get() der geerbten Klasse genutzt, daher ist der Ansatz der Polymorphie vorhanden.
Wenn ich also eine Helferklasse z.B. cWINDOW habe, kann ich somit definieren, dass ich die Methode \Create via einer eigenen \Create() Methode überladen lasse. So macht OOP erst richtig spaß :-)

Ich habe im o.g. Code auch noch etwas mit den Möglichkeiten der *this Zeiger Optionen innerhalb der Methoden gearbeitet.

Und dieser Code kommt dann raus:

Code: Alles auswählen

Declare.l ConstructOTHERCLASS() : Interface OTHERCLASS 
  OTHERCLASS ( ) 
  Release ( ) 
  
  get . s ( ) 
  
EndInterface : Structure sOTHERCLASS : *vt : Value . s 
EndStructure 

Declare.l ConstructTHECLASS() : Interface THECLASS Extends OTHERCLASS 
  THECLASS ( ) 
  _overloaded_Release ( ) 
  
  _overloaded_get . s ( ) 
  Set ( string . s , long . l ) 
  append ( string . s ) 
  
EndInterface : Structure sTHECLASS Extends sOTHERCLASS : string . s 
  long . l 
EndStructure 


Procedure OTHERCLASS_OTHERCLASS   (*this.sOTHERCLASS ) : *thisM.OTHERCLASS = *this 
  Debug "Constructor from OTHERCLASS called" 
  *this\ Value = "Here is a string from OTHERCLASS" 
EndProcedure 

Procedure OTHERCLASS_Release   (*this.sOTHERCLASS ) : *thisM.OTHERCLASS = *this 
  Debug "The destructor of OTHERCLASS called" 
EndProcedure 

Procedure . s OTHERCLASS_get   (*this.sOTHERCLASS ) : *thisM.OTHERCLASS = *this 
  ProcedureReturn *this\ Value 
EndProcedure 


Procedure THECLASS_THECLASS   (*this.sTHECLASS ) : *thisM.THECLASS = *this 
  Debug "Constructor from THECLASS called" 
EndProcedure 

Procedure THECLASS_Release   (*this.sTHECLASS ) : *thisM.THECLASS = *this 
  Debug "The destructor of THECLASS has been called" 
EndProcedure 

Procedure . s THECLASS_get   (*this.sTHECLASS ) : *thisM.THECLASS = *this 
  ProcedureReturn *this\ string + " from THECLASS! " 
EndProcedure 

Procedure THECLASS_Set   (*this.sTHECLASS,  string . s , long . l ) : *thisM.THECLASS = *this 
  *this \ string = Str ( long ) + " " + string 
  *this \  long = long 
EndProcedure 

Procedure THECLASS_Append   (*this.sTHECLASS,  string . s ) : *thisM.THECLASS = *this 
  For i = 0 To *this\ long - 1 
    Debug Str ( i ) + " " + *this\ string 
  Next 
  For i = 0 To *this\ long - 1 
    Debug Str ( i ) + " " + *this \ string 
  Next 
  For i = 0 To *this \ long - 1 
    Debug Str ( i ) + " " + *thisM \ get ( ) 
  Next 
EndProcedure 

*object . THECLASS =  ConstructTHECLASS() 

*object \ Set ( "A nice word" , 10 ) 
Debug *object \ get ( ) 
*object \ append ( " comes here" ) 

*object\Release() : FreeMemory(PeekL(*object)) : FreeMemory(*object)  

; jaPBe Version=3.7.7.653 
; Build=0 
; Language=0x0000 Language Neutral 
; FirstLine=0 
; CursorPosition=7 
; ExecutableFormat=Windows 
; DontSaveDeclare 
; EOF 
; ------------------------------- OOP Constructors, etc. -------------------------------

Procedure ConstructOTHERCLASS()
  Protected *this.sOTHERCLASS = AllocateMemory(SizeOf(sOTHERCLASS))
  Protected *thisM.OTHERCLASS = *this
  If Not *this : ProcedureReturn #False : EndIf
  Global _VT_OTHERCLASS = AllocateMemory(SizeOf(OTHERCLASS))
  *this\vt = _VT_OTHERCLASS
  PokeL(_VT_OTHERCLASS + OffsetOf(OTHERCLASS\OTHERCLASS()), 	@OTHERCLASS_OTHERCLASS() )
  PokeL(_VT_OTHERCLASS + OffsetOf(OTHERCLASS\Release()), 	@OTHERCLASS_Release() )
  PokeL(_VT_OTHERCLASS + OffsetOf(OTHERCLASS\get()), 	@OTHERCLASS_get() )
  CompilerIf Defined(OTHERCLASS_OTHERCLASS, #PB_Procedure) = #True
  *thisM\OTHERCLASS()
  CompilerEndIf
  ProcedureReturn *this
EndProcedure

Procedure ConstructTHECLASS()
  Protected *this.sTHECLASS = AllocateMemory(SizeOf(sTHECLASS))
  Protected *thisM.THECLASS = *this
  If Not *this : ProcedureReturn #False : EndIf
  Global _VT_THECLASS = AllocateMemory(SizeOf(THECLASS))
  *this\vt = _VT_THECLASS
  PokeL(_VT_THECLASS + OffsetOf(THECLASS\OTHERCLASS()), 	@OTHERCLASS_OTHERCLASS() )
  PokeL(_VT_THECLASS + OffsetOf(THECLASS\Release()), 	@OTHERCLASS_Release() )
  PokeL(_VT_THECLASS + OffsetOf(THECLASS\get()), 	@OTHERCLASS_get() )
  PokeL(_VT_THECLASS + OffsetOf(THECLASS\THECLASS()), 	@THECLASS_THECLASS() )
  PokeL(_VT_THECLASS + OffsetOf(THECLASS\Release()), 	@THECLASS_Release() )
  PokeL(_VT_THECLASS + OffsetOf(THECLASS\get()), 	@OTHERCLASS_get() )
  PokeL(_VT_THECLASS + OffsetOf(THECLASS\Set()), 	@THECLASS_Set() )
  PokeL(_VT_THECLASS + OffsetOf(THECLASS\append()), 	@THECLASS_Append() )
  CompilerIf Defined(OTHERCLASS_OTHERCLASS, #PB_Procedure) = #True
  *thisM\OTHERCLASS()
  CompilerEndIf
  CompilerIf Defined(THECLASS_THECLASS, #PB_Procedure) = #True
  *thisM\THECLASS()
  CompilerEndIf
  ProcedureReturn *this
EndProcedure
Die Zeilenstruktur ist komplett zwecks Debugging erhalten da die OOP spez. Dingen via ":" im Code angehangen und die Konstruktoren etc. am Ende angefügt sind.
Zuletzt geändert von inc. am 29.10.2007 14:19, insgesamt 1-mal geändert.
Hier gibts die OOP Option für PureBasic.
Benutzeravatar
bembulak
Beiträge: 228
Registriert: 13.12.2005 16:34
Wohnort: Österreich

Beitrag von bembulak »

Tja, dann fehlt nur noch eine IDE, aber eine vorhandene Scite installation anzupassen, dürfte kein Problem sein, denke ich.
Ich habe schon mehrmals Scite.Properties an meine Bedürfnisse angepasst. Auch als ich noch mit PB 3.3 gearbeitet habe, hatte ich eigentlich große Freude mit Scite/Scintilla.
Das wäre (für's erste zumindest) der geringste Aufwand.
Benutzeravatar
inc.
Beiträge: 348
Registriert: 27.10.2004 12:25

Beitrag von inc. »

Ein klarer Vorteil bei der Codeausgabe oben wäre z.B., dass dieser immer noch sehr übersichtlich, nicht mit ZeilenDummy-Füllern etc. erstellt, aber trotzdem Debugger kompatibel ist.

Wenn man also OOP Code anbietet, diesen aber auch den Leuten in der Community ohne OOP Plugin zur Verfügung stellen will, lässt sich dieser Code oben auch übersetzt gut weiternutzen.
Hier gibts die OOP Option für PureBasic.
Benutzeravatar
ZeHa
Beiträge: 4760
Registriert: 15.09.2004 23:57
Wohnort: Friedrichshafen
Kontaktdaten:

Beitrag von ZeHa »

Sieht schonmal sehr professionell aus!

Zwei Dinge möchte ich aber anmerken, gerade was die Syntax-Festlegung angeht. Bitte plant mit ein, daß ihr wirklich drüber nachdenkt und nicht einfach vorhandenes kopiert. Bei zwei Dingen ist es mir aufgefallen:

Code: Alles auswählen

*object.THECLASS = New THECLASS
und

Code: Alles auswählen

Virtual get.s()
Ersteres ist ein klares C++ Zitat, aber eigentlich auch irgendwie umständlich. Ein einfaches *object.THECLASS() würde sicherlich genügen, schließlich werden normale Variablen auch einfach über Name.Typ erstellt.

Ob zweiteres nötig ist, ist ebenfalls fraglich. Ich will mir nicht anmaßen, darüber zu urteilen, da ich nicht alle Vor- und Nachteile kenne - aber ich glaube, es wäre zumindest wert, drüber nachzudenken, ob man "Virtual" auch einfach weglassen kann.

Wie gesagt, ich möchte hier nicht sagen daß meine Vorschläge die einzig wahren sind, ich möchte nur, daß sensibel damit umgegangen wird und ihr mehrere Möglichkeiten in Betracht zieht und auch darüber nachdenkt, welche die meisten Vorteile gegenüber anderen bietet.
Bild     Bild

ZeHa hat bisher kein Danke erhalten.
Klicke hier, wenn Du wissen möchtest, woran ihm das vorbeigeht.
Benutzeravatar
inc.
Beiträge: 348
Registriert: 27.10.2004 12:25

Beitrag von inc. »

*object.THECLASS = New THECLASS
Wie gesagt, ist mir auch noch zu C++ lastig, eher sowas PB mässiges wie

Create *myObject.CLASS

kennt man von ...

Dim array.l(49)



Ja, das "Virtual" kann anders lauten, so z.B. "Flexible" o.ä., ... ist aber bei kontrollierter Polymorphie obligatorisch, damit ich festlegen kann, welche Methoden beim Vererben fürs überladen frei gegeben werden.
Wie gesagt, ich möchte hier nicht sagen daß meine Vorschläge die einzig wahren sind, ich möchte nur, daß sensibel damit umgegangen wird und ihr mehrere Möglichkeiten in Betracht zieht und auch darüber nachdenkt, welche die meisten Vorteile gegenüber anderen bietet.
Ich verstehe dich genau richtig :) und habe jene Syntax - wie oben im Thread mit den Codebeispielen beschrieben - noch nicht festgelegt.

Keywords sind im SourceCode des Parsers als Konstanten definiert und können ohne Probleme geändert werden, genauso wie z.B. die Befehlsfolge beim Erstellen der Klasse wie bei dem Beispiel oben mit " ... New ...".
Hier gibts die OOP Option für PureBasic.
Antworten