[Tutorial] Compiler und Virtual Machine

Hier kannst du häufig gestellte Fragen/Antworten und Tutorials lesen und schreiben.
Benutzeravatar
7x7
Beiträge: 591
Registriert: 14.08.2007 15:41
Computerausstattung: ganz toll
Wohnort: Lelbach

Re: [Tutorial] Compiler und Virtual Machine

Beitrag von 7x7 »

[Beginn Streicheleinheit]
Ich finde dein Tutorial ganz interessant! Wenn zum Schluss etwas lauffähiges und brauchbares herauskommt, darfst du gerne weitermachen.
Es gab hier schon Einige, die hier mit großen Ankündigungen den Versuch unternommen haben, etwas auf die Beine zu stellen. So weit wie du hat noch keiner durchgehalten. Respekt!!
[Ende Streicheleinheit]
:D
puretom hat geschrieben:
Danilo hat geschrieben:aber als Einführung für Interessierte finde ich das schon ganz OK.
Danke, mehr kann ich auch selbst nicht und will ich auch nicht
Genau so soll es sein! Erweitern und verbessern kann jeder selbst - man soll ja auch nur begreifen, wie es geht!


Ich lese (wie ich Zeit habe) mit. Einfach nur aus Interesse. Was ich aber noch nicht kapiert habe, ist:
puretom hat geschrieben:Diese soll dann auf eine Stack Machine als Virtual Machine compilieren und dann eben in einer solchen ablaufen
Stack Machine? Was ist das? Oder andersrum gefragt: Was kommt beim Kompilieren heraus? Maschinensprache? Wenn ja: welche?
Oder etwas "anderes"? Theoretisch ist das ja egal, weil prinzipiell austauschbar.
Aber: Soll (nur?) in der VM laufen? Warum?

Möglicherweise stehe ich auch nur auf der Leitung :D
- alles was ich hier im Forum sage/schreibe ist lediglich meine Meinung und keine Tatsachenbehauptung
- unkommentierter Quellcode = unqualifizierter Müll
puretom
Beiträge: 109
Registriert: 06.09.2013 22:02

Re: [Tutorial] Compiler und Virtual Machine

Beitrag von puretom »

Lieber 7x7!

Zuerst wie immer, Danke für dein Feedback! :D
Es gab hier schon Einige, die hier mit großen Ankündigungen den Versuch unternommen haben, etwas auf die Beine zu stellen. So weit wie du hat noch keiner durchgehalten. Respekt!!
Davor habe ich auch gewarnt. Habe mich aber schon in der Einleitung entschuldigt, falls ich nicht durchhalte. Wenn ich nicht mehr mag, mag ich nicht mehr, so geht es wohl jedem von uns, außerdem haben wir alle eine Arbeit und ev. sogar Familie. Und Lebenswege und -ziele können sich sehr schnell und plötzlich ändern, wenn etwas Unvorhergesehenes geschieht.
Aber bisher macht es noch Spaß und ich hoffe, das ist noch lange so. <)

P.S. Meine Schaffensgeschwindigkeit liegt zum Teil auch daran, dass einiges an funktionierendem Code hier vor mir liegt und ich einen Erklärungstext dazu verfasse, Grafiken mache usw. für das Tut, also den Code vielfach nur anpasse, aber nicht gänzlich neu code.
Ab einem bestimmten Punkt aber, werden meine Code-Stücke hier dünner, dann wird's eh' härter, weil ich dann mehr denken muss. Aber sollte ich bis dorthin nicht mehr mögen, habt ihr zumindest die Infos bis dorthin bekommen und könnt sie nutzen.

Zu deiner Frage:
Stack Machine? Was ist das? Oder andersrum gefragt: Was kommt beim Kompilieren heraus? Maschinensprache? Wenn ja: welche?
Ich habe gehofft, dass das aus meinem Tutorial klar herauskommt.
Solltest du mein Tutorial nur überflogen haben, bitte ich dich, es zu lesen und mir zu sagen, ob es danach klar ist.

Da gibt es das Kapitel "3. Das große Bild" und das Kapitel "5. Kurze Einführung in Assembler/Maschinensprache", in denen ich, wie ich hoffte, alles erklärt habe.

Wenn nicht, dann habe ich nämlich Erklärungsfehler oder Unklarheiten drinnen und bitte dich, mir das zu sagen, vor allem, WO es nicht klar ist, damit ich die Sache so überarbeiten kann, dass das klar rüberkommt.

Ein kleiner Nachsatz: Wenn ich dann das Kapitel mit der Virtuellen Maschine mache, dann wird es vielleicht klarer, denn bislang "läuft" ja hier noch nichts und wer nicht eingearbeitet ist ins Thema, der weiß natürlich nicht, wo das alles hinführen soll.

