Benutzer-Werkzeuge

Webseiten-Werkzeuge


scriptstack

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
scriptstack [2025/12/15 01:56]
jango
scriptstack [2025/12/30 17:42] (aktuell)
admin [Models]
Zeile 1: Zeile 1:
 +=====Interna=====
 +
 +====Neuen Datentyp hinzufügen====
 +
 +Token.cs -> Neuen Tokentyp erstellen (Decimal)
 +Lexer.cs -> Neuen State hinzufügen (Decimal)
 +Lexer.cs::GetTokens() -> State und Daten erfassen
 +
 +Parser.cs::Literal() -> den Case decimal hinzufügen
 +Parser.cs::Atom() -> den case decimal hinzufügen 
 +
 +Interpreter.cd::Arithmetic() -> decimal auch berechnen
 +
 +Routine::Validate() -> decimal hinzufügen
 +
 =====Manager===== =====Manager=====
  
-The scripting system is initialised by creating one or more instances of the ScriptManager class. +Das Skriptsystem wird initialisiert, indem eine oder mehrere Instanzen der Klasse "Manager" erstellt werden. Jede Instanz repräsentiert eine Skriptumgebung, in der Skripte geladen und ausgeführt werden können. Jede Instanz stellt außerdem einen globalen Variablenbereich bereit, über den die Skripte Daten austauschen können.
-Each instance represents a scripting environment where scripts can be loaded and executed. Each +
-instance also provides a global variable scope that the scripts can use to share data.+
  
-<code>+<code csharp>
 Manager manager = new Manager(); Manager manager = new Manager();
 </code> </code>
Zeile 11: Zeile 24:
 =====Script===== =====Script=====
  
-Once a script manager is available, scripts can be loaded by creating instances of the Script class. +Sobald ein Manager verfügbar ist, können Skripte durch Erstellen von Instanzen der Klasse "Script" geladen werden. Der Konstruktor des Skriptobjekts benötigt eine Referenz auf den Skriptmanager und einen Namen zur Identifizierung des Skripts. Standardmäßig entspricht dieser Name einem Dateinamen auf der Festplatte.
-The script object's constructor requires a reference to the script manager and a name to identify +
-the script. By default, this name corresponds to a disk filename.+
  
-<code>+<code csharp>
 Script script = new Script(manager, "script.txt"); Script script = new Script(manager, "script.txt");
 </code> </code>
  
-The script object's constructor automatically compiles the script source into Conscript byte code. +Der Konstruktor des Skriptobjekts kompiliert den Skriptquellcode automatisch in Scriptstack-Bytecode. Standardmäßig wird der generierte Bytecode mithilfe eines "Peephole" Assembleroptimierers optimiert. Debug Anweisungen werden hinzugefügt, um die Zuordnung des generierten Codes zum Originalquellcode zu erleichtern. Diese Einstellungen können über die Methoden "Debug" und "Optimise" des "Manager" gesteuert werden.
-By default, the generated byte code is optimised using a "peephole" assembly optimiser. Debug +
-instructions are added to facilitate mapping of the generated code with the original source. These +
-settings may be controlled by setting the ScriptManager's properties DebugMode and +
-OptimiseCode.+
  
 =====Interpreter===== =====Interpreter=====
  
