Mittwoch, 16. Juli 2008

Lang lang ist's her...

Nach mittlerweile über einem halben Jahr ohne Informationen möchte ich mal wieder ein paar Informationen loswerden.

Es ist ziemlich still um das Projekt Chest geworden - das liegt an mehreren Faktoren, allen voran mein Studium. Beispielsweise bin zur Zeit dabei, für mein Compilerbau-Vorlesung einen C-Compiler zu schreiben (hoffentlich bis nächste Woche Dienstag), für meine Software-Engineering-Vorlesung ein 3D-Spiel zu entwickeln (bis mitte November) und IBM-intern auch noch ein Software-Projekt zu beenden (hoffentlich bis Ende der ersten August-Woche).

Zudem bahnt sich ein weiteres Projekt auf Basis von MWconn an (siehe dazu auch MWconn IPC-Interface für Pascal), dass evtl. cross-platform (Linux & Windows) sein wird.
Ganz ab davon, gibt es zur Zeit ein anderes privates Projekt, das meine restliche Freizeit auffrist: sp!!k

Um jedoch Chest nicht vollständig abzuschreiben, sei gesagt, dass es geplant ist, die Sprache innerhalb von sp!!k zu nutzen. Es ist also nichts vorbei, nur verzögert. ;-)

Deshalb verabschiede ich mich mit...



Bis demnächst...
Wirsing

Labels: ,

Samstag, 15. Dezember 2007

Wieder ist ein Monat um...

Herje, wie die Zeit verrennt, wenn man zu tun hat und flach liegt. ~_~
Nachdem die BA-Phase angefangen hatte, wurde ich mit Vorlesungskram überschüttet.
Und also ob das nicht genug wäre, war nun bereits die letzten zwei Wochen außer Gefecht - ein paar weitere werden noch folgen. Diagnose: Blinddarm-Entzündung. Der kleine Wurmfortsatz ist mittlerweile fort und die Narben am abheilen.

Nun aber zur Sprache:
Nach längerem hin-und-her und für-und-wider habe ich mich für folgende Blocksyntax entschieden: begin [befehl] ... end [befehl];
Das mag zwar erstmal ungewohnt aussehen, bringt aber einige (auch ästetische) Vorteile mit sich.
Zum einen ist es bei zeilenweiser Einrückung problemlos(er) möglich, Blockenden ihren Anfängen zuzuordnen (durch das Spezifizieren, was für ein Block beendet werden soll).
Desweiteren wird das bewährte begin ... end; Schema weitergeführt, das ja bekanntlich bei korrekter Einrückung einen überaus übersichtlichen Code ermöglicht (und es nebenbei einfacher möglich macht, eine saubere Einrückung durchzuhalten).

Hier ein paar Beispiele:
begin variables
end variables;

begin constants
end constants;

begin code
end code;

begin if (boolean) do
end if;

begin while (boolean) do
end while;

begin repeat do
end repeat on (boolean);


Desweiteren wird die for-Schleife eine erweiterte Funktionalität erhalten. Zum einen kann man nun die Schrittlänge pro Durchlauf angeben (und dadurch auch erstmals Kommawerte in der for-Schleife verarbeiten). Zum anderen bekommt die for-Schleife einen neuen Deskriptor till. Dieser ermöglicht es, for-Schleifen nicht aufgrund ihres Indexes zu beenden, sondern aufgrund eines bool'schen Ausdruckes. Dadurch sollen Programmierungen ersetzt werden, in denen entweder for-Schleifen durch ein break beendet werden, oder while-Schleifen, in denen manuell eine Zählvariable hochgezählt wird.
begin for Index := 1 till (boolean) do
end for;

begin for Index := 1 to 5 step 0.5 do
end for;

Natürlich ist es auch möglich, der for-till-Schleife einen step-Deskriptor mit zu übergeben.

So, das waren dann erstmal die neusten Neuerungen.
Hoffentlich geht es nun wieder periodischer zu Gange.


Bis demnächst...
Wirsing