Liebe Grüße
Puretom
Windows 7 und Windows 10 (Laptop), PB 5.62 | Projekt: Tutorial - Compiler und Virtual Machine | vielleicht einmal ein Old School Text-Adventure Tutorial | Neu: Spielereien, Üben rund um OOP in PB
puretom
Beiträge: 109
Registriert: 06.09.2013 22:02

Re: [Tutorial] Compiler und Virtual Machine

Beitrag von puretom »

DAS POSTING, AUF DAS ICH ANTWORTE, IST AUF EINMAL WEG???

Was habe ich jetzt falsch gemacht oder gedrückt???


Hi Danilo!

Danke, dass du dich noch damit auseinandersetzt.

ERSTENS:

Ein bisschen entsetzt mich, dass Kapitel-8-Parser das akzeptiert, der muss eine Fehlermeldung ausgeben!!!!!
Meiner tut das!

Also der Compiler von Kapitel 8 müsste hängenbleiben bei diesem Code:

Code: Alles auswählen

if (b=1)               
    if (a=3)
       print("a=3")
else
    print("else")
Die Version von Kapitel 8 hat nämlich noch keine Vergleichsoperatoren und ruft außerdem als Default-Option in Statement() immer den Expression-Parser mit Expression() auf. Also das sollte so nicht funktionieren!

ZWEITENS:

Wenn ich vorgreifen darf auf Kapitel 9 (EDIT: Wird zu einem späteren Zeitpunkt kommen, vorher verbesserter Mathe Parser), dann poste ich, was der Kapitel 9 (?) Parser ausgibt (auch hier muss ich noch etwas zaubern, weil ich immer noch auf Expression() "defaulte", aber ich bin noch im Entwicklungsstadium:


Also wir haben es hier mit einem typischen Dangling Else zu tun.

In diesem Wikipedia-Artikel(http://de.wikipedia.org/wiki/Dangling_else) ist ein identes Beispiel mit Zahlen, daran habe ich mich gehalten, als ich die Toy-C-Grammatik-Logik gemacht habe:

Code: Alles auswählen

 if (a == 1)
    if (b == 1)
      a = 42;
 else
    b = 42;
Wikipedia hat geschrieben:In diesem Beispiel erwarten einige Nutzer, dass für den Fall der Variablen der Wert zugewiesen wird. Der Compiler bezieht den else-Zweig allerdings auf die letzte (!!!!) if-Abfrage.
Also sollte sich also das else auf das letzte if beziehen.

Ich rücke meinen Code also schnell mal so ein, wie die Sache wirklich gemeint ist:

Code: Alles auswählen

if (b=1)
    if (a=3)
       print_a_ist_3
    else            
       print_else
Annahme b<>1, also die erste If-Abfrage geht auf FALSE:

Code: Alles auswählen

if (b=1) ---------------.
    if (a=3)            |
       print_a_ist_3    |
    else                |
       print_else       |
                        v
                        * hinter print_else
Ist doch so? Sag mir bitte, wenn ich mich täusche!

Mein Compiler macht dasselbe daraus:

Code: Alles auswählen

        push Global B
        push Const  1
        eq
        JF IF0 ----------------------. JF = Jump if False
        push Global A                |
        push Const  3                |
        eq                           |
        JF IF1                       |
        push Global PRINT_A_IST_3    |
        JF IF2                       |
[IF1]                                |
        push Global PRINT_ELSE       |
[IF2]                                v
[IF0]                                * hinter print_else
Annahme b=1, also die erste If-Abfrage geht auf TRUE:
Annahme a=0, also die zweite If-Abfrage geht auf FALSE, jetzt müssten wir zu ELSE kommen, oder?

Code: Alles auswählen

if (b=1)               TRUE
    if (a=3)           FALSE
       print_a_ist_3    |
    else                |
       print_else  <----' nimmt else-Zweig 
Mein Compiler mach das daraus:

Code: Alles auswählen

        push Global B
        push Const  1
        eq
        JF IF0                      TRUE (weiter gehts)
        push Global A                |
        push Const  3                |
        eq                           v
        JF IF1                     FALSE (jump)
        push Global PRINT_A_IST_3    |
        JF IF2                       v
[IF1]                                * nimmt else-Zweig
        push Global PRINT_ELSE       
[IF2]                                
[IF0]                                
Nehmen wir das 2. Beispiel aus der Wikipedia (ich habs gleich umgewandelt, damit mein Compiler das isst).


a=0 --> a = FALSE

Code: Alles auswählen

if (a = 1)               FALSE
{                          |
     if(b = 1)             |
          b_ist_true       |
}                          |
else                       v
     else_zweig_von_a      * else-Zweig kommt
Compiler:

Code: Alles auswählen

        push Global A
        push Const  1
        eq                              FALSE
        JF IF0                            |
        push Global B                     |
        push Const  1                     |
        eq                                |
        JF IF1                            |
        push Global B_IST_TRUE            |
[IF1]                                     |
        JF IF2                            v
[IF0]                                     * else-Zweig kommt 
        push Global ELSE_ZWEIG_VON_A
[IF2]
a=TRUE, b=TRUE, else-Zweig darf jetzt NICHT KOMMEN.

Code: Alles auswählen

if (a = 1)               TRUE
{                          |
     if(b = 1)           TRUE
          b_ist_true       |
}                          |
else                       |
     else_zweig_von_a      v        
                           * else-Zweig kommt NICHT
Compiler:

Code: Alles auswählen

        push Global A
        push Const  1
        eq                              TRUE
        JF IF0                            |
        push Global B                     |
        push Const  1                     |
        eq                                |
        JF IF1                           TRUE
        push Global B_IST_TRUE            |
[IF1]                                     |
        JF IF2                          ÜBERSPRINGEN
[IF0]                                     |
        push Global ELSE_ZWEIG_VON_A      v
[IF2]                                     * else-Zweig kommt NICHT
Und so weiter: also für mich passt das eigentlich so.
Er springt auch bei a=TRUE und b=FALSE zuverlässig über den Else-Zweig (doppelt JF IF1 -> JF IF2)

LG Puretom
Zuletzt geändert von puretom am 03.10.2013 19:46, insgesamt 2-mal geändert.
Windows 7 und Windows 10 (Laptop), PB 5.62 | Projekt: Tutorial - Compiler und Virtual Machine | vielleicht einmal ein Old School Text-Adventure Tutorial | Neu: Spielereien, Üben rund um OOP in PB
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: [Tutorial] Compiler und Virtual Machine

Beitrag von Danilo »

puretom hat geschrieben:DAS POSTING, AUF DAS ICH ANTWORTE, IST AUF EINMAL WEG???
Was habe ich jetzt falsch gemacht oder gedrückt???
Nix falsch gemacht. Hatte es gelöscht, da ich mir schon denken konnte, dass Du das mit Blöcken machst.

Code: Alles auswählen

if (b=1)
{
    if (a=3)
       print("a=3")
}
else
    print("else")
puretom hat geschrieben:Ein bisschen entsetzt mich, dass Kapitel-8-Parser das akzeptiert, der muss eine Fehlermeldung ausgeben!!!!!
Meiner tut das!

Also der Compiler von Kapitel 8 müsste hängenbleiben bei diesem Code:

Code: Alles auswählen

if (b=1)               
    if (a=3)
       print("a=3")
else
    print("else")
Die Version von Kapitel 8 hat nämlich noch keine Vergleichsoperatoren und ruft außerdem als Default-Option in Statement() immer den Expression-Parser mit Expression() auf. Also das sollte so nicht funktionieren!
Bei mir lief folgender Code:

Code: Alles auswählen

// OK
if (b=1)               
    if (a=3)
       print("a=3")
else
    print("else")
Das lag an:

Code: Alles auswählen

   Procedure SkipLineComment()
      
      ; bis Zeilenende oder Ende des Source-Files (0-Byte)
        While Look<>#LF And Look<>0 
            GetChar()
        Wend
Habe Source-Code.tc nun so abgespeichert, das Zeilenenden als #LF gespeichert werden.
Vorher hat es mein Editor hier auf dem Mac wohl mit #CR gespeichert.
Nun geht es korrekt, wenn man als ASCII (ohne BOM) mit #LF-Zeilenenden abspeichert.
Zuletzt geändert von Danilo am 28.09.2013 22:57, insgesamt 1-mal geändert.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: [Tutorial] Compiler und Virtual Machine

Beitrag von NicTheQuick »

Danilo hat geschrieben: Das lag an:

Code: Alles auswählen

   Procedure SkipLineComment()
      
      ; bis Zeilenende oder Ende des Source-Files (0-Byte)
        While Look<>#LF And Look<>0 
            GetChar()
        Wend
Habe Source-Code.tc nun so abgespeichert, das Zeilenenden als #LF gespeichert werden.
Vorher hat es mein Editor hier auf dem Mac wohl mit #CR gespeichert.
Nun geht es korrekt, wenn man als ASCII mit #LF-Zeilenenden abspeichert.
In dem Fall am besten den Compiler alle Zeilenende akzeptieren lassen, also #LF und #CR. Wenn man dann unter Windows mit #CRLF speichert, muss man nur aufpassen, dass der Compiler keine falschen Zeilennummern anzeigt, weil für ihn dann jeder Zeilenumbruch wie zwei aussieht.
Bild
puretom
Beiträge: 109
Registriert: 06.09.2013 22:02

Re: [Tutorial] Compiler und Virtual Machine

Beitrag von puretom »

Habe Source-Code.tc nun so abgespeichert, das Zeilenenden als #LF gespeichert werden.
Vorher hat es mein Editor hier auf dem Mac wohl mit #CR gespeichert.
Nun geht es korrekt, wenn man als ASCII mit #LF-Zeilenenden abspeichert.
Wobei ich dir für den Tipp danke, vielleicht sollte ich das #CR auch in die Schleife reingeben?
Dann ist die Sache wasserdichter für mehr Plattformen.

Danke für den Bug, genau so etwas such ich!

Testet! Testet! Mit dem Mac hätte ich im Leben nicht gerechnet, was eine 2. Perspektive ausmacht.

Danke! Werde das einarbeiten.

LG
Puretom

P.S. Schon geändert.
Windows 7 und Windows 10 (Laptop), PB 5.62 | Projekt: Tutorial - Compiler und Virtual Machine | vielleicht einmal ein Old School Text-Adventure Tutorial | Neu: Spielereien, Üben rund um OOP in PB
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: [Tutorial] Compiler und Virtual Machine

Beitrag von Danilo »

NicTheQuick hat geschrieben:In dem Fall am besten den Compiler alle Zeilenende akzeptieren lassen, also #LF und #CR. Wenn man dann unter Windows mit #CRLF speichert, muss man nur aufpassen, dass der Compiler keine falschen Zeilennummern anzeigt, weil für ihn dann jeder Zeilenumbruch wie zwei aussieht.
Folgender Pseudo-Code akzeptiert als Zeilenende: #LF, #CR, #LFCR, #CRLF

Code: Alles auswählen

While currentChar <> #LF And currentChar <> #CR And currentChar <> 0
    IgnoreIt()
Wend

If currentChar = #LF      ; #LF
    CurrentLine + 1
    IgnoreIt()
    If currentChar = #CR  ; #LFCR
        IgnoreIt()
    EndIf
ElseIf currentChar = #CR  ; #CR
    CurrentLine + 1
    IgnoreIt()
    If currentChar = #LF  ; #CRLF
        IgnoreIt()
    EndIf
EndIf
Das sollte ziemlich sicher sein. AFAIK macht kein Editor gemischte Zeilenenden, also mal #CR und mal #LF,
d.h. ein Zeilenende ist eigentlich immer gleich. #LF oder #CR oder #LFCR oder #CRLF.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
puretom
Beiträge: 109
Registriert: 06.09.2013 22:02

Re: [Tutorial] Compiler und Virtual Machine

Beitrag von puretom »

Korrektur, jetzt war ich zu schnell:
-> Falsch von mir

1. Oben ist wohl die While-Schleife -> habe ich genau so gelöst auf die Schnelle als Workaround!

2. Ist fürs Zeilenzählen - denke ich, wenn ich das mal einbaue wegen Debuggen, dann darf ich hoffentlich von deiner Lösung "naschen"? :lol:

Danke, LG Tom
Windows 7 und Windows 10 (Laptop), PB 5.62 | Projekt: Tutorial - Compiler und Virtual Machine | vielleicht einmal ein Old School Text-Adventure Tutorial | Neu: Spielereien, Üben rund um OOP in PB
puretom
Beiträge: 109
Registriert: 06.09.2013 22:02

Re: [Tutorial] Compiler und Virtual Machine

Beitrag von puretom »

Frage:

Wo gibst du das Zeilenzählen hinein, ich habe es immer direkt in GetChar(), also ganz nah an der "Quelle" sozusagen????
Windows 7 und Windows 10 (Laptop), PB 5.62 | Projekt: Tutorial - Compiler und Virtual Machine | vielleicht einmal ein Old School Text-Adventure Tutorial | Neu: Spielereien, Üben rund um OOP in PB
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: [Tutorial] Compiler und Virtual Machine

Beitrag von Danilo »

puretom hat geschrieben:Wo gibst du das Zeilenzählen hinein, ich habe es immer direkt in GetChar(), also ganz nah an der "Quelle" sozusagen????
Ja, das ist am Besten. GetChar() könnte dann #LF, #CR, #LFCR, #CRLF behandeln, Zeilennummer erhöhen, und es
gibt für #LF, #CR, #LFCR, #CRLF immer #LF zurück. Es konvertiert also auch #CR, #CRLF und #LFCR zu #LF -
dann musst Du an anderen Stellen nur auf #LF prüfen.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Antworten