Offene Fragen bei der Entwicklung einer kleinen Programmiersprache



  • Ethon schrieb:

    Ich habe das return Statement so implementiert dass ich eine Exception mit dem Rückgabewert werfe und das Call-Statement diese Exception fängt und damit den Rückgabewert hat. Ist das eine zu wüste Vergewaltigung des C++-Exceptionsystems?
    Afaik wirft Python sogar Exceptions um das Ende einer Iteration zu signalisieren. 🤡

    Es kommt drauf an, was man unter Exceptions versteht.
    Ausschliesslich als Ausnahmebehandlung: Dann ist das eine Vergewaltigung.
    Als besseren/billigeren longjump: Dann ist das ok.

    Selbst in C++ wäre es unter Umständen schneller,

    try {
      for (auto it=...;; ++it)
        ...
    } catch(end_of_iteration) {}
    

    zu schreiben, weil man sich damit die Abfrage it!=end spart.

    Du kannst es gerne so machen, aber es ist um einiges einfacher und effizienter, das return wie in C zu implementieren. Und es würde z.B. überhaupt nicht zu C++ passen, das Muster müsste sich in deiner Sprache dann wiederholen um konsistent zu wirken.

    Warum verwenden viele Sprachen wie auch C++ ein Semikolon um ein Statement abzuschließen ... das ist doch Prinzip garnicht nötig? Oder wo ist es das?

    Doch, selbst "1-1" hat zwei Interpretationen:

    1-1;
    1; -1;
    

    Jede Sprache hat ein Semikolon. Manche nehmen ";", manche nehmen Whitespaces.

    Eine echte Sprache (nicht Assembler, Brainf*ck oder sonstige Spässe), die kein Semikolon benötigt, ist mir nicht bekannt.



  • Eine echte Sprache (nicht Assembler, Brainf*ck oder sonstige Spässe), die kein Semikolon benötigt, ist mir nicht bekannt.

    Lua zum Bleistift. 🙂

    pytarius schrieb:

    Doch, selbst "1-1" hat zwei Interpretationen:

    1-1;
    1; -1;
    

    Jede Sprache hat ein Semikolon. Manche nehmen ";", manche nehmen Whitespaces.

    Kommt doch darauf an wie die Grammatik definiert ist ... meine Grammatik ist greedy und matcht was geht. So ist aber zb. diese C Grammatik ( http://www.lysator.liu.se/c/ANSI-C-grammar-y.html ) für den Standard auch definiert ...

    1; -1; macht ja auch keinen Sinn - sowas muss man doch nicht übersetzen können.
    Fällt dir ein sinnvolles Beispiel ein wo solche Doppeldeutigkeiten auftreten können? Mir eben nicht ...



  • Kleiner Showoff weil ich auf mein Baby mittlerweile recht stolz bin. 🙂

    puts = native "puts" from "libc.so" defined (s : "string8") -> "int32"
    
    result = 0
    for i in 0..1000
    {
        if i % 3 == 0 || i % 5 == 0
            result += i
    }
    
    puts(i)
    

    (Bin gerade dabei http://projecteuler.net Probleme zu lösen da ich Probleme habe andere nette Testaufgaben für meine Sprache zu finden - wer welche kennt, bitte her damit!)

    Von dem was man sehen kan (ist ja nicht viel): Irgendetwas auszusetzen?



  • Ethon schrieb:

    Von dem was man sehen kan (ist ja nicht viel): Irgendetwas auszusetzen?

    Nee, nur interessierte Nachfragen. Wie hast Du das Einbinden der lib realisiert? Und wenn Du magst, kannst Du ja auch mal die Grammatik oder weitere Beispiele zeigen.



  • Wie hast Du das Einbinden der lib realisiert?

    Primär über libffi. Anhand der Angaben nach "defined" baue ich das ffi_cif zusammen bzw. konvertiere ich die Parameter zurecht.

    native "puts" from "libc.so" defined (s : "string8") -> "int32"
    

    ist ein Ausdruck der Objekt vom Typ "native_function" zurückgibt.
    Jede Bibliothek ist refcounted, jedes native_function Objekt hat eine Referenz auf das Bibliothekshandle - ich entlade die Bibliothek wenn sie nicht mehr referenziert wird. Danke das ist besser als die Bibliothek im Speicher zu belassen.

    Und wenn Du magst, kannst Du ja auch mal die Grammatik oder weitere Beispiele zeigen.

    Jetzt wirds peinlich: Ich habe mir keine genaue Grammatik aufgeschrieben.
    Ich habe mir die C++-Operatoren-Präzedenzregeln als Vorlage genommen und mir anhand dessen einen Recursive-Descent Parser zusammengeschustert.
    Hab halt mit nem Matheparser begonnen und baue seitdem Funktionalität dazu.

    Mal sehen ob ich damit auf die Schnauze fliege. Wenn ist es mir aber auch egal, dann kipp ich das Projekt in die Tonne und versuche mich an einem self compiling C-Compiler. :p



  • Ethon schrieb:

    da ich Probleme habe andere nette Testaufgaben für meine Sprache zu finden - wer welche kennt, bitte her damit!

    http://www.haskell.org/haskellwiki/H-99:_Ninety-Nine_Haskell_Problems
    Da das Probleme für funktionale Sprachen sind, musst du sie eventuell etwas adaptieren.

    Ethon schrieb:

    Von dem was man sehen kan (ist ja nicht viel): Irgendetwas auszusetzen?

    Auszusetzen nicht direkt. Aber hat deine Sprache irgendwelche Konzepte, die es besonders interessant machen könnten, sie sich anzusehen? Bei dem kurzen Programmstück sehe ich abgesehen von leicht abgewandelter Syntax keine großartigen Unterschiede zu gängigen Skriptsprachen.



  • @Ethon
    Danke für die Antwort.
    Kannst Du weitere Beispiele zeigen, vielleicht ein Quicksort?
    Welche Sprachelemente hast Du bereits implementiert? Funktionen? Ein Modulsystem? Ist die Sprache Objektorientiert?
    Wenn Du mir alles notwendige zukommen lässt, würde ich vielleicht mal ein wenig damit programmieren. Mangels Grammatik bräuchte ich dann aber auch den Quellcode um sie mir aus dem Parser rauszufischen.



  • Upps, habe die Antwort jetzt erst gelesen, wurde mir unter den neuen Beiträgen nicht angezeigt.

    Ich Idiot habe es versäumt regelmäßige Backups zu machen und der Projektordner ist einer Dummheit zum Opfer gefallen.
    Musste mit einem sehr alten Stand weiterarbeiten, was nicht schlecht ist, ich habe ein paar Dinge jetzt anders gemacht, aber Funktionalität ist recht mau.

    Funktionen sind implementiert. (Defaultparameter auch, aber keine named Parameter)
    Modulsystem steht die Planung.
    Objektorientierung is theoretisch dabei, Builtin-Typen wie Integer verhalten sich wie Objekte, allerdings fehlt mir noch jedes Konzept wie nutzerdefinierte Klassen umgesetzt werden sollen. Ich möchte es halt schön hinbekommen.

    Eines der Probleme bezüglich Objektorientierung ist dass ich Refcounting und keinen GC verwende. (Und das auch so bleiben soll)
    Jetzt muss ich mir halt genau überlegen wie ich zyklische Referenzen lösen kann.

    Vermutlich werde ich einfach mal eine dumme struct ala C implementieren die nur ein Container für andere Objekte ist.

    Der ganze Krempel ist auf Github oben, wenn Interesse besteht kann ich ja mal nen Link posten.

    ----

    Aus aktuellem Anlass: Wäre es für euch intuitives Verhalten wenn der Ausdruck

    5.sqrt == 2
    

    wahr wäre?
    Ich nutze jetzt GMP für ints/floats und GMP bietet für Integer standardmäßig nur eine Wurzelfunktion bereit, die den abgeschnitten Integer + Rest zurückgibt.

    Bei floats sieht es anders aus, zb. wäre dieser Ausdruck false:

    5.float.sqrt == 2
    

    Bin mir halt nicht sicher ob eine implizite Konvertierung nach float sinnvoller wäre als einen abgeschnittenen Integer zurückzugeben.
    Meinungen?



  • Bei 5.sqrt würde ich 2.23 hoffen. Wer den int haben will, kann ja 5.sqrt.int schreiben.

    Basic mag ich da. 5/2==2.5 aber 5\2==2.



  • Ich habe in dieser Beziehung immer debug (win32) sehr gemocht bzw. die Intellowlevelebene, weil man beim Teilen das Ergebnis im AX Register hat, den Rest im DX Register (und die klassische Registervergrößung mit diesem beiden Registern). Wäre schön, wenn das an Taschenrechner auch könnte, bzw. wenn eine Funktion divmod, die zwei Werte ausspuckt, einfach mal Standard wäre, und nicht getrennt in div und mod oder ungefragt Fließkomma und aufgedrängtes Rundungsverhalten.

    Bei Wurzeln gibt es ja immer mehrere Möglichkeiten. Hier fände ich Transparenz gut, und Auswahlmöglichkeiten (auch Anzahl der Nachkommastellen), wie auch eine, Schätzfunktion bzw. -hilfe.
    Aber wie wäre es, einfach mehrere Werte auszugeben, den Floatwert und den Integerwert mit Rest, Anzahl der Nachkommastellen und Schätzbereich(e). 😉

    Wenn das alles nicht geht, dann würde ich die Funktion selber mit Heron und der FPU machen, also standardmäßig Fließkomma mit maximaler Bitbreite.
    Grammatisch finde ich sqrt 5 mit Fließkommaausgabe am sinnvollsten. FP für Wurzeln ist letzlich auch generell intuitiver, weil die FPU für größere Bitbreiten/Zahlen näher liegt.

    Aber einen C-Sprachtyp als Vorbild/Orientierung empfinde ich nicht unbedingt als gute Wahl. Auch wenn python eine Menge kann und u.a. Hackers Liebling ist, syntaktisch sollte man sich auch Haskell und Fortran(und Basic) gut anschauen, und auch Lisp und (Entwicklung nach) Closure. Aber nicht nur, Programmiersprachen sind selten isoliert, sondern Anwendungsgebunden, hier kommt es auch immer aufs drumherum an, Compilerauswahl und -Installationsmöglichkeiten, Betriebsysteme, Bibliotheken, Plugins, DesktopundGUI, Community, Weiterpflege usw.

    Ansonsten: Zeig mal, (oder probier mal) wie man einfache Sachen angehen kann, wie z.B. Registerwerte manipulieren (für OS Programming), mathematische Funktionen, Kettenbrüche, Analysis, Fakultätsberechnung, Quicksort, Heron-Wurzel (mit Schritt-Liste) und Cäsar-Verschlüsselung oder Konvertierungen zwischen Zahlensystemen (und welche?) eine Bitmap/Farbtabelle für einen Desktop(Betriebsystem) erstellen, oder einen simplen Texteditor o.ä. aber auch wie komplizierte Schleifenverschachtelungen aussehen würden.

    (ach so, damit der Stack nicht vollgeschrieben wird, kann man Jumps machen statt calls (mit ret), grundlegende Funktionen zusammenlegen, und je nach Funktionsaufruf den Navigationswert im Speicher zurücksetzen, also die Startadresse bzw. die Speicheradresse(n) vom (wenn sich hier was bewegt) und im Stack.

    Auf abstrakterer Ebene hilft die Beschäftigung mit Stackoverflows weiter z.B.
    http://en.wikipedia.org/wiki/Stack_overflow )



  • volkard schrieb:

    Bei 5.sqrt würde ich 2.23 hoffen. Wer den int haben will, kann ja 5.sqrt.int schreiben.

    Basic mag ich da. 5/2==2.5 aber 5\2==2.

    Macht Sinn, danke.
    Die Basic-Syntax gefällt mir nicht. Sehen beide zu ähnlich aus.

    Ich habe in dieser Beziehung immer debug (win32) sehr gemocht bzw. die Intellowlevelebene, weil man beim Teilen das Ergebnis im AX Register hat, den Rest im DX Register (und die klassische Registervergrößung mit diesem beiden Registern). Wäre schön, wenn das an Taschenrechner auch könnte, bzw. wenn eine Funktion divmod, die zwei Werte ausspuckt, einfach mal Standard wäre, und nicht getrennt in div und mod oder ungefragt Fließkomma und aufgedrängtes Rundungsverhalten.

    Kommt halt bei einer Skriptsprache doof wenn Ergebnisse von grundlegenden Operationen nicht einfach verwendet werden können. Also zb. bei deinem Divisions-Beispiel.
    Soetwas könnte man natürlich als Library anbieten aber mein /-Operator darf schon ein float zurückgeben.

    Wenn das alles nicht geht, dann würde ich die Funktion selber mit Heron und der FPU machen, also standardmäßig Fließkomma mit maximaler Bitbreite.
    Grammatisch finde ich sqrt 5 mit Fließkommaausgabe am sinnvollsten. FP für Wurzeln ist letzlich auch generell intuitiver, weil die FPU für größere Bitbreiten/Zahlen näher liegt.

    Bei mir sind Integer/Floats multiple-precision da ich GMP für die Implentierung nutze. Erstmal möchte ich da nicht allzuviel selbst implementieren. 😉

    Ansonsten: Zeig mal, (oder probier mal) wie man einfache Sachen angehen kann, wie z.B. Registerwerte manipulieren (für OS Programming), mathematische Funktionen, Kettenbrüche, Analysis, Fakultätsberechnung, Quicksort, Heron-Wurzel (mit Schritt-Liste) und Cäsar-Verschlüsselung oder Konvertierungen zwischen Zahlensystemen (und welche?) eine Bitmap/Farbtabelle für einen Desktop(Betriebsystem) erstellen, oder einen simplen Texteditor o.ä. aber auch wie komplizierte Schleifenverschachtelungen aussehen würden.

    Wie gesagt, im Moment steht noch nicht allzuviel.
    Low-Level Kram kommt in die Sprache garnicht rein, es ist eben ein dynamisch typisierte Scriptsprache. Im Moment ist es relativ leicht nativen Code zu nutzen (Bindings sind leicht zu schreiben (wenn auch noch nicht komfortabel implementiert) und es gibt eingebauten Support für C-Funktionen in DLLs.)

    Faktultät:

    x = 1123
    fak_of_x = x!
    


  • Ethon schrieb:

    volkard schrieb:

    Bei 5.sqrt würde ich 2.23 hoffen. Wer den int haben will, kann ja 5.sqrt.int schreiben.

    Macht Sinn, danke.

    Dann beachte aber, daß es (gut, aber nur in der hand des compilerbauers) allen Deiner Verantwortung unterliegt,
    5.sqrt.int
    und
    5.sqrt
    was vollkommen verschiedenes machen zu lassen! Erstere Version ist evtl viel schneller.
    Kann es möglich sein (besser, in der hand des bibliotheksschreibers!!!!!), daß der Anwender beschreiben kann, daß .sqrt.int vorrangich matcht vor .sqrt ?
    Und wäre das überhaupt tragfähig für viele andere Optimierungen oder nur eine Eintagsfliege?



  • Basic mag ich da. 5/2==2.5 aber 5\2==2.

    Diese Syntax ist irritierend.

    Kaum zu unterscheiden, wobei Code flink lesbar und verständlich sein soll.
    Einen Strich auf verschiedene Seiten zu kippen ist für einen Menschen nicht schnell genug unterscheidbar und kann und wird zu vielen Missverständnissen führen/geführt haben.

    Du hast, beiläufig gesprochen, Ethon falsch zitiert.



  • Sone schrieb:

    Basic mag ich da. 5/2==2.5 aber 5\2==2.

    Diese Syntax ist irritierend.

    Kaum zu unterscheiden, wobei Code flink lesbar und verständlich sein soll.
    Einen Strich auf verschiedene Seiten zu kippen ist für einen Menschen nicht schnell genug unterscheidbar und kann und wird zu vielen Missverständnissen führen/geführt haben.

    Nö, wenn mans ein wenig gewohnt ist, kein Problem.

    Sone schrieb:

    Du hast, beiläufig gesprochen, Ethon falsch zitiert.

    Hab's nur auf die Nicht-Basic-Sache reduziert. Bin sicher, es war in seinem Sinne.



  • volkard schrieb:

    Nö, wenn mans ein wenig gewohnt ist, kein Problem.

    Nun, du wirst es wissen. 🙂

    Sone schrieb:

    Du hast, beiläufig gesprochen, Ethon falsch zitiert.

    Hab's nur auf die Nicht-Basic-Sache reduziert. Bin sicher, es war in seinem Sinne.

    Oh, ich hätte schwören können, du hast die Basic-Syntax zitiert... nun, ich bin blind.

    Wie willst du aber auch die Basic-Syntax auf das Radizieren anwenden?

    Bei 5.sqrt würde ich 2.23 hoffen. Wer den int haben will, kann ja 5.sqrt.int schreiben.

    Das ist nicht so hübsch wie bei C++, wo man das alles auf das Typsystem reduzieren kann. Hat diese Skriptsprache eigentlich ein statisches Typsystem?

    bibliotheksschreibers!!!!!

    Was ist denn da so überaus wichtig, dass du es mit fünf Ausrufezeichen hervorhebst?????



  • volkard schrieb:

    Ethon schrieb:

    volkard schrieb:

    Bei 5.sqrt würde ich 2.23 hoffen. Wer den int haben will, kann ja 5.sqrt.int schreiben.

    Macht Sinn, danke.

    Dann beachte aber, daß es (gut, aber nur in der hand des compilerbauers) allen Deiner Verantwortung unterliegt,
    5.sqrt.int
    und
    5.sqrt
    was vollkommen verschiedenes machen zu lassen! Erstere Version ist evtl viel schneller.
    Kann es möglich sein (besser, in der hand des bibliotheksschreibers!!!!!), daß der Anwender beschreiben kann, daß .sqrt.int vorrangich matcht vor .sqrt ?
    Und wäre das überhaupt tragfähig für viele andere Optimierungen oder nur eine Eintagsfliege?

    Naja, das sind ja Properties.

    Integer(5).sqrt().int()

    wäre es mit Funktionsaufrufen.

    Da zu optimieren würde einiges an statischer Analyse verlangen auf die ich schlichtweg wenig lust habe.
    Machen die wenigsten Scriptsprachen, also versuchen zu erraten was der Nutzer ausdrücken wollte und dementsprechend optimieren.
    Durch die Dynamik ist das auch reichlich schwer.

    Da würde ich zb.

    (5).trunc_sqrt
    

    bevorzugen.

    (Die Zahl muss btw in Klammern da der Parser sonst ein Float-Literal matcht. Hat mich einiges an Verwunderung gekostet 😃 )



  • Sone schrieb:

    Wie willst du aber auch die Basic-Syntax auf das Radizieren anwenden?

    Klappt nicht.
    Kenne Smalltalk!

    Sone schrieb:

    Bei 5.sqrt würde ich 2.23 hoffen. Wer den int haben will, kann ja 5.sqrt.int schreiben.

    Das ist nicht so hübsch wie bei C++, wo man das alles auf das Typsystem reduzieren kann. Hat diese Skriptsprache eigentlich ein statisches Typsystem?

    Letztendlich irrelevant.

    bibliotheksschreibers!!!!!

    Was ist denn da so überaus wichtig, dass du es mit fünf Ausrufezeichen hervorhebst?????

    Um nicht in den PHP-Großnotstand zu fallen.



  • Sone schrieb:

    Bei 5.sqrt würde ich 2.23 hoffen. Wer den int haben will, kann ja 5.sqrt.int schreiben.

    Das ist nicht so hübsch wie bei C++, wo man das alles auf das Typsystem reduzieren kann. Hat diese Skriptsprache eigentlich ein statisches Typsystem

    Nein, dynamisch typisiert, wenn auch mit strengeren Regeln als zb. PHP.
    Es wird nicht allzuviel geraten, manchmal muss man eben explizit sagen was man meint. Damit mit dem Cast nach int ist aber eher ein Hack (da man das Implementierungsdetail ausnutzt dass bei Float -> Integer abgerundet wird), schöner wäre

    (5).sqrt.floor
    

    Um nicht in die PHP-Großnotstand zu fallen.

    Was meinst du damit?
    Den Krempel um die Basistypen herum möchte ich als builtins implementieren (allein schon damit Libraries nicht mit internen Repräsentationen der Grunddatentypen arbeiten müssen - wie hier eben GMP).
    Den Rest komplett als Librarylösungen.



  • Ethon schrieb:

    Um nicht in die PHP-Großnotstand zu fallen.

    Was meinst du damit?

    Da haben es Fremdbibliotheken gelinde gesagt schwer.

    edit: Nicht im Sinne von Fremd, aus einer anderen Sprache, sondern fremd als nicht vom PHP-Vertreiber mitvertrieben.



  • Okay.
    Das habe ich nicht vor. Im Moment spiele ich sogar mit dem Gedanken Grunddatentypen austauschbar zu machen.

    Zb. bei Python funktioniert ja auch soetwas:

    > class Foo:
    ... pass
    ...

    > class Bar:
    ... pass
    ...

    > Foo = Bar
    > Foo()
    <__main__.Bar object at 0x7ffcd675d890>

    Wäre noch eine nette Idee wenn mein Compiler ein

    5
    

    zu

    int(5)
    

    umschreiben würde und

    int = MyInt
    

    möglich wäre?


Anmelden zum Antworten