Script-Engine (Compiler+Interpreter) entwickelt

Alles, was nicht direkt mit Python-Problemen zu tun hat. Dies ist auch der perfekte Platz für Jobangebote.
Antworten
Arakis
User
Beiträge: 6
Registriert: Dienstag 21. November 2006, 10:52

Ich habe einen Script-Kompilierer/-Interperter in .NET geschrieben, um Scripte in einer speziellen Sprache auszuführen, ohne dass dabei temporäre Assemblies den Speicher zumüllen. Die Syntax ist an Java/PHP/c# angelehnt. Die Script-Engine selbst ist in VB.NET geschrieben.

Die Script-Engine bietet folgendes:
- Alle gängigen Sprachelemente wie Deklaration, Schleifen, Bedingungen, Eigene Funktionen, ...
- Objektorientiert(Klassen müssen zuvor in .NET geschrieben worden sein)
- Kann in jedes beliebige .NET Programm eingebunden werden um Dinge zu automatisieren/anpassbar zu gestalten.
- Bei Beendigung eines Script wird der reservierte Speicher wieder freigegeben, es bleiben keine Temporären Assemblies wie bei einer nativen .NET Kompilierung im Speicher.
- Die Script-Engine kann so eingestellt werden, dass sie wie eine Sandbox arbeitet, in der auch unsicherer Code ausgeführt werden kann.
- Die Script-Engine kann aber auch so eingestellt werden, dass sie Vollzugriff auf die Host-Anwendung hat.
- Das Einbinden der Script-Engine in die eigene Applikation ist sehr einfach.
- Für nicht-kommerzielle Nutzung kostenlos.

Hier ist die Projekt-Url: http://scripting.larne.de

Leider habe ich noch nicht viel Doku geschrieben :/

Ich bin für jedes Feedback dankbar.

Grüße,
Sebastian
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8500
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Arakis hat geschrieben:Die Syntax ist an Java/PHP/c# angelehnt.
Mir wird gleich übel... :?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Arakis
User
Beiträge: 6
Registriert: Dienstag 21. November 2006, 10:52

Man könnte auch meinen es könne einem von Python übel werden, wobei ich da Perl noch um einiges krasser finde von der Syntax her. Aber es wäre schön wenn wir uns darauf einigen könnten sachlich und konstruktiv zu bleiben.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8500
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Es war nur ein spontaner Gefühlsausbruch ;)

Mir ist auch klar, das es einfacher ist, einen Parser zu schreiben der sich auf Steuerzeichen bezieht, als einen wie der von Python :) Dafür bleiben uns Python anhänger aber so unsinnige Zeichen wie {...} erspart, um Blöcke zu markieren. Außerdem muß man nicht die IMHO unsinnigen ; am Ende von *jeder* Zeile/Befehl schreiben...

Wenn ich mal ein wenig JavaScript schreibe, vergesse ich nämlich des öfteren ein Semikolon am Ende :?

Das Beispiel von deiner Seite:

Code: Alles auswählen

Var List As New ArrayList();
Var i As Integer = 0;
For (i=0 To 10)
{
  List.Add(i*2);
};

Var Value As Integer = 0;
For (Each Value In List)
{
  WriteLine(Value);
};
In Python:

Code: Alles auswählen

List = []
for i in xrange(10):
    List.append(i*2)

Value = 0
for item in List:
    print Value
Wobei mir irgendwie nicht klar ist, was die zweite Schleife bei dir macht, deswegen macht die in Python nicht wirklich viel Sinn...

Gut, der Python code ist kleiner, weil man halt keine Typen bestimmen muß... Aber dennoch, durch die fehlenden Markierungszeichen ist es einfach klarer...


btw. Warum machst du das überhaupt??? Es gibt doch IMHO ein paar Skriptsprachen, u.a. auch Python, für .NET...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8500
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Weil es Spass macht, noch ein Beispiel:

Code: Alles auswählen