-A script object represents only the programming instructions contained within and not its +Ein Skriptobjekt repräsentiert lediglich Programmanweisungen (sog Token), nicht aber seinen Ausführungszustand. Um das Skript auszuführen, muss eine Instanz der Klasse "Interpreter" erstellt werden. Der Konstruktor dieser Klasse benötigt eine Referenz auf das auszuführende Skript oder eine Referenz auf eine seiner Funktionen. Eine Skriptreferenz bewirkt die Ausführung der "main"-Funktion. Der Skriptkontext ermöglicht die Ausführungssteuerung und den Zugriff auf den Ausführungszustand, einschließlich der während der Ausführung definierten Variablen, der nächsten auszuführenden Anweisung usw. Die Klasse "Interpreter" repräsentiert eine laufende Instanz eines Skripts. Daher können mehrere Instanzen desselben Skriptobjekts innerhalb desselben Skriptmanagers ausgeführt werden, indem mehrere Interpreter erstellt werden, die auf dasselbe Skript verweisen.
-execution state. To execute the script, an instance of the ScriptContext class must be created. The +
-class' constructor requires a reference to the script to be executed or a reference to one of the +
-script's functions. A script reference implies that the main function will be executed. The script +
-context provides execution control, as well as access to the execution state in terms of the variables +
-defined during execution, the next statement to be executed and so on. The ScriptContext class +
-represents a running instance of a script. Hence, multiple instances of the same script object can be +
-executed within the same script manager by creating multiple script contexts referencing the same +
-script.+
  
-<code>+<code csharp>
 // create a context for the script's main function // create a context for the script's main function
 Interpreter interpreter = new Interpreter(script); Interpreter interpreter = new Interpreter(script);
 +
 // also creates a context for the script's main function // also creates a context for the script's main function
 Interpreter interpreter = new Interpreter(script.MainFunction); Interpreter interpreter = new Interpreter(script.MainFunction);
 +
 // create a context for one of the script's named functions // create a context for one of the script's named functions
-Function scriptFunction = script.Functions["WanderAround"];+Function scriptFunction = script.Functions["Just looking..."];
 Interpreter interpreter = new Interpreter(scriptFunction); Interpreter interpreter = new Interpreter(scriptFunction);
 </code> </code>
  
-The script context object allows execution of the referenced script via the three variants of its +Das Interpreter-Objekt ermöglicht die Ausführung des referenzierten Skripts über drei Varianten seiner "Interpret()"-Methode: unbegrenzte Ausführung, Ausführung innerhalb eines bestimmten Zeitintervalls oder Ausführung bis zu einer maximalen Anzahl ausgeführter Anweisungen. Die erste Variante erlaubt die unbegrenzte Ausführung der referenzierten Skriptfunktion oder deren Beendigung. Enthält das Skript eine Endlosschleife, blockiert diese Methode unbegrenzt, sofern keine Unterbrechung ausgelöst wird. Die "Interpret()"-Methode gibt die Gesamtzahl der seit ihrem Aufruf ausgeführten Anweisungen zurück.
-Execute method. These are: execution of scripts for an indefinite amount of time; execution of +
-scripts for a given time interval or execution of scripts for up to a maximum number of executed +
-statements. +
-The first method variant allows the referenced script function to execute indefinitely or until the +
-end of the function is reached. If the script contains an infinite loop, this method will block +
-indefinitely unless an interrupt is generated. The Execute method returns the total number of +
-statements executed since its invocation.+
  
-<code> +<code csharp> 
-// execute indefinitely, or until termination, or until +// execute indefinitely, or until termination, or a script interrupt is generated 
-// a script interrupt is generated +interpreter.Interpret();
-scriptContext.Execute();+
 </code> </code>
  
-The second variant of the Execute method allows the script context to execute up to a given +Die zweite Variante der "Interpret()"-Methode ermöglicht es dem Interpreter, bis zu einer vorgegebenen maximalen Anzahl von Anweisungen auszuführen. Der Interpreter kann die Ausführung abbrechen, bevor das Maximum erreicht ist, wenn keine weiteren Anweisungen zu verarbeiten sind oder eine Unterbrechung ausgelöst wird.
-maximum number of statements. The script context may break out of execution before the +
-maximum is reached if there are no more statements to process or if an interrupt is generated.+
  
-<code>+<code csharp>
 // execute up to a maximumum of 10 statements // execute up to a maximumum of 10 statements
-scriptContext.Execute(10);+interpreter.Interpret(10);
 </code> </code>
  