Labels: ,

Freitag, 16. November 2007

Lebenszeichen

Da sich der eine oder andere sicher fragt, warum es in letzter Zeit so sehr stockend voran ging, möchte ich (bevor ich zu den Neuigkeiten komme) kurz erzählen, wie meine letzten Wochen aussahen.
Kurz gesagt: stressig und chaotisch - und zwar im wahrsten Sinne der Wörter.

Der letzte Eintrag ist vom 23.10.2007 - am 26.10.2007 war mein letzter Arbeitstag bei der BWI Systeme (HERKULES Projekt). Danach hieß es "zurück nach Mannheim" zum studieren - fast jedenfalls.
Vorher waren noch drei Wochen Projektarbeit bei der IBM Deutschland in Mainz angesagt - woran ich gearbeitet habe, kann ich leider nicht sagen (ich sage nur, dass mir der Ausdruck "Highly Confidential" mittlerweile zum Halse heraushängt - vor allem, weil dieser Umstand einem die Arbeit nicht sonderlich erleichtet). Was ich vielleicht erwähnen darf, ist jedenfalls, dass es was mit programmieren zu tun hatte.

Diese drei Wochen Projektarbeit sind nun vorbei. Parallel durfte ich jedoch auch noch einen Fachtext schreiben (insgesamt sind es 37 Seiten zum schönen Thema "Multi-Tiered Application Development in Java" [anhand einer selbst-geschriebenen Middleware-Lösung] geworden). Das Schlimmste war jedoch, den gesamten Papierkram zu erledigen (im speziellen: Unterschriften aus Berlin und Brandenburg zu organisieren, während man selbst in Mainz und Mannheim ist). Als Anhaltspunkt: heute war der letzte Termin, bei dem es noch nicht zu Umständlichkeiten gekommen wäre - gestern Abend trudelten die letzten Unterschriften mit der deutschen Post ein.

Und um zu zeigen, was noch zu tun ist:
  • Anfangen, für die Java-Klausur am Montag zu lernen

  • zu Montag ein vollständiges Programm für Java entwickeln

  • zu Freitag einen Fachtext "analogies of human and computer communication" schreiben

Nebenbei normales Studium und das Projekt für die IBM Mainz.
Das ist der derzeitige Stand, was das zeitliche angeht.


Nun aber zu dem interessanteren Thema: Was ist mit Chest?

Wie man sich vorstellen kann, blieb zuletzt nicht viel Zeit dafür - jedoch waren bereits ein paar Dinge in Aussicht, die nur noch nicht öffentlich gemacht wurden.

Da erkenntlich geworden ist, dass es durchaus umständlich werden würde, bei Methoden jedes mal ein Ergebnis einer Methode über einen Zugriff auf ein Feld des Ergebnisses (das an sich ein Objekt ist) zu erledigen, wurde von mir die Idee eingeführt, dass nicht jede Methode unbedingt eine neue Klasse darstellen muss.

Anstelle also wie hier, für einen einfachen Integer-Rückgabewert eine eigene Klasse zu haben...
Sum get (NumberA as Integer; NumberB as Integer;)
set (Result as Integer;)
begin
Result := NumberA + NumberB;
end;

...sollte es möglich sein, einen bereits bestehenden Typ einfach nur zu benutzen.
Sum get (NumberA as Integer; NumberB as Integer;)
set Integer
begin
This := NumberA + NumberB;
// Ob es nun "This" oder anders heißt,
// ist noch nicht raus
end;


Dieses Vorgehen würde sich nahtlos mit der jetzigen Vorgehenweise (definieren einer neuen Klassenstruktur) vereinigen lassen.


Als zweiter Punkt zu einer (vielleicht) unwichtigeren Sache, die jedoch nicht unerwähnt bleiben sollte - aufgrund dessen, dass bestimmte Operatoren eine Mehrfachdeutung erlaubt hätten, wurde für die Zuweisung der aus Pascal bekannte Operator ":=" eingeführt.

