Autor Thema: Templates/Generic Types für eigene Programmiersprache  (Gelesen 7648 mal)

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« am: 09. February 2006, 16:19 »
Hi, ich arbeite im Moment an einer eigenen (bytecode basierten) Programmiersprache, und ich finde keinen guten Weg, um Templates zu implementieren. Eine Möglichkeit wäre, die Templates vom Compiler einfach durch Einsetzen der richtigen Typen anstatt der Typ-Argumente zu kompilieren. Dann können Shared Libraries (von denen der Source unbekannt ist), von denen der Code unbekannt ist, Templates aber nur eingeschränkt nutzen. C++ basiert ja darauf, wie löst C++ dieses Problem? (oder ist das in C++ auch nicht möglich?) Eine andere Möglichkeit wäre, alle Primitiven Objekte in Wrapperklassen zu stecken (die nicht-primitven Objekte basieren eh alle auf einer Grundklasse) und dann das Template nur für die Grundklasse zu kompilieren. Durch Operator Overloading könnte man alle Typen einheitlich handhaben. Diese Methode würde ich gerne vermeiden, da das sehr lahm wäre, ausserdem wäre sie schwer zu implementieren. (Die Programmiersprache hat sehr viele Primitive und Strukturen, die nicht in andere Typen gecastet werden können, also auch nicht in die Grundklasse)

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 09. February 2006, 18:14 »
Zitat von: SSJ7Gohan
Eine Möglichkeit wäre, die Templates vom Compiler einfach durch Einsetzen der richtigen Typen anstatt der Typ-Argumente zu kompilieren. Dann können Shared Libraries (von denen der Source unbekannt ist), von denen der Code unbekannt ist, Templates aber nur eingeschränkt nutzen.

Ich vermute, die Funktionen für jeden Typ einmal zu kompilieren, das ist die einfachste Möglichkeit. Inwieweit das mit Shared Libraries nutzbar ist, hängt wohl im wesentlichen davon ab, wie dein Bytecode aussieht. Aber wenn es ohnehin etwas eigenes ist, sollte sich das doch passend machen lassen?

Zitat
Eine andere Möglichkeit wäre, alle Primitiven Objekte in Wrapperklassen zu stecken (die nicht-primitven Objekte basieren eh alle auf einer Grundklasse) und dann das Template nur für die Grundklasse zu kompilieren. Durch Operator Overloading könnte man alle Typen einheitlich handhaben.

Klingt nach Java. ;) Was du an dieser Stelle aber mit überladenen Operatoren bezweckst, verstehe ich nicht ganz.


Disclaimer: Mit Compilerbau habe ich mich bisher nur theoretisch beschäftigt, inwieweit ich da jetzt komplett danebenliege - keine Ahnung.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 09. February 2006, 18:23 »
Hier mal grad ein Beispiel in Pseudocode:
class <TYPE> {
static TYPE add(TYPE a, TYPE b) {
return a + b;
}
}

Du überladene Operatoren funktioniert dass, egal, ob man jetzt eine Wrapper-Klasse für Integer, Floats, Chars oder was-auch-immer übergibt.

Das Problem bei Shared Libraries ist, dass ein komplett anderer Code erzeugt wird, wenn man einem Template z.B. ein Objekt statt einem Integer übergibt. Der Bytecode müsste extrem abstrakt sein, dann kann man auch gleich den Sourcecode der Shared Library veröffentlichen, statt solchen Bytecode zu benutzen. Ausserdem würde das Ausführen langsammer, weil die VM die abstrakten Instructions noch in kleinere Umwandeln müsste.

Ich werde wohl die erste Methode benutzen, Shared Libraries müssten dann entweder als Source vorliegen, oder als Templateargumente können nur die Typen benutzt werden, für welche die Library kompiliert wurde. Wenn man andere benutzen will, kann man die ja immernoch in Wrapperklassen stecken.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #3 am: 09. February 2006, 18:58 »
hi,