-The third variant of the Execute method accepts a TimeSpan defining the maximum time interval +Die dritte Variante der "Interpret()"-Methode akzeptiert einen TimeSpan, der das maximal zulässige Zeitintervall für die Skriptausführung definiert. Die Methode kann die Ausführung vor Ablauf des angegebenen Intervalls abbrechen, wenn keine weiteren Anweisungen zu verarbeiten sind oder eine Unterbrechung ausgelöst wird. Bei einem Skript mit einer ausgewogenen Anzahl verschiedener Anweisungen kann diese Methode beispielsweise verwendet werden, um die Geschwindigkeit des Skriptsystems in der Zielumgebung in Bezug auf die pro Sekunde ausgeführten Anweisungen zu ermitteln.
-allowed for script execution. The method may break out of execution earlier than the given interval +
-if there are no more statements to process or an interrupt is generated. Given a script with a good +
-balance of different statements, a possible use of this method is to determine the speed of the +
-scripting system on the target environment in terms of statements executed per second.+
  
-<code>+<code csharp>
 // execute for up to 10 milliseconds // execute for up to 10 milliseconds
 TimeSpan tsInterval = new TimeSpan(0, 0, 0, 0, 10); TimeSpan tsInterval = new TimeSpan(0, 0, 0, 0, 10);
-scriptContext.Execute(tsInterval);+interpreter.Interpret(tsInterval);
 </code> </code>
  
-The second and third variants of Execute may be used to implement a virtual multi-threaded 
-scripting environment. Global variables may be used as semaphores to synchronise concurrently 
-running scripts. 
  
-A script context will normally execute its referenced script function indefinitely, for a given time +Ein Interpreter führt seine referenzierte Skriptfunktion normalerweise unbegrenzt für ein bestimmtes Zeitintervall aus, bis eine maximale Anzahl von Anweisungen ausgeführt wurde oder keine weiteren Anweisungen mehr zu verarbeiten sind. In manchen Fällen ist es jedoch wünschenswert, die Ausführung vorzeitig abzubrechen, beispielsweise um die Kontrolle an den Host zurückzugeben, sobald bestimmte Anweisungen ausgeführt wurden, oder weil ein Skript zu rechenintensiv ist, um es in einem Durchgang auszuführen. 
-interval, until a given maximum number of statements are executed or until there are no more +
-statements to process. In some cases it is desirable to break execution prematurely, such as to +
-return control to the host when specific statements are executed, or because a script is too +
-computationally intensive to execute in one go.+
 Conscript provides two ways for generating script interrupts: Conscript provides two ways for generating script interrupts:
  
Zeile 99: Zeile 80:
 =====Scanner===== =====Scanner=====
  
-To allow for loading of scripts from other sources -- such as an archive file, network or database -- +Um das Laden von Skripten aus anderen Quellen wie Archivdateien, dem Netzwerk oder Datenbanken zu ermöglichen, kann ein benutzerdefinierter Scanner an den Manager gebunden werden. Dieser Scanner kann jede Klasse sein, die das Interface `Scanner` implementiert. 
-a custom script loader class can be developed and bound to the script manager to be used for +
-loading the script. The script loader class may be any class that implements the ScriptLoader +
-interface. The loader is used to retrieve the script specified in the Script class constructor and also +
-any additional include scripts defined within the original script.+
  
-<code>+<code csharp>
 // custom script loader class // custom script loader class
-public class MyScriptLoader +public class MyScanner : Scanner
- : ScriptLoader+
 { {
- public List<string /> LoadScript(String strResourceName)+ public List<string /> Scan(String strResourceName)
  {  {
  // loader implementation here...  // loader implementation here...
  }  }
 } }
 +
 // in initialisation code... // in initialisation code...
-ScriptLoader scriptLoader = new MyScriptLoader(); +MyScanner scanner = new MyScanner(); 
-scriptManager.Loader = scriptLoader;+interpreter.scanner = scanner;
 </code> </code>
  
Zeile 123: Zeile 100:
 =====Variablen===== =====Variablen=====
  