VAR var1 AS Integer = 42;
if (var1 < 42)
{
  WriteLine('var1 ist kleiner als 42');
}
elseif (var1 > 42)
{
  WriteLine('var1 ist größer als 42');
}
else
{
  WriteLine('var1 ist weder größer noch kleiner als 42');
}
in Python:

Code: Alles auswählen

var1 = 42
if var1 < 42:
    print 'var1 ist kleiner als 42'
elif var1 > 42:
    print 'var1 ist größer als 42'
else:
    print 'var1 ist weder größer noch kleiner als 42'
EDIT: Ach, was mir da noch auffällt... Muss nicht bei deinem IF-Beispiel ganz am Ende ein Semikolon??? Ich hab das ganze von http://scripting.larne.de/wiki/index.ph ... =Anleitung

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

jens hat geschrieben:Es war nur ein spontaner Gefühlsausbruch ;)
Spätestens wenn man die Doku liest ist der durchaus sachlich gerechtfertigt. :twisted:

Da wird ungarische Notation der übelsten Sorte empfohlen. Mir ist jetzt auch schlecht. :?
Mir ist auch klar, das es einfacher ist, einen Parser zu schreiben der sich auf Steuerzeichen bezieht, als einen wie der von Python :) Dafür bleiben uns Python anhänger aber so unsinnige Zeichen wie {...} erspart, um Blöcke zu markieren.


Die Blöcke sind relativ einfach zu parsen. Man muss sich im Lexer nur die Einrückung der vorhergehenden Zeile merken, mit der aktuellen vergleichen und falls beide unterschiedlich sind ein entsprechendes Token für '{' oder '}' liefern. Das ist nur ganz minimal aufwändiger als die Klammern direkt im Quelltext zu haben.
Arakis
User
Beiträge: 6
Registriert: Dienstag 21. November 2006, 10:52

@jens: Richtig, im Prinzip muss da auch ein Semikolon hin, aber da eine geschweifte Klammer im prinzip immer "anweisung beendet" bzw. "code block zu ende" bedeutet, ist es halt nicht unbedingt nötig. Der Parser selbst ist nicht unbedingt der beste, der akzeptiert es manchmal sogar wenn man vergisst klammern zu schließen - nur wird dann auf grund der rekursion die ganze anweisung nicht ausgeführt.
BlackJack

Ich habe die beiden Beispiele mal mit meiner Lieblings-.NET-Sprache umgesetzt:

Code: Alles auswählen

using Nemerle.Collections
using System.Console
using System.Math

def Liste = List.Range (1, 11) . Map (fun (x) { x * 2 })
Liste.Iter(WriteLine : (int -> void))


def Var = 42

def CompareWith42 (value)
    match (Sign (value - 42))
        |  0 => "weder grösser noch kleiner"
        |  1 => "grösser"
        | -1 => "kleiner"
        |  _ => assert (false)  // Should never happen.

WriteLine ("Var ist {0} als 42.", CompareWith42 (Var))
Die Einrückungssyntax wie bei Python gefällt mir besonders gut. Man kann allerdings auch '{}' benutzen, deshalb sind anonyme Funktionen (``fun``) mächtiger als in Python.

Nemerle ist statisch typisiert, versucht aber wo es möglich ist die Typen selbst zu ermitteln. Im Beispiel da oben musste ich nur beim Iterieren über `Liste` nachhelfen, weil es von `System.Console.WriteLine` zwei Varianten gab die vom Typ her passen.
Arakis
User
Beiträge: 6
Registriert: Dienstag 21. November 2006, 10:52