in C++ werden Templates mit Sicherheit zur Compile-Zeit aufgelöst und nicht erst beim Linken, deshalb müssen Templates normalerweise auch immer includiert werden... :roll:
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 09. February 2006, 19:05 »
Zitat von: SSJ7Gohan
Hier mal grad ein Beispiel in Pseudocode:
class <TYPE> {
static TYPE add(TYPE a, TYPE b) {
return a + b;
}
}

Du überladene Operatoren funktioniert dass, egal, ob man jetzt eine Wrapper-Klasse für Integer, Floats, Chars oder was-auch-immer übergibt.

Ah, ok, darauf willst du hinaus. Um in der Java-Terminologie zu bleiben, wäre das das "Autoboxing", oder? Also, daß Integer zu int kompatibel ist.

Zitat
Das Problem bei Shared Libraries ist, dass ein komplett anderer Code erzeugt wird, wenn man einem Template z.B. ein Objekt statt einem Integer übergibt. Der Bytecode müsste extrem abstrakt sein, dann kann man auch gleich den Sourcecode der Shared Library veröffentlichen, statt solchen Bytecode zu benutzen. Ausserdem würde das Ausführen langsammer, weil die VM die abstrakten Instructions noch in kleinere Umwandeln müsste.

Hmm, klar, solche Funktionen müßten fast in einer Art eigenem Zwischencode gespeichert werden. Der Code würde ja aber nie direkt ausgeführt werden, sondern nur benutzt werden, um die Instanzen mit konkreten Datentypen in "richtigen", ausführbaren Bytecode zu kompilieren. Das würde vielleicht auf die Dateigröße gehen, aber nicht auf die Ausführungsgeschwindigkeit.

Ich wollte grad mal ausprobieren, wie Ada mit Generics umgeht, aber da wird zum Kompilieren der Source benötigt. Das heißt, der Code wird wohl erst beim Konkretisieren in das Modul, wo er benutzt wird, kompiliert. Jedenfalls ist er dort in meinem Versuch gelandet. ;)

Zitat
Ich werde wohl die erste Methode benutzen, Shared Libraries müssten dann entweder als Source vorliegen, oder als Templateargumente können nur die Typen benutzt werden, für welche die Library kompiliert wurde. Wenn man andere benutzen will, kann man die ja immernoch in Wrapperklassen stecken.

Ja, solange es für alle Klassen funktioniert, sollte das ja kein größeres Problem darstellen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 09. February 2006, 19:13 »
Ja, das wäre dann Autoboxing. Allerdings unterstützt meine Sprache wie schon gesagt Strukturen, die sich in keine andere Klasse casten lassen (auch nich in die Superklasse), für die müsste ich dann automatisch einen Wrapper generieren lassen oder den Wrapper auch zu nem Template machen.

Naja, auf die Ausführungsgeschwindigkeit würde das nicht gehen, aber auf die Ladezeit für ein Programm, da der Zwischencode ja erst in vernünftigen Bytecode übersetzt werden muss.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 09. February 2006, 19:34 »
Zitat
Naja, auf die Ausführungsgeschwindigkeit würde das nicht gehen, aber auf die Ladezeit für ein Programm, da der Zwischencode ja erst in vernünftigen Bytecode übersetzt werden muss.

Die Übersetzung würde doch nicht zur Laufzeit geschehen. Die generische Funktion selbst würde ja nie übersetzt werden, da sie etwas abstraktes ist.

Aber an irgendeiner Stelle wird die Funktion bzw. Klasse doch konkretisiert. Sei es durch eine explizite Deklaration wie in Ada oder implizit durch Benutzung wie afaik in Java. Und an dieser Stelle würde der Compiler den passenden Code (also vernünftigen Bytecode) für die konkrete Instanz erzeugen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 09. February 2006, 20:28 »
Achso, ja, das wäre auch eine Möglichkeit. Das könnte man ja später mal ergänzen, ich werde erstmal die Methode nehmen, bei der ich einfach alle Typen durch die Richtigen ersetze.

 

Einloggen