Der genaue Grund ist folgender: (überspringen, falls uninteressant)
Da Chest fast vollständig objektorientiert sein wird, wurde überlegt, wie man die Nutzbarkeit dieses Konzeptes vereinfachen könnte. Das Ergebnis ist, dass Objekte zwar immernoch Objekte sind, jedoch einfacher zu handhaben sein werden (nämlich in etwa wie native Typen). Das bedeutet z.B., dass eine Variablenzuweisung nicht zu einem Kopieren der Referenz führt, sondern zum Duplizieren des entsprechenden Objektes führt. Da das Kopieren von Referenzen jedoch genauso einfach gehen sollte, wurde eine Referenzzuweisung eingeführt ("^=").
Und genau hier liegt das Teilproblem: die Referenzen, die in Chest eine höhere Funktionalität aufweisen, als in Java.
In Chest ist es möglich durch ein ^Bezeichner das entsprechende Objekt zu referenzieren und durch ein Bezeichner^ wieder zu dereferenzieren.
Angenommen, wir hätten also ein einfaches Ist-Gleich als Zuweisungsoperator, so könnte ein Bezeichner^=x; nicht eindeutig als Referenzzuweisung (Bezeichner ^= x; - alternativ auch als ^Bezeichner := ^x; schreibbar) oder als Wertzuweisung an das dereferenzierte Objekt (Bezeichner^ := x;) identifiert werden. Deshalb dieser Schritt des geänderten Zuweisungsoperators.


Des weiteren wurde beschlossen, einen constants-Bereich einzuführen. Ob es einen properties-Bereich mit einer ähnlichen Funktionalität wie den Pascal-Properties geben wird, steht noch nicht fest.


Ein besonderes Feature, das hoffentlich ein wenig Anklang finden wird, ist, dass es möglich sein würden, Klassen bei der Ableitung zu überschreiben. Das bedeutet z.B., dass es möglich sein wird, eine Klasse String zu definieren, die von der Klasse String erbt. Bindet man nun die entsprechende Klasse ein, steht die neue Version zur Verfügung, ohne, dass es Quelltextänderungen vorgenommen werden müssen.


Nun zur letzten großen Entscheidung, die bisher jedoch noch nicht vollständig gefällt wurde.
Und zwar kam die Idee auf, anstatt von begin und end; zur Markierung von Quelltext-Blöcken lieber kontextbezogene Blöcke zu nutzen.
Ein Beispiel wäre z.b. ein if (true) do ... endif; bzw. eine Variante, die bisher schon teilweise zum Einsatz kommt: if (true) do ... if;.
Code-Blöcke würden dann eventuell in einem code ... code; eingeschlossen werden.

Die Hauptfrage ist, wie man am besten eine einheitliche Syntax hinbekommt, die so wenig Ausnahmen beinhaltet wie möglich - und hier ist die zweit-gezeigte Variante wirklich gut zu gebrauchen, abgesehen davon, dass die Lesbarkeit erhöht wird, da Probleme, wie das Auszählen von Begins und Ends, so weit wie möglich entfallen.


Ich denke mal, dass das nun aber wirklich genug Informationen für heute waren.


Bis demnächst...
Wirsing

Labels: ,

Dienstag, 23. Oktober 2007

Weitere Sprachfeatures

Nach einer etwas längeren Auszeit aufgrund von Serverproblemen ist der Blog nun wieder da. In diesem Zuge wurde der Blog auch gleich auf schönere Füße gestellt.
So ist er nicht mehr unter http://coltishware.com/~chest/ erreichbar, sondern nur noch ausschließlich unter der Subdomain http://chest.coltishware.com .
Aus diesem Grund müssen auch diejenigen, die den RSS-Feed abonniert haben, dies noch einmal tun, damit die Adressen übereinstimmen.
Sollte es noch einmal vorkommen, dass der Server ausfällt, so wird dieser Blog, wie dieses Mal, wahrscheinlich für die diese Zeit unter http://coltishware.blogspot.com zu finden sein.


