Seite 1 von 1

Pointer in Array aus Bytes speichern

Verfasst: 23.01.2013 23:06
von Bobo-Jack
Hallo, ich arbeite grad dran, eine die Ausführung einer Skriptsprache mit Purebasic umzusetzen, und das so schnell wie nur möglich.
Da hab ich mir gedacht ich übersetz den Skript in eine Art Bytecode (mit selbstausgedachtem Aufbau) und damit bei den Bedingungen der Zugriff auf die beiden verglichenen Werte möglichst schnell ist, wollte ich direkt mit Pointern drauf zugreifen, also die Pointer auf die Variablen einfach in den Bytecode schreiben.
Und so hätte ich nen Pointer als Integer in den Array gespeichert. Hab mal gehört, dass Arrays zusammenhängende Speicherbereiche sind, und bin daher auf folgende Idee für das Speichern gekommen. Funktioniert ... aber wahrscheinlich nicht der beste Weg für sowas.
Andererseits hab ich mal gehört, dass Integer nicht wirklich für das Speichern von Pointern geeignet sind.
Hat vielleicht jemand ne bessere Idee?

Code: Alles auswählen


; Array, eigentlich aus Bytes

Dim blub.a(10)

; Die Bytes 3 bis 6 speichern den Pointer...

pos = 3

; Wert des Integers, soll dann später als pointer funktionieren

CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
  x.i = 1234567890
CompilerElse
  x.i = 12345678904321
CompilerEndIf

Debug x

; Reinschreiben

PokeI(@blub(pos), x)

; Überprüfen

Debug PeekI(@blub(pos))

; ... so sieht der Array in Bytes aus

Debug "----"

For foo = 0 To 9
  Debug blub(foo)
Next
Weiter überlegt hab ich, dass die Pointer auch auf Funktionen zeigen könnten, die dann Ausgeführt werden und deren Rückgabewert dann verglichen wird. Naja eigentlich wollte ich einfach mal eure Kommentare zu der Methode hören. mfg daniel :D

Re: Pointer in Array aus Bytes speichern

Verfasst: 23.01.2013 23:19
von STARGÅTE
Irgendwie schmeißst du in deinem Beispielcode alles etwas durcheinander.

Wieso speicherst du in einem Byte-Array Integers?
Wenn du gleich ein IntegerArray nehmen würdest, brauchst du auch kein PeekI() mehr...
Alles etwas komisch.

Für eine schnelle Scriptsprache würde ich dir einen Funktions/Prozedur-Baum empfehlen.
Das heißt, du erstellst für alles mögliche eine Procedure (Addiere zwei Werte, Lese eine Zahl aus dem Speicher, Push & Pop).
Danach kannst du einen Byte-Code erstellen (besteht nicht aus einzel Bytes!) der dann abgearbeitet wird:

Code: Alles auswählen

Position Anweisung
0        PUSH 123
8        PUSH 456
16        ADD
20       POP x
x wäre danach dann 579

Re: Pointer in Array aus Bytes speichern

Verfasst: 23.01.2013 23:31
von Bobo-Jack
Den Bytecode wollte ich eigentlich nur aus Bytes machen um Speicher zu sparen, alle anderen Werte außer den Pointern wären zw. 0 und 255 gewesen... aber ich glaub du hast recht, Speicher zu sparen ist nicht wirklich nötig bei der verfügbaren Menge. Is nur so ne Angewohnheit.

Hab ich vielleicht die Idee vom Bytecode missverstanden? Dachte mir das so, dass es für jede Art Anweisung einen eindeutigen Wert gibt, der dann an die Stelle im Bytecode kommt und die Kette von Werten dann eine Anweisungssequenz "nachbaut".

Deine Idee klingt logisch und ganz praktisch... könnte ich meine Procedures dann über Pointer im Bytecode aufrufen?

Re: Pointer in Array aus Bytes speichern

Verfasst: 23.01.2013 23:47
von STARGÅTE
Bobo-Jack hat geschrieben:Dachte mir das so, dass es für jede Art Anweisung einen eindeutigen Wert gibt, der dann an die Stelle im Bytecode kommt und die Kette von Werten dann eine Anweisungssequenz "nachbaut".
Jo klar geht das, aber dann brauchst du ja "ein Übersetzer" welcher die Anweisung in einen Prozeduraufruf umwandelt.
Bobo-Jack hat geschrieben:Deine Idee klingt logisch und ganz praktisch... könnte ich meine Procedures dann über Pointer im Bytecode aufrufen?
Ja das geht, hier mal ein ganz einfachen Beispiel:

Code: Alles auswählen

Prototype.i Function(Parameter.i)

Structure ScriptCall
	Function.Function
	Parameter.i
EndStructure

Structure Script
	Call.ScriptCall[0]
EndStructure

Procedure EvaluateScript(*Script.Script)
	Protected Call.i
	While *Script\Call[Call]\Function
		*Script\Call[Call]\Function(*Script\Call[Call]\Parameter)
		Call + 1
	Wend
EndProcedure


Procedure FunktionA(Parameter.i)
	Debug "FunktionA mit Parameter "+Str(Parameter) 
