Hallo Besucher, der Thread wurde 32k mal aufgerufen und enthält 170 Antworten

letzter Beitrag von EgonOlsen71 am

BASIC V2 Interpreter/Compiler in/für Java

  • Ein kleines Feature-Update nach einiger Zeit: MOSpeed kann jetzt auch SYS mit Parametern kompilieren. Also sowas:


    Code
    1. SYS S,XP,Y,A$

    oder, aus Data Beckers Super-Graphik-Buch, sowas:


    Code
    1. SYS 51221,X,40*COS(X/20)+100,50*SIN(X/30)+100,X/1.6


    SYS mit Parametern ist in BASIC V2 allerdings keine korrekte Syntax. Das Prinzip ist, dass der Interpreter die Kontrolle an das aufgerufene Maschinenprogramm abgibt, bevor er merkt, dass hinter dem SYS XXXX noch was kommt (mit dem er nichts anfangen könnte). Das Maschinenprogramm muss dann dafür sorgen, diese Parameter zu lesen und dabei den Interpreterstatus entsprechend so zu korrigieren, dass diese Parameter nach dem Rücksprung in den Interpreter nicht mehr gelesen werden, sondern dahinter weiterinterpretiert wird.

    Das Problem bei Compilern ist nun, dass all das eigentlich nicht geht. Deswegen unterstützt das auch kein BASIC-Compiler von damals (jedenfalls kenne ich keinen). Es ist ja kein BASIC-Programm mehr da, aus dem das Maschinenprogramm die Parameter selber herauslesen könnte und die Variablen sind auch keine Variablen im Sinne des BASIC-Interpreters mehr.

    Um das zu lösen, erzeugt MOSpeeds Compiler-Runtime zur Laufzeit den nötigen Teil des BASIC-Programms in einem Puffer und lässt den Interpreter zeitweise darauf zeigen. Damit "denkt" das Maschinenprogramm hinter dem SYS-Aufruf, es würde tatsächlich normalen BASIC-Code lesen und der Aufruf funktioniert. Nachteil: Das ist in den meisten Fällen langsamer, als wenn man den Aufruf direkt im unkompilierten BASIC gemacht hätte. Da der Rest des Programms aber weiterhin ganz normal beschleunigt wird, sollte das in den meisten Fällen nicht ins Gewicht fallen.

  • Um das zu lösen, erzeugt MOSpeeds Compiler-Runtime zur Laufzeit den nötigen Teil des BASIC-Programms in einem Puffer und lässt den Interpreter zeitweise darauf zeigen. Damit "denkt" das Maschinenprogramm hinter dem SYS-Aufruf, es würde tatsächlich normalen BASIC-Code lesen und der Aufruf funktioniert. Nachteil: Das ist in den meisten Fällen langsamer, als wenn man den Aufruf direkt im unkompilierten BASIC gemacht hätte. Da der Rest des Programms aber weiterhin ganz normal beschleunigt wird, sollte das in den meisten Fällen nicht ins Gewicht fallen.

    Naja, finde ich auch nicht so schlimm, dass hier das aufgerufene SYS-Programm seine Parameter "interpretiert". Der Grund für solche SYS-Aufrufe - also zumindest bei mir - waren Routinen, die ja eine Sachen deutlich schneller erledigen, als dies "zu Fuß" mit BASIC möglich ist. Also z.B. aus einer Datei zuverlässig eine Zeile einlesen, oder Strings sortieren. Da wäre die interpretierte Parameterübergabe ohnehin vernachlässigbar.


    Da stellt sich mir die Frage, wie dann mit den vielen impliziten Datenrückgabemöglichkeiten umgegangen wird.


    Z.B. SYSF1,A$,1,20,13

    liest in die Stringvariable A$ einen String von Datei #1 max 20 Zeichen bis zu einem Trennzeichen 13 ein.

    A$ ist ein Ausgabeparameter. Dieser nimmt lediglich den Stringdescriptor eines neu angelegten Strings auf. D.h. die String-Allocation funktioniert im Compilat genauso?


    Oder SYSF2,F$(0),N sortiert ein String-Array F$ ab Index 0 für N Elemente. Dabei werden die String-Descriptoren im Array getauscht. Ist diese Datenstruktur im Compilat überhaupt vorhanden?


    Vermutlich versteh ich den MOSpeed hier intern auch gar nicht ...

  • Da stellt sich mir die Frage, wie dann mit den vielen impliziten Datenrückgabemöglichkeiten umgegangen wird.

    Gar nicht...;)


    Lesen geht noch über diesen oben beschriebenen Weg, aber der Rückweg ist leider nicht möglich. Dein Maschinenprogramm wird diese Variablen gar nicht erst finden, weil sie der zur Laufzeit erzeugte BASIC-Programmteil nicht enthält. Dann müsste man das komplette Variablenmanagment des Interpreters nachbilden...:X

  • Der Basic-Boss hat das mit den Parametern hinter SYS ganz gut hinbekommen - allerdings nur im lesenden Zugriff. Eine Rückgabe von Werten war nicht möglich ...

    Ja, stimmt. Aber nur, wenn man den OTHERON-Parameter im Code ergänzt hat. Dann muss der sowas ähnliches machen, jedenfalls ist die Geschwindigkeit ähnlich (niedrig).

  • Lesen geht noch über diesen oben beschriebenen Weg, aber der Rückweg ist leider nicht möglich. Dein Maschinenprogramm wird diese Variablen gar nicht erst finden, weil sie der zur Laufzeit erzeugte BASIC-Programmteil nicht enthält. Dann müsste man das komplette Variablenmanagment des Interpreters nachbilden...

    Das hab ich eh befürchtet. Ist aber eigentlich auch egal. Auch jetzt nur aus meiner Sicht: Die SYS-Bibliotheken, die ich mir gemacht habe, habe ich ja eben aus dem Grund verwendet, weil ich mir damit einen Compiler erspart habe. Daher wäre es aus meiner Sicht ohnehin nicht sinnvoll, dann ein Compilat zu erstellen, dass dann nur noch eher unwichtige Teile (den Glue-Code einer Applikation) beim Interpretieren "beschleunigt". :D

  • Beim Basic Boss ist es schade, dass bei DIM-Anweisungen keine Variabeln genutzt werden dürfen. Zudem gibt es auch Probleme, Basic-Code so anzupassen, dass die Direktiven genutzt werden können.


    Unten ist ein Ausschnit aus einem Basic-Programm. Wie kann man das so anpassen, dass ein Kompilat funktioniert.


  • Hmm, gar nicht, würde ich sagen. Ich weiß nicht genau, was das macht, aber irgendwie liest es ja scheinbar Zeilen ein und spielt mit dem Data-Zeiger rum. Das ist zu sehr auf den Interpreter ausgelegt, als dass man das vernünftig kompilieren kann.

    Was die DIM-Anweisung mit Variablen angeht: Das ist so üblich bei BASIC-Compilern, weil die die Strukturen dafür schon beim Kompilieren anlegen. Man könnte das sicherlich auch dynamisch machen, aber dann ist man schon wieder halb beim Interpreter. MOSpeed kann mit Variablen im DIM umgehen, wenn es eigentlich Konstanten sind. D.h. wenn du die oben im Programm irgendwo zuweist und dann für das DIM nutzt und sonst nie wieder veränderst, dann erkenne ich das und erlaube es für DIM.

  • Danke!


    Du hast recht mit den Zeilen. Code stammt aus dem Spiel (Robox). Es werden Texte ausgegeben. Die Ausgabe ist aber mit Bedingungen verknüpft.

    Ich wollte das in P-Code wandeln und mittels an der SCPU angepassten RT-Code mit dieser nutzen.



    Die Austro-/Blitz- Compiler verarbeiten DIM-Anweisungen mit Variabeln. Es sind auch die Einzigen, die das machen.

    "Basic Boss", "Basic 64 Compiler", "Laser Compiler", "DTL Compiler", "Speed Compiler", "Pet Speed" usw machen das nicht.

    Alles unter 10 braucht nicht per DIM deklariert werden. Oben genannte Compiler mögen das nicht. "Basic Boss" nutzt dann immer 10. Alle anderen Compiler fragen nach.

  • Ein neues Feature: Man kann jetzt "Löcher" in das Kompilat schneiden. Das kompilierte Programm wird ja oftmals größer als das BASIC-Programm. Deswegen hatte ich öfter das Problem, dass das Kompilat plötzlich Speicher belegt, den das BASIC-Programm für was anderes nutzen wollte, z.B. Zeichensätze oder Bitmap-Grafik. Das führt dann ohne Änderungen dazu, dass sich das Kompilat selbst überschreibt, was nicht zielführend ist. Abhilfe bisher war entweder, das Kompilat über den /progstart-Parameter woanders beginnen zu lassen oder über /compactlevel=xx zu versuchen, auf Kosten der Performance, kompakteren Code erzeugen zu lassen.

    Jetzt gibt es noch eine dritte Option: Über den /memhole-Parameter kann man angeben, welche Speicherbereiche nicht benutzt werden sollen. Das Programm wird dann quasi um diese Bereiche "herumkompiliert". Dadurch wird das PRG-File länger, weil das Loch da mit enthalten ist, aber man kann damit quasi Speicher mitten im Programm nutzen, ohne dieses zu zerstören.


    Beispielaufruf:

    Code
    1. mospeed affine.bas -memhole=$4000-$63ff

    Das kompiliert meinen alten Texturemapper so, dass der Bereich von $4000 bis $63FF nicht benutzt wird, weil dort die Bitmap und ein Teil des Farbspeichers liegen. Die Abgrenzung ist nicht ganz trennscharf, d.h. der Code hört nicht exakt bei $4000 auf (aber er fängt bei genau $6400 wieder an), weil man sonst evtl. Code zerreißen könnte, dem das nicht gut bekommt.


    Im Anhang ist das verwendete Beispielprogramm als BASIC-Code und fertig kompiliert.