Aber nun zum eigentlichen Thema...

Ich wurde letztens darum gebeten, eine Übersicht über die zeitliche Planung des Projektes abzugeben. Da solche zeitlichen Planungen sich nur selten an die Wirklichkeit halten, habe ich stattdessen einen groben Ablaufplan skizziert, der die einzelnen Phasen der Entwicklung zeigt.
  1. Sprachfeatures sammeln und in einen einheitlichen Sprach(-syntax-)kontext einfügen

  2. anhand der sprachfeatures den benötigten bytecode ausarbeiten (was muss die VM können, was kann durch Programmierung in ByteCode emuliert werden)

    1. die VM schreiben

    2. einen Source-zu-ByteCode-Compiler schreiben

  3. evtl. fehler an der Sprache ausmerzen

Zur Zeit befinden wir uns beim ersten Hauptpunkt - ohne Übersicht der Sprachfeatures kann man keine optimierte ByteCode-Sprache entwickeln.

Und da es bezüglich der Features noch etwas mager aussieht, gibt es noch ein paar neue, die ich an dieser Stelle vorstellen möchte.
Zum einen wurde noch nicht erwähnt, dass Chest case-insensitive sein wird, sprich: in der Sprache wird nicht zwischen Groß- und Kleinschreibung von Bezeichnern und Befehlen unterschieden werden.
Alles andere führt unweigerlich zu Fehlern, die auch problemlos umgangen werden können.
Desweiteren wurde ich darauf hingewiesen, dass ich mich noch nicht zu dem Thema Generics geäußert habe. Natürlich werden diese in der Sprache integriert sein.

In diesem Zuge wird ein weiteres Sprachfeature Einzug in Chest halten. An dieser Stelle möchte ich mich herzlich bei Christian Rehn (alias R2C2) bedanken, durch den ich die Idee für dieses wirklich wunderbare Sprachfeature überhaupt erst bekommen habe.
Zur Zeit hat es noch den Namen Code Injection, jedoch hoffe ich, dass mir früher oder später noch ein besserer Name dafür einfallen wird.
In bisherigen Szenarien ist es vor allem in Verbindung mit Generics aufgetreten und wird dort sicherlich gute Dienste tun.

Erst einmal ein Quelltextbeispiel, um daran die Funktion zu erklären:
//angenommen, MyArray.find ist so definiert:
find set (Result as LongInt)
provide (Item as )
retrieve (Return as Boolean) is providing;

{...}

find set (Result as LongInt)
provide (Item as )
retrieve (Return as Boolean)
variables
Index as LongInt;
variables;
begin
Result = -1;

for Index = Low(Self) to High(Self) do
begin
// if retrieve(provide(Self[Index])).Return do
if provide(Self[Index]).Return do
begin
Result = Index;

break;
end;
end;
end;

{...}

//Aufruf von MyArray.find() mit
//zusätzlich injiziertem Code
//und direktem Auslesen des
//Rückgabewertes "Result"
myResult = MyArray.find()
begin
Return = (Item.Name = 'SomeText');
end.Result;

Nun zur Erklärung des Codes:
Die Methode find() (hier von einer imaginären Klasse MyArray) ist hier als providing deklariert. Dieser Punkt ist wichtig, um dem Interpreter zu sagen, dass die Methode es erlaubt, eigenen Code in ihr auszuführen.
Zudem sind neben dem set-Feld zusätzlich noch die Felder provide und retrieve definiert. Diese sind für die Ausführung des injizierten Codes sehr wichtig: sie stellen den Kopf des injizierten Codes dar. provide steht dabei für die Werte die dem injizierten Code übergeben werden und retrieve steht für die Werte, die vom injizierten Code zurückgegeben werden.
Mit provide(Self[Index]) wird der injizierte Code aufgerufen. Da es sich intern um eine normale Methode handelt, kann demzufolge mit provide(Self[Index]).Return auch der Rückgabewert der Methode angesprochen werden. Der eigentlich ausgeführte Text ist dabei Return = (Item.Name = 'SomeText');.
Diese Variante erpart viel Tipparbeit im Vergleich zur Übergabe von Methodenreferenzen und hat zudem die Möglichkeit, dass für verschiedene Implementierungen von Generics verschieder Code eingefügt und ausgeführt werden kann.
So ist es erstmalig möglich, eine Suchfunktion in einem Generic zu implementieren und lediglich die Überprüfung der genauen Felder auszulagern.

