GWBASIC nach PASCAL (maschinell) konvertieren

  • (Eine Bitte vorab - diesen Thread nicht für eine vom Thema abgleitende Diskussion nutzen, Danke!)


    Ich habe nach brauchbaren GWBASIC nach PASCAL (ISO PASCAL oder Turbo PASCAL, das ist hier nicht so wichtig) Umsetzer/Konverter gesucht.

    Leider können die gefundenen Programme nicht GOTO Konstrukte auflösen, sondern wenn überhaupt, benutzen sie das eigentlich unerwünschte GOTO1) auch im PASCAL Code.


    Ich hätte nicht den Anspruch, beliebig verschachtelte Sprünge aufzulösen, aber vielleicht in der Tiefe der Verschachtelung, die so üblich in (schlechten) BASIC-Programmen ist.


    Also habe ich mir einige Beispiele für eine (spätere) maschinelle Umsetzung ausgedacht. Mir ist noch nicht ganz klar, wie man bei den komplizierteren Beispielen das mit einer Programmvorschrift/-regel zu machen, ich denke nicht an einer manuellen Umsetzung (das kriege ich natürlich auch hin, macht aber absolut kein Spaß bei großen Programmlistings).


    Ich fange mal bei den einfachen BASIC-Programmkonstrukten an.
    Da ich die Formatierung/Einrückung und Einfärbungen hier im Forum nur mit großem Aufwand hinbekommen würde, habe ich das in Bildern gemacht:


    Das Beispiel ist m.E. noch recht einfach auch bei einem maschinellen Umsetzer zu programmieren.


    1) GOTO ist schon im Sprachumfang enthalten, entspricht aber keiner strukturierten Programmierung und funktioniert in einigen PASCAL-Implementationen nicht global, sondern nur lokal (also nur innerhalb einer Funktion/Prozedur)

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.

  • Jetzt etwas komplexer:


    Die Schwierigkeit hier ist das Erkennen eines Programmblocks, wenn eigentlich bei Erfüllung der Bedingung nichts mehr außer einem Sprungbefehl kommt.

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.

  • Das kann man noch komplexer gestalten:


    Hier ist erstmalig ein Zusammenfügen von Code nötig (die zwei "writeln" Statements).

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.

  • Wo ich allmählich Probleme bekomme, sind solche Konstrukte:


    Es ist also nötig, Statements via Programmregel zusammenzufassen, und diese "Blöcke" auch im BASIC-Code vorab zu erkennen.


    Ich suche eine Logik, um Code-Blöcke zusammenzusetzen, damit weiterhin eine Blockstruktur (vergleiche mit Nassi-Shneiderman Diagrammen) vorhanden ist.


    Verboten sind weiterhin Sprünge aus Schleifen !


    Also auf keinen Fall umsetzbar ist/soll umgesetzt werden:
    10 FOR I=1 TO 10
    20 IF I=5 THEN 40
    30 NEXT I
    40 PRINT “ENDE ERREICHT”

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.

  • Außerdem habe ich mir noch keine Gedanken für rückwärts gewandte GOTO-Sprünge in BASIC gemacht.

    Also so was:


    10 PRINT "TEST1"

    20 IF CONDITION1 THEN PRINT "TEST2":GOTO 60

    30 PRINT "TEST3"

    40 PRINT "TEST4"

    50 IF CONDITION2 THEN 10

    60 PRINT "TEST5"


    Das müsste eigentlich so in PASCAL aussehen, dass man einen Block von Zeilennummer 10 bis Zeilennummer 50 bilden müsste, aber der Sprung am Ende der Zeile 20 macht da einem einen Strich durch die Rechnung...

    Vielleicht kann man das durch Code-Wiederholungen entschärfen, wenn keine Blöcke bildbar sind.

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.

  • Vielleicht ist das hier die Lösung:


    Finde das aber anspruchsvoll, wenn man es in ein Programm dann immer so umwandeln muss.

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.

  • Eigentlich ist das ja


    Dazu muss der Compiler natürlich 'Break' können (wie z.B. Turbo Pascal).


    Mit so einem Ansatz "schöne" Pascal-Programme zu erstellen, halte ich allerdings für etwas "abitioniert". Subroutinen dürften eine ziemliche Herausforderung werden - da die in BASIC eben nicht nur je einen "Eingang und Ausgang" haben, der Rückgabewert (wenn es denn einen gibt) sehr schwer erkennbar ist (typischerweise auch gar nicht als solcher behandelt wird - Subroutinen machen normalerweise "viel"...) und sowas wie "Lokalität" in BASIC eben unbekannt ist.


    Decompiler (wie z.B. Ghidra) machen ja etwas ganz ähnliches, können das aber nur, weil sie davon ausgehen dürfen, dass ein Compiler den Maschinencode, den sie zurückübersetzen, erzeugt hat und deswegen auf entsprechende Muster scannen. Setzt man ihnen ein ursprünglich in Assembler geschriebenes Programm vor, kommt ziemlicher Spaghetticode raus.

  • Dein Code ist mit dem "break" erstmal eleganter (aber nur wenn es überhaupt "break" gibt).

    In BASIC-Quellen könnten noch mehr Verschachtelungen oder besser ausgedrückt, Spaghetti-Code existieren, da bin ich mir halt nicht sicher, ob man das mit dem Verknüpfen der "until" Bedingungen noch hinkriegt, aber auch nicht sicher, ob da noch "break" helfen wird.

    Muss mir nochmal Gedanken machen, wie man das nur bis zu einer bestimmten Tiefe der Verschachtelung erlauben kann, und ansonsten abbricht.

    Könnte auch sein, dass man mehrere "Pässe" braucht, aber ich glaube dann ist es ein Generationsprojekt.


    P.S.: Eben nachgeschaut, "break" in Verbindung mit dem "IF" gibt es z.B. nicht in TopSpeed PASCAL oder in UCSD PASCAL (und in der ISO PASCAL Definition). Scheinbar also nur in Turbo PASCAL, was schade ist. Ist wohl von C-Compilern abgeschaut worden.

    Dazu gibt es auch eine interessante Diskussion >hier<.

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.

  • lustiges problem. und dir ist die qualitaet des pascal codes wichtig, oder geht es nur darum, basic programme zum laufen zu bekommen?

    Eher letzteres, aber eben ohne GOTO in PASCAL.

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.

  • Könnte auch sein, dass man mehrere "Pässe" braucht, aber ich glaube dann ist es ein Generationsprojekt.

    Die wirst Du schon brauchen, wenn Du an Subroutinen mit GOSUB stösst:

    Code
    10 GOTO 40
    20 PRINT "HALLO"
    30 RETURN
    40 GOSUB 20
    50 END

    Du siehst erst in Zeile 40, dass die Zeilen 20 und 30 eine Subroutine sind, die Du ein eine PROCEDURE übersetzen musst. Oder kannst Du Dich in GWBASIC darauf verlassen, dass keine GOSUBs vorkommen? Ich habe mit GWBASIC noch nicht gearbeitet, daher kenne ich den Stil dort nicht. In Applesoft BASIC ist das sehr gebräuchlich.


    Die Idee finde ich richtig gut, die Komplexität ist aber wahrscheinlich schon bei kleinen Programmen recht groß.

    Denn Feindschaft wird durch Feindschaft nimmermehr gestillt; Versöhnlichkeit schafft Ruh’ – ein Satz, der immer gilt. Man denkt oft nicht daran, sich selbst zurückzuhalten; Wer aber daran denkt, der lässt den Zorn erkalten. Sprüche von Buddha, aus dem ‹Dhammapada›.


    Mein Netz: Acorn | Atari | Milan | Amiga | Apple //e und IIGS | Macintosh | SUN Sparc | NeXT |SGI | IBM RS/6000 | DEC Vaxstation und Decstation| Raspberry Pi | PCs mit OS/2, BeOS, Linux, AROS, Windows, BSD | Stand-alone: Apple //c und III | Commodore 128D | Sinclair QL | Amstrad | PDAs

  • also auf die gefahr hin, dass ich mit tomaten beworfen werde--

    wenn es keine gosubs gibt und keine rueckwaertssprunge, kann man bestimmt evtl. den

    "PC" einfach mitschleppen. wenn der basic code so aussieht, z.b.


    10 if A goto 60

    20 blkA

    30 if B goto 50

    40 goto 90

    50 blkC

    60 if C goto 80

    70 blkD

    80 blkE

    90 blkF


    wuerde man daraus das hier machen:


    goto = 10

    if goto == 10 A then goto=60 else goto=20

    if goto == 20: blkA; goto = 30

    if goto == 30 and B then goto=50 else goto=40

    if goto == 40 then goto = 90 else goto = 50

    if goto == 50 blkC goto = 60

    if goto == 60 and C then goto = 80 else goto = 70

    if goto == 70 blkD goto = 80

    if goto == 80 blkE goto = 90

    if goto == 90 blkF


    das muesste relativ leicht zu programmieren sein.

    rueckwaertsspruenge muesste man ueber repeat schleifen reinfriemeln koennen.

    absolut kein code, den man nutzen/bearbeiten will, aber vielleicht

    als erster "machbarkeits" prototyp brauchbar?

  • ... hab' ich schon mal erwähnt, daß der Hr. Dijkstra gerade wieder seine wahre Freude daran hätte ... und ein passendes Zitat dafür vorhanden ist.



    Davon abgesehen - das hier oben drüber würde man doch einfach in einen klassischen Switch / Case auflösen wollen.


    Code
    switch (variable)             |      case variable of
      case a (block)              |        a : (block)
      case b (block)              |        b : (block)
      case c (block)              |        c : (block)
      else   (alles andere)       |        else (block)
                                  |      end



    Und wegen der SUB Routinen per GOSUB (#11) , wäre es evtl. sinnvoll einen FirstPass Run zumachen und erstmal alle Sprünge und Sprungziele einzusammeln und dann evtl. sowas komplett rauszusortieren und in Prozeduren zu packen. Dann wird das schnell übersichtlicher.

    -- 1982 gab es keinen Raspberry Pi , aber Pi und Raspberries

  • Sowas ist auch nett:



    Wie man das wohl umsetzt?

    1ST1

  • Genau das, also erstmal alle Sprungziele und Unterroutinen im 1. Durchlauf sammeln ist essentiell, aber danach kommt halt die Umsetzung. Natürlich ohne GOTO, als Informatiker habe ich bei den vielen GOTOs fast Schnappatmung bekommen.

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.

  • Sowas ist auch nett:



    Wie man das wohl umsetzt?

    Ich bin recht routinierter Pascal-Programmierer, aber da kommt mir auch nichts in den Sinn.

    Ihr könnt ja mal versuchen hier nachzufragen, da hat es sehr viele Profis.

    Deutsches Lazarusforum - Foren-Übersicht

  • Das Beispiel ist ziemlich hypothetisch, d.h. so etwas findest Du in der Form nicht in (GW)BASIC-Programmen. Daher mache ich mir über dieses sehr unwahrscheinliche Konstrukt keinen Kopf...

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.

  • Das Beispiel ist ziemlich hypothetisch, d.h. so etwas findest Du in der Form nicht in (GW)BASIC-Programmen. Daher mache ich mir über dieses sehr unwahrscheinliche Konstrukt keinen Kopf...

    Sowas könnte in der Praxis etwa so aussehen, je nachdem, ob man auch den Titel will oder nicht.

    Code
    05 GOTO 100
    10 Print "Titel"
    20 Print "Text"
    30 Print "Text"
    40 RETURN
    100 REM Mit Titel
    110 GOSUB 10
    120 REM ohne Titel
    130 GOSUB 20
    140 END
  • Sowas

    Übrigens, ich hätte inzwischen eine Idee, wie es geht. Mal sehen, ob ihr darauf kommt.

    hat der Herr Fermat auch mal geschrieben. Die Leut' wissen bis heut' nicht, was er und ob er was gemeint hat. ( Info )


    https://xkcd.com/1381/




    Wie auch immer


    -- 1982 gab es keinen Raspberry Pi , aber Pi und Raspberries

  • Hypothetisch, aber es funktioniert in Basic. Und es muss ja auch nicht in jeder Zeile I=I+1 stehen, erst dann wirds interessant...


    Übrigens, ich hätte inzwischen eine Idee, wie es geht. Mal sehen, ob ihr darauf kommt.

    In etwas so würde ich es machen:

  • Ich habe die Diskussion hier nicht vollumfänglich gelesen. Ich habe eben einfach nur nach "Converter Basic to Pascal" geguurgelt und das hier gefunden.


    Basic to Pascal
    Download Basic to Pascal for free. Convert basic code to pascal. shBasic (formerly bas2pas) is a new programming language based on BASIC and the power and…
    sourceforge.net


    Ob das etwas für Peter z80.eu ist, keine Ahnung... zumal es die Bedingung GWBasic nicht erfüllt.

    Gruß Torsten

    BFZ MFA, ZX80Core, AX81, ZX81, ZX81NU, Spectrum+, Harlequin, MSX VG8010, Amstrad NC100, Cambridge Z88, C64, C128D, Amiga 500 & 1200, Atari Portfolio, HP200LX, IBM PC5155, TP755c, TP755cx, T20, T41, T61, PS/2 (Model 40SX), PS/2E, Accura 101, Apple //e, Sharp PC1401 & PC1403H, TI59 m. PC-100c, HP48SX & HP48GX


    An die Person, die meine Schuhe versteckt hat, während ich auf der Hüpfburg war: Werd' erwachsen! :motz:


    ::matrix::

  • Dort sind exakt die beiden Basic-Befehle "goto" und "gosub", um die es seit dem Ausgangsposting geht, geschickt ausgeschlossen, indem schon der Basic-Dialekt bedeutend moderner ist.

  • Hier hat sich wohl das Vorurteil der Spaghetti-Sprache durch gesetzt.
    Ein grosses Problem ist doch die Definition von Variablen.

    10 A=5

    20 B=3.5 + 1.5

    30 IF A=B Then ....

    40 REM Integer mit REAL vergleichen?

    50 REM "Wie viel Speicher brauchst du für die Strings?"

  • Das ist kein wirkliches Problem, weil in BASIC echte Integer Variablen auch tatsächlich extra markiert werden (z.B. als I%). D.h. bei deinem Beispiel ist A tatsächlich auch ein "float" / "real".




    Wenn Zeile 50 ein extra Frage ist:


    Strings sind da potentiell schon interessanter, weil das "normale" Pascal eigentlich Strings so anlegt, daß erst ein Byte kommt, worin die Länge steht und dann die Buchstaben folgen. Daher kann es dann auch maximal 255 Zeichen geben pro String. Das könnte evtl beim BASIC deutlich mehr sein, je nach Variante.

    -- 1982 gab es keinen Raspberry Pi , aber Pi und Raspberries