-One approach for allowing a script to communicate with or control the host application entails the +Eine Möglichkeit, einem Skript die Kommunikation mit der Hostanwendung oder deren Steuerung zu ermöglichen, besteht darin, dass die Anwendung die lokalen Variablen des zugehörigen Interpreters und die globalen Variablen des zugehörigen Managers abfragt. Dies geschieht durch Abfragen der "LocalMemory"-Eigenschaft des "Interpreter"-Objekts, der "ScriptMemory"-Eigenschaft des "Script"-Objekts oder der "GlobalMemory"-Eigenschaft des "Manager"-Objekts.
-application polling the local variables of the associated script context and global variables of the +
-associated script manager. It does this by querying the LocalDictionary property of the +
-ScriptContext object, the ScriptDictionary property of the Script object or the +
-GlobalDicitonary property of the ScriptManager object.+
  
-<code>+<code csharp>
 // get value of local variable // get value of local variable
-int iIndex = (int) scriptContext.LocalDictionary["index"];+int i = (int)interpreter.LocalMemory["variableName"]; 
 // get value of script variable // get value of script variable
-int iScore = (int) script.ScriptDictionary["s_playerScore"];+int i = (int)script.ScriptMemory["variableName"]; 
 // get value of global variable // get value of global variable
-bool bNewQuest =  +int i = (int)manager.SharedMemory["variableName"];
- (bool) scriptManager.GlobalDictionary["g_wizardQuestAvailable"];+
 </code> </code>
  
Zeile 151: Zeile 125:
 functions registered beforehand. functions registered beforehand.
  
-<code> +<code csharp> 
-// define host function to move player +// define route 
-HostFunctionPrototype hostFunctionPrototype = new HostFunctionPrototype( +Routine routine = new Routine((Type)null, "Print", (Type)null, "A function to print text");
- null, "Player_MoveTo", typeof(int), typeof(int));+
 </code> </code>
  
Zeile 161: Zeile 134:
 List<Type>, is also provided: List<Type>, is also provided:
  
-<code>+<code csharp>
 // prepare parameter type list // prepare parameter type list
 List<Type> listParameterTypes = new List<Type>(); List<Type> listParameterTypes = new List<Type>();
-listParameterTypes.Add(typeof(String));+listParameterTypes.Add(typeof(string));
 listParameterTypes.Add(typeof(int)); listParameterTypes.Add(typeof(int));
 listParameterTypes.Add(typeof(int)); listParameterTypes.Add(typeof(int));
 listParameterTypes.Add(typeof(bool)); listParameterTypes.Add(typeof(bool));
-listParameterTypes.Add(typeof(AssociativeArray)); +listParameterTypes.Add(typeof(ArrayList)); 
-// define function prototype with many parameters + 
-HostFunctionPrototype hostFunctionPrototype = new HostFunctionPrototype( +// define routine with many parameters 
- typeof(float), "FuncWithManyParams", listParameterTypes);+Routine routine = new Routine((Type)null, "Print", listParameterTypes);
 </code> </code>
  
Zeile 180: Zeile 153:
 prototype without a handler: prototype without a handler:
  
-<code>+<code csharp>
 // register host function // register host function
-m_scriptManager.RegisterHostFunction(hostFunctionPrototype);+manager.Register(routine);
 </code> </code>
  
Zeile 192: Zeile 165:
 A.I. scripts in a game: A.I. scripts in a game:
  