Ich hoffe, diese Erklärung war zumindest annähernd verständlich. Das Feature selbst ist einfach zu nutzen, jedoch schwer zu erklären.
Sollte es also Fragen geben: einfach Fragen... ;-)


Bis demnächst...
Wirsing

Labels: ,

Donnerstag, 11. Oktober 2007

Erste Sprachbeispiele

updated

Ich will nur erst einmal die Informationen loswerden.
Erklären werde ich alles über ein späteres Update.

Ich dachte mir, es wäre einmal interessant, einen kleinen Einblick in den bisherhigen Sprachaufbau zu geben.

Fangen wir am besten mit dem Klassen-Aufbau an:
Wie zu erkennen ist, ist zur Zeit echte Mehrfachvererbung vorgesehen.
Wie in an C++ angelehnten Sprachen üblich, ist der eigentliche Quelltext in der Klassendefinition mit eingeschlossen.
Ein Problem, das mir bei Java aufgefallen ist, ist, dass Methoden und Variablen im ganzen Klassen-Block verstreut sein können. Da versteckt sich mitunter eine private Methode unter einem Haufen public Methoden oder vice versa.
Um den ein bisschen entgegenzuwirken und den Quelltext aufzuräumen, gibt es Sektionen - für jede Sichtbarkeitsebene (private, protected und public) jeweils eine. Jedoch mit einem Unterschied: den Bezeichnungen.
Was ist denn der Unterschied zwischen private und protected?
Warum sollte ich das eine hierfür und das andere dafür benutzen?
Um ein bisschen Licht ins Dunkel zu bringen, werden neue Bezeichner für diese Sichtbarkeits-Ebenen benutzt, die dem ganzen (hoffentlich) mehr Klarheit verschaffen. In Chest wird es daher folgende Ebenen geben:
  • implementation (= private)
    hier definierte Variablen und Methoden sind nur der Klassen-Implementation zugänglich

  • inheritor (= protected)
    hier definierte Variablen und Methoden sind nur der Klassen-Implementation und deren Erben (engl. inheritors) zugänglich

  • public
    hier definierte Variablen und Methoden sind jedem zugänglich

Desweiteren ist jede Sektion noch einmal in 2 Unter-Sektionen aufgeteilt: variables und methods. Es dürfte klar sein, dass Variablen in dem einen Block und Methoden (inkl. deren Quelltext) in dem anderen Block definiert werden.


Class-Definition:
<ClassName> inherits <ClassName> [, <ClassName>]

//... contains variables and methods that
//... are available to this class
implementation
variables
//... some variables
variables;

methods
//... some methods
methods;
implementation;

//... contains variables and methods that
//... are available to this class and
//... to inheriting classes
inheritor
variables
//... some variables
variables;

methods
//... some methods
methods;
inheritor;

//... contains variables and methods that
//... are available to all classes
public
variables
//... some variables
variables;

methods
//... some methods
methods;
public;

<ClassName>;


Nun kommen wir einmal zur Variablen-Deklaration:
Dieser ist eigentlich relativ einfach. Da Chest eine "sprechende" Programmiersprache sein soll, wird eine Variable auch einfach als ein "<Name> als <Typ>" definiert.


Variable-Definition:
<Name> as <Type>;