EndProcedure

Procedure FunktionB(Parameter.i)
	Debug "FunktionB mit Parameter "+Str(Parameter) 
EndProcedure



Define *Script.Script = AllocateMemory(3*SizeOf(ScriptCall)) ; Platz für 2 Aufrufe mit Paramater und ein leeren Platz für Abbruchbedingung.
*Script\Call[0]\Function = @FunktionA()
*Script\Call[0]\Parameter = 123
*Script\Call[1]\Function = @FunktionB()
*Script\Call[1]\Parameter = 456


EvaluateScript(*Script)
Unten erstelle ich im Speicher eine Art Bytecode, wo genau drin steht, welche Funktion aufgerufen werden soll, mit welchem Parameter.
Danach wird der Code mit EvaluateScript() einfach ausgeführt und die Prozeduren jeweils aufgerufen.

Edit: Als Parameter kannst du dann zB auch den Pointer einer Variable übergeben, in die eine Definierte Funktion dann reinschreibt.

Re: Pointer in Array aus Bytes speichern

Verfasst: 23.01.2013 23:53
von Bobo-Jack
Klasse, danke :D

Werd das dann so in der Art machen, aber eine Frage hab ich noch: So haben ja dann alle Funktionen die gleiche Zahl an Parametern, weil es ja immer derselbe Prototype ist. Oder?

edit:

bin beim durchlesen anderer threads auf eine andere methode gestoßen, die funktion aufzurufen.

wenn man

Code: Alles auswählen

*Script\Call[Call]\Function(*Script\Call[Call]\Parameter)
durch

Code: Alles auswählen

CallFunctionFast(*Script\Call[Call]\Function, *Script\Call[Call]\Parameter)
ersetzt, funktioniert der code genauso. worin besteht der unterschied?

danke nochmal :)

Re: Pointer in Array aus Bytes speichern

Verfasst: 24.01.2013 00:07
von STARGÅTE
Bobo-Jack hat geschrieben:So haben ja dann alle Funktionen die gleiche Zahl an Parametern, weil es ja immer derselbe Prototype ist. Oder?
Richtig, in dem Fall einen.
Aber du kannst genauso gut immer 2 Parameter übergeben, oder (was vllt günstiger ist) einfach die Adresse im Bytecode, wo alle Parameter aufgelistet sind. der eine Parameter ist dann einfach die Adresse und die Funktion die ihn nutzt, liest dann von dort eine Integer und eine Float.
Dann müsstest du allerdings noch eine Art Sprung einbauen, denn dann liegen die Funktionen ja nicht mehr geordnet vor.
Jede Funktion muss dann noch eine Adresse bekommen, wo die nächste Funktion ist.
Bobo-Jack hat geschrieben:bin beim durchlesen anderer threads auf eine andere methode gestoßen, die funktion aufzurufen.
Diese "andere" Methode ist älter und auch nicht so flexibel wie das "neue" Prototyp.

EDIT:
Noch ein wichtiger Hinweis: Da in meiner Methode echte Adresse genutzt werden, kannst du den Code nicht speichern und dann später wieder einlesen, weil bei einem andere Programmstart es ja andere Adresse geben kann.
Dann solltest du doch die Methode der definierten Anweisungszahlen nutzen und in einer Tabelle nach der passenden Funktion suchen.

Das sieht dann so aus:

Code: Alles auswählen

Prototype.i Function(Parameter.i)

Structure ScriptCall
	Function.i
	Parameter.i
EndStructure

Structure Script
	Call.ScriptCall[0]
EndStructure

Structure FunctionList
	Function.Function[0]
EndStructure

Global *FunctionList.FunctionList = ?FunctionList

Procedure EvaluateScript(*Script.Script)
	Protected Call.i
	While *Script\Call[Call]\Function
		*FunctionList\Function[*Script\Call[Call]\Function](*Script\Call[Call]\Parameter)
		Call + 1
	Wend
EndProcedure


Procedure FunktionA(Parameter.i)
	Debug "FunktionA mit Parameter "+Str(Parameter) 
EndProcedure

Procedure FunktionB(Parameter.i)
	Debug "FunktionB mit Parameter "+Str(Parameter) 
EndProcedure



Define *Script.Script = AllocateMemory(3*SizeOf(ScriptCall)) ; Platz für 2 Aufrufe mit Paramater und ein leeren Platz für Abbruchbedingung.
*Script\Call[0]\Function = 1 ; FunktionA
*Script\Call[0]\Parameter = 123
*Script\Call[1]\Function = 2 ; FunktionB
*Script\Call[1]\Parameter = 456


EvaluateScript(*Script)


DataSection
	FunctionList:
	Data.i 0
	Data.i @FunktionA()
	Data.i @FunktionB()
EndDataSection

Re: Pointer in Array aus Bytes speichern

Verfasst: 28.01.2013 17:48
von Bobo-Jack
Vielen dank, habs hinbekommen. Skriptsprache mit "Compiler" und Bytecode-Interpreter, inclusive Variablen-Management und allem. :)