-<code>   +<code csharp>   
-public class Enemy +public class Program : Host
- : HostFunctionHandler+
 { {
- // class implementation + 
- private ScriptContext m_scriptContext +    private Interpreter interpreter; 
- public Enemy(..., Script script, ...) + 
- { +    public Main(script script) 
- // create script context +    { 
- m_scriptContext = new ScriptContext(script); +        interpreter = new Interpreter(script); 
- // assign self as host function handler +        interpreter.Handler = this; 
- m_scriptContext.Handler = this; +    } 
- } +  
- // HostFunctionHandler implementation +    public object Invoke(String functionName, List<object> parameters) 
- public object OnHostFunctionCall(String strFunctionName,  +    { 
- List<object> listParameters) +        if (functionName == "Print") 
- { +        { 
- // handle random number generator +            string str = (int)parameters[0]; 
- if (strFunctionName == "GetRandom") +            Console.WriteLine(str); 
- { +            return; 
- int iMin = (int)listParameters[0]; +        } 
- int iMax = (int)listParameters[1]; +        return null; 
- return s_random.Next(iMin, iMax); +    } 
- } +     
- // handle enemy movement +}
- else if (strFunctionName == "Move") +
- { +
- int iDeltaX = (int)listParameters[0]; +
- int iDeltaY = (int)listParameters[1]; +
- Move(iDeltaX, iDeltaY); +
- } +
- // handle enemy direction +
- else if (strFunctionName == "SetDirection") +
- { +
- Direction = (EntityDirection)(int)listParameters[0]; +
- } +
- // handle enemy direction flag +
- else if (strFunctionName == "SetAutomaticDirection") +
- { +
- AutomaticDirection = (bool)listParameters[0]; +
- } +
- // handle enemy position query +
- else if (strFunctionName == "GetPosition") +
- { +
- AssociativeArray associativeArrayPosition =  +
- new AssociativeArray(); +
- associativeArrayPosition["X"] = this.X; +
- associativeArrayPosition["Y"] = this.Y; +
- return associativeArrayPosition; +
- } +
- // handle player position query +
- else if (strFunctionName == "GetPlayerPosition") +
- { +
- AssociativeArray associativeArrayPosition =  +
- new AssociativeArray(); +
- associativeArrayPosition["X"] = m_player.X; +
- associativeArrayPosition["Y"] = m_player.Y; +
- return associativeArrayPosition; +
- } +
- // handle enemy fire +
- else if (strFunctionName == "CastSpell") +
- { +
- Image imageSpell = Properties.Resources.EnemySpell; +
- int iDamage = m_enemyType == EnemyType.Wizard ? 40 : 20; +
- Spell spell =  +
- new Spell(m_enemies.Room.Spells,  +
- imageSpell, false, iDamage, Direction); +
- spell.X = X; +
- spell.Y = Y - 30; +
- m_enemies.Room.Spells.Add(spell); +
- return null; +
- } +
- return null; +
- }+
 </code> </code>
  
Zeile 276: Zeile 199:
 Alternatively, a host function prototype may be registered with an associated handler directly: Alternatively, a host function prototype may be registered with an associated handler directly:
  
-<code>+<code csharp>
 // register global Sine function // register global Sine function
-HostFunctionPrototype hostFunctionPrototype = new HostFunctionPrototype( +Routine routine = new Routine(typeof(float), "Print", typeof(float)); 
- typeof(float), "Sin", typeof(float)); +manager.Register(routine, printHandler); 
-m_scriptManager.RegisterHostFunction(hostFunctionPrototype, trigHandler);+
 // register global Cosine function // register global Cosine function
-HostFunctionPrototype hostFunctionPrototype = new HostFunctionPrototype( +routine = new Routine(typeof(float), "Read", typeof(float)); 
- typeof(float), "Cos", typeof(float)); +manager.Register(routine, readHandler);
-m_scriptManager.RegisterHostFunction(hostFunctionPrototype, trigHandler); +
-// register global Tangent function +
-HostFunctionPrototype hostFunctionPrototype = new HostFunctionPrototype( +
- typeof(float), "Tan", typeof(float)); +
-m_scriptManager.RegisterHostFunction(hostFunctionPrototype, trigHandler);+
 </code> </code>
  
Zeile 305: Zeile 223:
 illustrates an alternative implementation of the earlier trigonometry functions example: illustrates an alternative implementation of the earlier trigonometry functions example:
  
-<code>   +<code csharp>   
-public class TrigonometryModule +using ScriptStack.Runtime; 
- : HostModule +using System; 
-{ + 
- // list of functions stored statically for one-off creation +namespace ScriptStack { 
- private static ReadOnlyCollection<hostfunctionprototype /> + 
-s_listHostFunctionPrototypes; +    public class Example: Model { 
- // module constructor +     
- public TrigonometryModule() +        private static ReadOnlyCollection < Routine > exportedRoutines; 
- { + 
- // if list created, don't do anything else +        public Example() { 
- if (s_listHostFunctionPrototypes != null) return; + 
-  +            if (exportedRoutines != null) 
- // create list of function prototypes +                return; 
- List<hostfunctionprototype /> listHostFunctionPrototypes = + 
- new List<hostfunctionprototype />(); +            var r = new List<Routine>(); 
- HostFunctionPrototype hostFunctionPrototype = null; + 
- // add Sine prototype to list +            r.Add(new Routine(typeof (bool), "std.print", (Type) null, "Ausgabe auf der Konsole erzeugen.")); 
- hostFunctionPrototype =  +            r.Add(new Routine(typeof (int), "std.read", "Einen Tastenanschlag von der Konsole lesen.")); 
- new HostFunctionPrototype(typeof(float), "Sin", typeof(float)); +            r.Add(new Routine(typeof (string), "std.readLine", "Eine Zeile von der Konsole lesen.")); 
- listHostFunctionPrototypes.Add(hostFunctionPrototype); + 
- // add Cosine prototype to list +            exportedRoutines = r.AsReadOnly(); 
- hostFunctionPrototype =  + 
- new HostFunctionPrototype(typeof(float), "Cos", typeof(float)); +        } 
- listHostFunctionPrototypes.Add(hostFunctionPrototype); + 
- // add Tangent prototype to list +        public ReadOnlyCollection < Routine > Routines => exportedRoutines; 
- hostFunctionPrototype =  + 
- new HostFunctionPrototype(typeof(float), "Tan", typeof(float)); +        public object Invoke(string routine, List <object> parameters) { 
- listHostFunctionPrototypes.Add(hostFunctionPrototype); + 
- s_listHostFunctionPrototypes =  +            if (routine == "std.print") { 
- listHostFunctionPrototypes.AsReadOnly(); +                System.Console.Write(parameters[0]); 
- } +                return true; 
- // returns list of available functions +            } 
- public ReadOnlyCollection<hostfunctionprototype /> HostFunctionPrototypes + 
- { +            if (routine == "std.read") 
- get { return s_listHostFunctionPrototypes; } +                return (int) System.Console.ReadKey().Key; 
- } + 
- // implements functions +            if (routine == "std.readLine") 
- public object OnHostFunctionCall(String strFunctionName,  +                return System.Console.ReadLine(); 
- List<object> listParameters) + 
- { +            return null; 
- if (strFunctionName == "Sin") +        } 
- // implement Sine +    }
- return (float)Math.Sin((float)listParameters[0]); +
- else if (strFunctionName == "Cos") +
- // implement Cosine +
- return (float)Math.Cos((float)listParameters[0]); +
- else if (strFunctionName == "Tan") +
- // implement Tangent +
- return (float)Math.Tan((float)listParameters[0]); +
- // unknown function (should not happen) +
- throw new ExecutionException( +
- "Unimplemented function '" + strFunctionName + "'."); +
- }+
 } }
 </code> </code>
Zeile 364: Zeile 271:
 Host module registration is very similar to individual function registration: Host module registration is very similar to individual function registration:
  
-<code>+<code csharp>
 // create module instance // create module instance
-TrigonometryModule trigonometryModule = new TrigonometryModule();+Model example = new Example();
 // register module // register module
-m_scriptManager.RegisterHostModule(trigonometryModule)+Manager.Register(example)
 </code> </code>
scriptstack.1765760208.txt.gz · Zuletzt geändert: 2025/12/15 01:56 von jango