Auch bei der Definition von Methoden gibt es keine Zauberei:
Jedoch gibt es im Gegensatz zu anderen Sprachen keine "einfachen" Rückgabewerte mehr. Stattdessen definiert man für jede Methode eine List von Rückgabewerten. Dadurch spart man sich Parameter-Strukturen, die in anderen Sprachen Gang und Gebe sind (z.B. var-Parameter in Pascal, Reference-Übergaben wie in C, C++, etc.). Stattdessen definiert man einfach weitere Rückgabewerte.
Nun mag man sich fragen: "Wie soll man mehrere Rückgabewerte auslesen können?"
Schließlich will man eine Methode ja nicht mehrfach aufrufen, nur um dann jeweils einen weiteren Rückgabewert auszulesen, wie z.b. in:
begin
println(Calculate(5, 5).Add);
println(Calculate(5, 5).Divide);
println(Calculate(5, 5).Multiply);
end;

Um solche Probleme zu umgehen, wird ein besonderer Trick angewendet, den ich schon länger mit mir umhertrage: "Warum betrachtet man Methoden nicht wie Klassen?"
Diese Idee ist ja teilweise schon im Umlauf - z.B. ist in Java der Konstruktur einer Klasse einfach deren Name (der Rückgabe der Methode ist eine Klasse mit dem Namen der Methode). So etwas kann man doch auch für normale Methoden einführen - eben um die Rückgabewerte darin zu speichern. Um dies zu erreichen, muss also für jede Methode ein eigener (dynamischer) Typ im Hintergrund generiert werden. Dadurch sind dann soetwas möglich:
variables
MyVariable as Calculate;
variables;
begin
MyVariable = Calculate(5, 5);

println(MyVariable.Add);
println(MyVariable.Divide);
println(MyVariable.Multiply);
end;


Nun aber noch zu ein Paar weiteren Dingen:
Neben normalen Methoden wird es noch abstrakte Methoden (is abstract) geben. Dabei handelt es sich lediglich um die Definition einer Methode ohne deren Implementierung. Dadurch ist es möglich, eine Form von Interfaces zu schreiben.
Des weiteren wurde ja bereits angesprochen, dass Chest die Möglichkeit der Mehrfachvererbung erhalten soll. Nun ist jedoch die Frage, was sein soll, wenn zwei Superklassen einer Klasse Methoden besitzen, die genau gleich definiert sind (Name und Parameterliste stimmen überein), sodass die Methoden nicht als überladen definiert sein können.
Für diesen Fall gibt es das Renaming (is <ClassName>.<MethodName>). Durch dieses wird es möglich, Methoden einer Superklasse in einem Nachkommen unter einem neuen Namen anzubieten. Diese Möglichkeit ist natürlich genau dann nützlich, wenn man Namenskonflikte bei verschiedenen Elternklassen auflösen muss.


Method-Definition:
<MethodName> get ([<Name> as <Type>;])
set ([<Name> as <Type>;])
is abstract;
<MethodName> get ([<Name> as <Type>;])
set ([<Name> as <Type>;])
is <ClassName>.<MethodName>;

<MethodName> get ([<Name> as <Type>;])
set ([<Name> as <Type>;])
variables
//... some variables
variables;
begin
//... some sourcecode
end;


Zum Schluss gibt es noch einmal ein kleines Quelltext-Beispiel.

Calling a Method
  //...

returnLongWord get (Value as LongInt;)
set (Result as LongWord;)
begin
Result = LongWord:Value;
// cast Value to a LongWord (not yet sure)
end;

//...

variables
myValueA as retunLongWord;
myValueB as LongWord;
variables;
begin
myValueA = returnLongWord(5);
println(myValueA.Result);

myValueB = returnLongWord(5).Result;
println(myValueB);

println(returnLongWord(5).Result);
end;

//...


So, damit wäre dieses größere Update auch schon zu Ende.
Ich hoffe, der Einblick in den derzeitigen Sprachaufbau war für euch interessant.

Man beachte aber bitte, dass Dinge wie "println()" und das Type-Casting nur als Platzhalter zu verstehen sind. Hier ging es erst einmal um die im Text näher beschriebenen Sprachfeatures.
Über Änderungen halte ich euch natürlich auf dem Laufenden!