jens hat geschrieben:btw. Warum machst du das überhaupt??? Es gibt doch IMHO ein paar Skriptsprachen, u.a. auch Python, für .NET...
Wenn du ein bestehendes .NET Programm mit Scripten automatisieren möchtest, kann man dies über Plugins oder temporär kompilierten Assemblies lösen. Nachteil ist, dass einmal geladene Assemblies nicht mehr entladen werden, sofern sie in der selben Appdomain geladen wurden. Ist der auszuführnde code jedoch in einer anderen appdomain, so muss .NET Remoting her und dann wird's "Langsam" und das ganze bricht in einer schnittestellen definitions chaos aus, wenn man z.b. 100 klassen hat, welche man veröffentlichen will, welche zig unterobjekte haben. Deshalb habe ich eine Script-engine geschrieben, welche in der selben appdomain laufen kann, im selben prozess und vollzugriff auf sämtlche vorgänge des Host-prozesses hat, sofern man diesen erteilt.

Scripte können so endlos oft während der Laufzeit geändert werden, ohne dass der Speicher mit temporären Assemblies zugemüllt wird - Denn es werden gar keine Assemblies kompiliert, sondern es wird eine zwischen struktur geparst, welche dann rasch ausgeführt werden kann mit dem Larne Script Interpreter.

Grüße,
Sebastian
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Arakis hat geschrieben:Man könnte auch meinen es könne einem von Python übel werden, wobei ich da Perl noch um einiges krasser finde von der Syntax her. Aber es wäre schön wenn wir uns darauf einigen könnten sachlich und konstruktiv zu bleiben.
Dem schließe ich mich an. Formulierungen wie "da wird mir übel finde ich auch" äußerst unpassend und lässt auf lange sicht eine Community lächerlich erscheinen, weil viele dazu neigen auf Grund dessen alle über eine Kam einer Comunnity zu scheren. Stichwort: GIGA, Gamestar etc.

So ein wenig Sachliche Kritik: Mir gefällt die entliehene Syntax nicht so gut. Ich fühle mich dabei nicht so wohl. Das liegt zum teil auch daran das mich teilweise die Deklaration von Variabeln an Basic (oder wars Pascal. Schon zu lange her ^^) erinnert.
BlackJack hat geschrieben:
jens hat geschrieben:Es war nur ein spontaner Gefühlsausbruch ;)
Spätestens wenn man die Doku liest ist der durchaus sachlich gerechtfertigt. :twisted:

Da wird ungarische Notation der übelsten Sorte empfohlen. Mir ist jetzt auch schlecht. :?
[…]
Sry, du wärst der letzte gewesen von dem ich so ein Statement erwartet hätte :/ :-[ :?
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8500
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mensch XtraNine du hast es heute aber nicht so mit dem Humor, was? Wäre doch ein wenig langweilig, so ganz ohne...

Ich denke gerade unser Forum ist recht offen und hilfsbereit... Natürlich sind wir alle mehr oder weniger fixiert auf Python, aber das ist wohl nicht sehr verwunderlich, oder?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Wenn jemand mit einer Sprache daherkommt die in Syntax und Konventionen sozusagen das Gegenteil von Python ist, dann sollte er ein paar bissige Kommentare mit Smilies vertragen können. IMHO.

Das was die Sprache zu lösen versucht, sollte man besser an anderer Stelle in Angriff nehmen, nämlich dort wo die .NET Laufzeitumgebung die Assemblies nicht wieder verwirft und den Speicherplatz freigibt. Wenn man das Problem nämlich an der Stelle beseitigt, kann man plötzlich *alle* .NET Sprachen für's Skripting mit "Speicherdiät" verwenden.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8500
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

@Arakis: Sag mal, nur interessehalber, was machst du eigentlich genau, das du überhaupt auf .NET angewiesen bist?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

jens hat geschrieben:Mensch XtraNine du hast es heute aber nicht so mit dem Humor, was? Wäre doch ein wenig langweilig, so ganz ohne...

Ich denke gerade unser Forum ist recht offen und hilfsbereit... Natürlich sind wir alle mehr oder weniger fixiert auf Python, aber das ist wohl nicht sehr verwunderlich, oder?
Naja ok, kann auch sein das ich das alles heute falsch interpretiere. :? Naja, Sorry falls sich dadurch jemand angegriffen gefühlt hat. :/
Arakis
User
Beiträge: 6
Registriert: Dienstag 21. November 2006, 10:52

@BlackJack: Du hast es begriffen ^^

@Jens: Ich entwickel in .NET seit dem es rausgekommen ist(vorhaber aber viel in Delphi) und da es ursprünglich für mein Internetspiel gedacht war, welches ebenfalls in .NET geschrieben ist( http://stne.net ), sprach nichts dagegen es auch in .NET zu schreiben. Außerdem ist so ein integrierter Garbage collector recht nützlich :twisted: Da mir viele sagten dass die Script Engine echt gut ist, habe ich sie nun veröffentlicht.

Die Sprache ist an alles mögliche angelehnt, ich habe mir bei jeder Syntax überlegt, wie man sie am ehensten akzeptieren könnte. Der eine hasst Pyhton, der andere perl, wieder andere c++/javascript ({}), andere pascal und die meisten halt vb. Die Syntax sollte nicht zu komplex zu begreifen sein, vernünftig lesbar und leicht verständlich für jemanden mit grundkenntnisssen in der Programmierung, schließlich sollte die Sprache massentauglich für meine Spieler werden. Aber wie BlackJack es schon erkannt hat, es geht nich um die Sprache, sondern um die Engine, und dessen Möglichkeiten. Und dass das Framework irgendwann mal lernt Assemblies zu entladen ohne die ganze Appdomain zu entladen, wage ich zu bezweifeln.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Was mich aber nun interessiert ist wie von deiner Seite aus zukünftig der Support sein wird?

Ist das nun ein Seröses Projekt oder auch nur einer der unzähligen Sprachen die nach nem Jahr nicht mehr Supportet werden? Schließlich muss man dafür auch Zeit investieren und es wäre schade wenn die investierte Zeit zum lernen deiner Sprache verschwendet wäre, wegen mangels Weiterentwicklung, Bugfixes, etc...

lg
Arakis
User
Beiträge: 6
Registriert: Dienstag 21. November 2006, 10:52

Das kann ich dir sagen. Erstmal möchte ich schauen wie das Feedback ist, ob sowas überhaupt gebraucht wird etc. Wenn das Feedback stimmt, werde ich mich dran setzten und eine vollständige Doku schreiben. Und wenn ich ein Projekt erst mal richtig angelaufen ist, dann kümmere ich mich auch noch Jahre später drum - ich supporte noch heute ein Projekt wo ich grad mal volljährig wurde. Und als freiberuflicher Fachinformatiker muss ich mich wohl auch drum kümmern. Von daher sollte das mit der Seriösität geklärt sein.

Dennoch möchte ich anmerken, dass wenn man einmal eine Sprache "perfekt" beherrscht, das erlernen von anderen Sprachen eher im handumdrehen stattfindet, es geht dann nur noch um Syntax und Befehlssatz. Denn wie wir alle wissen, Programmieren besteht nich nur daraus, ein Handbuch auswendig im Kopf zu haben....

Grüße,
Sebastian
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Arakis hat geschrieben:Dennoch möchte ich anmerken, dass wenn man einmal eine Sprache "perfekt" beherrscht, das erlernen von anderen Sprachen eher im handumdrehen stattfindet, es geht dann nur noch um Syntax und Befehlssatz.
Dem widerspreche ich: obwohl Ruby und python ähnlich sind, programmiert man in beiden Sprachen meist anders, man nimmt andere Ansätze her. Genauso ist es auch mit Java/C-Programmen die auf Python übersetzt wurden: manchmal posten ehemalige Java/C-Programmierer ihren COde der unter Python sehr umständlich aussieht. Es ist also nicht nur Syntax, es sit auch Denkweise.

Eine andere Sache ist, warum nicht einfach die populärste embedding-Sprache nehmen, Lua.NET. Und auch wenn Lua.NET nicht ganz das gewünschte ist, kann man es ja entweder verbessern oder neu implementieren. Das fände ich sinnvoller, als irgendwelche neuen DSLs zu erstellen.

Edit (Leonidas): Thread nach Offtopic verschoben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Ich möchte mich Leonidas anschliessen. Insbesondere wenn die Sprachen einem ganz anderen Paradigma folgen wie zum Beispiel funktionale Sprachen. Wie man vielleicht an dem Nemerle-Beispiel sehen kann. Oder hier in Haskell, einer reinen funktionalen Programmiersprache:

Code: Alles auswählen

listTest = unlines (map (show.(* 2)) [1..10])

var = 42

compareWith42 value = f (compare value 42)
    where f LT = "kleiner"
          f EQ = "weder grösser noch kleiner"
          f GT = "grösser"

test42 = unwords ["Var ist", compareWith42 var, "als 42."]

main = putStrLn (listTest ++ test42)
Alles ist Funktion, alles hat einen Rückgabewert. Funktionen sind auch Werte. Nehmen wir mal den Teilausdruck ``show.(* 2)`` aus der ersten Zeile und schauen uns die Typen der Komponenten an:

Code: Alles auswählen

Prelude> :type (*)
(*) :: (Num a) => a -> a -> a
Prelude> :type 2
2 :: (Num t) => t
Prelude> :type (* 2)
(* 2) :: (Num a) => a -> a
Prelude> :type show
show :: (Show a) => a -> String
Prelude> :type show.(* 2)
show.(* 2) :: (Num a) => a -> String
``(*)`` ist also eine Funktion die zwei Argumente eines numerischen Typs entgegen nimmt und ein Ergebnis dieses Typs liefert. Auch `2` ist eine Funktion(!) die einen konstanten Wert liefert. Wenn man nun `(*)` auf `2` anwendet, dann ist das kein Syntaxfehler weil nur ein Argument übergeben wurde, sondern die Anwendung auf ein Argument ergibt automatische eine Funktion die nur noch das andere Argument benötigt. Sozusagen eine Funktion der man den Namen `verdoppeln` geben könnte:

Code: Alles auswählen

Prelude> let verdoppeln = (* 2)
Prelude> verdoppeln 42
84
Prelude> verdoppeln 23
46
`show` erwartet ein Argument das zur Typklasse `Show` gehört und liefert eine Zeichenkette. Es wandelt solche Argumente also um.

Code: Alles auswählen

Prelude> show 4711
"4711"
Mit dem Funktionskompositionsoperator, dem Punkt, kann man aus zwei Funktionen eine neue erschaffen die beide Funktionen nacheinander auf ein Argument anwenden. Es gilt also ``f.g x = f(g(x))``. So wird eine Funktion erzeugt die erst ein Element mit 2 multipliziert und dann in eine Zeichenkette umwandelt. Und diese Funktion wird auf jedes Element der Liste ``[1..10]`` angewandt.

Es gilt wie in der Mathematik, das man einer Variablen nur einmal etwas zuweisen kann und das steht dann im Laufe der Berechnung fest! Man könnte also nicht ein paar Zeilen später ``var = 23`` schreiben, das wäre ein Fehler der die Übersetzung abbricht. Es gibt in reinen funktionalen Sprachen keine Sprungbefehle oder Schleifen, nur Rekursion. Das ist alles andere als nur eine andere Syntax. Da muss man komplett umdenken.

Aber auch bei eher imperativen, objektorientierten Sprachen kann es gewaltige semantische Unterschiede zu Java oder Python geben. Zum Beispiel Sprachen bei denen es keine Klassen gibt, sondern nur Objekte die man klonen und verändern kann. Welche bei denen Argumente von Methodenaufrufen nicht grundsätzlich vor dem Aufruf ausgewertet werden, sondern wo der Empfänger entscheiden kann ob, wann und in welchem Kontext der jeweilige Ausdruck ausgewertet werden soll. So eine Sprache ist Io. ``if`` ist dort eine Methode die drei Argumente erhält die *nicht vor* dem Aufruf ausgewertet werden. Die Methode wertet erst das erste Argument aus und entscheidet dann, je nachdem ob dabei wahr oder falsch herausgekommen ist, ob das zweite ("then-Zweig") oder das dritte ("else-Zweig") Argument ausgewertet werden muss und liefert auch dessen Rückgabewert als Ergebnis.

Man sollte sich schon auf die jeweilige Programmiersprache einlassen und nicht nur fragen wie Kommentare gekennzeichnet werden und wo das Semikolon hinkommt, und ansonsten so weitermachen wie man es von der letzten Sprache gewohnt war. In comp.lang.python wurde mal jemandem, der versucht hat Python wie Java zu behandeln, gesagt: Wenn Du aufhörst die Sprache zu bekämpfen, dann hast Du mehr Zeit das Problem anzugehen das Du lösen willst. (Frei übersetzt)
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

BlackJack hat geschrieben:Ich möchte mich Leonidas anschliessen. Insbesondere wenn die Sprachen einem ganz anderen Paradigma folgen wie zum Beispiel funktionale Sprachen. Wie man vielleicht an dem Nemerle-Beispiel sehen kann. Oder hier in Haskell, einer reinen funktionalen Programmiersprache:
Dem muss ich mich ebenfalls anschließen.

Ich bin mit der Prozeduralen und OOP Programmierung vertraut und da ist die Funktionale oder Logische Programmierung ne ganz andere Nummer. Da kann ich mit mein wissen in den andren Paradigmen nichts anfangen.

Arakis, ich habe mich ganz, ganz, früher sehr lange mit C/C++ beschäftigt und habe die dort verwendeten Paradigmen mehr oder weniger verinnerlicht. Daher viel es mir z.B. nach etlichen Jahren nicht besonders Schwer in Perl und Python einzusteigen (Bis hier hin mag deine Aussage auch zutreffen) aber (nun kommts)...
BlackJack hat geschrieben: Man sollte sich schon auf die jeweilige Programmiersprache einlassen und nicht nur fragen wie Kommentare gekennzeichnet werden und wo das Semikolon hinkommt, und ansonsten so weitermachen wie man es von der letzten Sprache gewohnt war. In comp.lang.python wurde mal jemandem, der versucht hat Python wie Java zu behandeln, gesagt: Wenn Du aufhörst die Sprache zu bekämpfen, dann hast Du mehr Zeit das Problem anzugehen das Du lösen willst. (Frei übersetzt)
...Genau das ist der springende Punkt! Es bringt nichts wenn man in C/C++ Programmieren kann und dann in Python versucht wie in C zu programmieren.

Klassisches Beispiel ist es über range zu iterrieren und dann die Werte als Index für Listen (etc) zu Benutzen ^^ Das mag Gültigkeit für C habe (weil man da keine andere Möglichkeit hat) aber nicht für Python. In Python iterriert man dann gleich über die Liste ;) Und solche Unterschiede gibt es viele die man beachten muss um sauberen Code zu schreiben.

Daher finde ich diese Aussage auch...
Arakis hat geschrieben:[...]
Dennoch möchte ich anmerken, dass wenn man einmal eine Sprache "perfekt" beherrscht, das erlernen von anderen Sprachen eher im handumdrehen stattfindet, es geht dann nur noch um Syntax und Befehlssatz. Denn wie wir alle wissen, Programmieren besteht nich nur daraus, ein Handbuch auswendig im Kopf zu haben....
[...]
...nicht unbedingt zutreffend.

EDIT:
In dem Sinne, wenn man vor hat sich ernsthaft mit einer Sprache X einzulassen, dann reicht es nicht einfach die Syntax und die Befehle auswendig zu lernen um dann so zum Programmieren wie in Sprache Y.

lg
Antworten