Bis demnächst...
Wirsing

Labels: ,

Freitag, 5. Oktober 2007

Ideen zur Sprache

Wir haben wieder einmal Freitag: sprich, es wird Zeit für die neusten Informationen.
Heute möchte ich einmal über die Entwicklung der Sprach-Syntax schreiben.

Wie man sich vorstellen kann, ist es garnicht so einfach, in diesem Bereich Entscheidungen zu fällen: wenn man sich zu sehr an einer existierenden Sprache orientiert, kann es passieren, dass man diese einfach nur re-implementiert; jedoch muss man auch darauf achten, dass die Sprache gut zu erlernen ist - und da kann man sich bei bestehenden Sprachen ruhig eine Scheibe abschneiden.
Generell ist zudem zu beachten, dass die Sprache die gebotenen Sprachfeatures unterstützen und diese möglichst nahtlos in den Programmierfluss mit einbringen sollte.
Sprich: die Sprache ist abhängig vom Funktionsumfang der Sprache.
Daher sollte auch von Anfang an grob umrissen sein, welche Features die entsprechende Sprache unterstützen soll.
Auf ebendiese Features bin ich im letzten Posting schon einmal kurz eingestiegen.

Ein Beispiel: die Sprache soll den Speicherzugriff ermöglichen und diesen soweit möglich managen - die Speicherzugriffe selber sollten jedoch nicht zur Standard-Arbeit des Programmierers gehören. Daher wäre es hier z.B. ratsam, Bezeichner für Kern-Methoden von normalen Methoden abzuheben.
Dadurch erkennt man sofort, wo im Quelltext System-Funktionen genutzt werden - durch dieses Vorgehen kann ein Entwickler auch viel schneller mögliche Problembereiche im Quelltext ausfindig machen (moderne Programmiersprachen versuchen schließlich nicht umsonst, den Entwickler von heute von der Arbeit am Speicher abzukoppeln).

Nun aber zu einigen der im Titel versprochenen Ideen der Sprache: und da fangen wir auch direkt mit einem der wichtigsten Punkte an - das Einschließen von Code-Blöcken.
Es ist erschreckend, aber fast alle Sprachen benutzen dafür Klammern - am liebsten die geschweiften "{" und "}".
Nur einige Sprachen (z.B. Pascal) benutzen hierfür echte Codewörter.
Da diese Klammern überall im Quelltext auftauchen, prägen sie entscheidend das Erscheinungsbild einer Sprache und lassen sie dementsprechend (un-) strukturiert aussehen. Leider musste ich in meiner Laufbahn schon mehrfach feststellen, dass Programmierer Klammern zwar toll finden, da sie schnell einzutippen sind und da sie gut dafür geeignet sind, Blöcke zu kennzeichen (man schließt den Quelltext ja in einer Klammer zusammen), die meisten jedoch schnell in einen Trott bei der Klammer-Einrückung verfallen.
Warum für die eine kleine schließende Klammer nochmal eine ganze Zeile vergeuden - die sieht doch dann so leer aus. Und schon verschwindet die schließende Klammer hinter einem Befehl und fällt dort nicht weiter auf - zumindest bis diese eine Zeile bei Aufräumarbeiten gelöscht wird und der Compiler auf einmal Fehler über Fehler ausspuckt, weil irgendwo eine Klammer fehlt. Nur welche? Das ist die Frage.
Aus diesem Grund wird es in Chest Codewörter für das Bilden von Code-Blöcken geben - sie helfen dem Programmierer, eine gewisse Struktur zu wahren.

Insgesamt ist Chest als "sprechende Sprache" geplant - soweit es den Programmierfluss nicht stört, ist es angedacht, sprechende Codewörter statt kryptischer (leicht parsebarer) Sonderzeichen einzuführen und dem Programmierer auf diese Art und Weise eine Programmiersprache und keinen Programmierzeichensatz anzubieten.

So, das soll es für heute erst einmal gewesen sein...


Bis demnächst...
Wirsing

Labels: ,

Freitag, 28. September 2007

Warum Chest?

updated

Heute habe ich mir vorgenommen zum Beginn des Wochenendes mal ein bisschen mehr zu schreiben - und zwar dazu, warum es Chest überhaupt geben soll.

Diese Frage wurde mir schon x-fach gestellt, deswegen hoffe ich mal, dass die Antwort schon halbwegs gut formuliert ist. ;-)
Wie bei allem steht natürlich der Lerneffekt im Vordergrund - wie damals auch schon bei AlPhAbEt.
Seitdem haben sich meine Fähigkeiten in den Bereichen Parser-, Scanner- und Interpreterbau jedoch weiterentwickelt und ich möchte endlich einmal eine ordentliche höhere Sprache designen.

Achja... Und dann gibt es da noch einen Grund: Java ist zum kotzen.
Das soll kein politisches Statement sein - schließlich bin auch ich jemand, der (zur Zeit) vollzeit mit dieser Sprache arbeitet.
Jedoch wurden bei der Entwicklung von Java Entscheidungen getroffen, durch die die Sprache sehr viel an Potential einbüßen musste.
Das fängt schon bei den nicht-vorhandenen unsigned Typen an - ich will einfach keine BINÄR-Daten haben, in denen negative Werte vorkommen.
Der viel gravierendere Aspekt ist jedoch die komplette "Abkoppelung" vom System.
Abkoppelung in Anführungszeichen, da diese System-Zugriffe schon vorhanden sind, nur eben so versteckt und so tief im System vergraben, dass man als nutzender Programmierer nicht in der Lage ist, selbst Einfluss darauf zu nehmen.
(Beispielsweise ist im openJDK schön zu sehen, dass der Dateizugriff in Java über einfachen C-Code realisiert wird. Warum wird mir als Entwickler aber verwehrt, ebenso nach außen kommunizieren zu können?)
[Ich bin letztens über die JNI (Java Native Interface) gestolpert. Diese unterstützt tatsächlich das Einbinden von externen Resourcen. Allerdings ist in meinen Augen auch hier die eingesetzte Variante lediglich suboptimal.]

Einige mögen nun sagen, dass dies deshalb getan wurde, um die Sicherheit der Sprache zu erhöhen.
Das bedeutet im Umkehrschluss, dass Sun der Meinung ist, dass ihre Programmierer eher dazu geeignet sind, sicherheitskritischen Code zu schreiben, als externe Entwickler.
Auch sind viele nützliche Dinge mit dem Speicher allein deshalb nicht machbar, weil man unbedingt ein vollständiges Speicher-Management anbieten wollte.
Das ist an sich nicht das Problem, sondern eher, dass man sich die Sache leicht gemacht hat, anstatt das Speicher-Management ordentlich zu programmieren und dadurch auch komplizierten Speicherzugriff zu ermöglichen.
Oder wie schnell können Sie mir die Byte-Darstellung eines double-Wertes beschaffen, ohne über die Double-Klasse gehen zu müssen - bei der man zudem noch nicht mal weiß, wie es denn dort implementiert wurde und warum dort etwas getan werden kann, dass man nicht selber programmieren kann?

Kurz gesagt soll Chest folgendes werden:

  • eine ordentlich designte Programmiersprache mit ausgewählten Elementen aus verschiedenen Sprachen sein

  • auf einer eigenen virtuellen Maschine basieren

  • ein Plugin-Interfacing für die VM bieten, durch das Systemzugriffe für Chest-Programme ermöglicht werden sollen

  • eine ausgefeilte Speicherverwaltung bieten, die zum einen vollständige Garbarge-Collection und Speicherzugriffs-Kontrolle bietet, aber trotzdem ordentliches Arbeiten mit dem Speicher erlaubt


Es ist viel zu tun und es wird sicher nicht immer einfach sein, aber wenn das Ergebnis erst einmal zu sehen ist, wird man erkennen, dass es sich gelohnt hat.


Bis demnächst...
Wirsing

Labels: , ,