From d6e6d9237763f021bed8b8a2dea4ff8853ea3fde Mon Sep 17 00:00:00 2001 From: relt-1 <60782515+relt-1@users.noreply.github.com> Date: Tue, 26 Sep 2023 21:11:14 +0200 Subject: [PATCH] Wip markdown files --- .../Internals/IBaseScriptingInterface.md | 0 src/QScript/Contributing/Internals/QArgs.md | 0 .../Contributing/Internals/QCallback.md | 0 src/QScript/Contributing/Internals/QClass.md | 0 .../Contributing/Internals/QFunction.md | 0 .../Contributing/Internals/QInterface.md | 0 src/QScript/Contributing/Internals/QModule.md | 0 src/QScript/Contributing/Internals/QObject.md | 0 .../Contributing/Rundown/QScriptRundown1.md | 16 +++ .../Contributing/Rundown/QScriptRundown2.md | 12 ++ .../Contributing/Rundown/QScriptRundown3.md | 114 ++++++++++++++++++ .../Contributing/Rundown/QScriptRundown4.md | 12 ++ 12 files changed, 154 insertions(+) create mode 100644 src/QScript/Contributing/Internals/IBaseScriptingInterface.md create mode 100644 src/QScript/Contributing/Internals/QArgs.md create mode 100644 src/QScript/Contributing/Internals/QCallback.md create mode 100644 src/QScript/Contributing/Internals/QClass.md create mode 100644 src/QScript/Contributing/Internals/QFunction.md create mode 100644 src/QScript/Contributing/Internals/QInterface.md create mode 100644 src/QScript/Contributing/Internals/QModule.md create mode 100644 src/QScript/Contributing/Internals/QObject.md create mode 100644 src/QScript/Contributing/Rundown/QScriptRundown1.md create mode 100644 src/QScript/Contributing/Rundown/QScriptRundown2.md create mode 100644 src/QScript/Contributing/Rundown/QScriptRundown3.md create mode 100644 src/QScript/Contributing/Rundown/QScriptRundown4.md diff --git a/src/QScript/Contributing/Internals/IBaseScriptingInterface.md b/src/QScript/Contributing/Internals/IBaseScriptingInterface.md new file mode 100644 index 0000000..e69de29 diff --git a/src/QScript/Contributing/Internals/QArgs.md b/src/QScript/Contributing/Internals/QArgs.md new file mode 100644 index 0000000..e69de29 diff --git a/src/QScript/Contributing/Internals/QCallback.md b/src/QScript/Contributing/Internals/QCallback.md new file mode 100644 index 0000000..e69de29 diff --git a/src/QScript/Contributing/Internals/QClass.md b/src/QScript/Contributing/Internals/QClass.md new file mode 100644 index 0000000..e69de29 diff --git a/src/QScript/Contributing/Internals/QFunction.md b/src/QScript/Contributing/Internals/QFunction.md new file mode 100644 index 0000000..e69de29 diff --git a/src/QScript/Contributing/Internals/QInterface.md b/src/QScript/Contributing/Internals/QInterface.md new file mode 100644 index 0000000..e69de29 diff --git a/src/QScript/Contributing/Internals/QModule.md b/src/QScript/Contributing/Internals/QModule.md new file mode 100644 index 0000000..e69de29 diff --git a/src/QScript/Contributing/Internals/QObject.md b/src/QScript/Contributing/Internals/QObject.md new file mode 100644 index 0000000..e69de29 diff --git a/src/QScript/Contributing/Rundown/QScriptRundown1.md b/src/QScript/Contributing/Rundown/QScriptRundown1.md new file mode 100644 index 0000000..9210daa --- /dev/null +++ b/src/QScript/Contributing/Rundown/QScriptRundown1.md @@ -0,0 +1,16 @@ +# QScript Rundown Page 1 + +QScript is like onions. It has layers. + +1. Game +2. QScript +3. Interfaces +4. Languages + +The top layer is the game itself. That's where you talk with QScript to add modules, functions, classes, objects, etc. + +QScript is the second layer, it talks with the language interfaces about what files to load, what functions to call, etc. + +Interfaces actually talk with the scripting languages themselves. But to QScript, each one behaves the same way. There **cannot** be any language specific functionalities that are related to QScript and not the lanugage itself. + +[Next ->][QScriptRundown2] \ No newline at end of file diff --git a/src/QScript/Contributing/Rundown/QScriptRundown2.md b/src/QScript/Contributing/Rundown/QScriptRundown2.md new file mode 100644 index 0000000..4be589c --- /dev/null +++ b/src/QScript/Contributing/Rundown/QScriptRundown2.md @@ -0,0 +1,12 @@ +# QScript Rundown Page 2 + +If you want to add a feature to QScript, you first have to decide what layer it should lie in. If you want to add a new entity to QScript, you just modify the top-level game layer. If you want to add a new scripting functionality, you might want to modify QScript and the interfaces, but if you want to add something to a scripting language, you must modify its source code directly. + +An example of modifying a scripting language is what had to be done with Squirrel. + +Squirrel does not support inheriting from userdata, so what had to be done is to modify the source code of it to make it possible. +Same thing with changing the class after it has been created. I have added a _finish metamethod which gets called when the class is finished defining its methods. Its return value is what the class will be set to at the end. + +The fact that you can inherit from a userdata, and then get another userdata instance should not be possible in regular Squirrel. This is an example of modifying the scripting language to fit our needs. + +[<- Prev][QScriptRundown1.md] | [Next ->][QScriptRundown3.md] \ No newline at end of file diff --git a/src/QScript/Contributing/Rundown/QScriptRundown3.md b/src/QScript/Contributing/Rundown/QScriptRundown3.md new file mode 100644 index 0000000..5440f6d --- /dev/null +++ b/src/QScript/Contributing/Rundown/QScriptRundown3.md @@ -0,0 +1,114 @@ +# QScript Rundown Page 3 + +Lets talk about `QObject`s. + +A full `QObject` structure looks like this: + +```cpp +struct QObject +{ + struct QClass* cls; + union QValue vars[]; +}; +``` + +The structure is pretty complex. + +Lets try to understand it piece by piece. + +A `QObject` contains a pointer to a `QClass`. The `QClass` pointer is shared by `QObject`s which use the same class. +The QObject also contains a list of [QValues][QValue] which are the individual unique variables of the QObject. + +--- + +```cpp +struct QClass +{ + const char* name; + + int vars_count; + struct QVar* vars; + + int methods_count; + struct QFunction* methods; + + int sigs_count; + struct QInterface** sigs; +}; +``` + +Let's go one level deeper and this is where we start to branch out. We will tackle `QVar* vars` first. + +--- + +```cpp +struct QVar +{ + enum QType type; + const char* name; + int size; + bool is_private; + union QValue defaultval; +}; +``` + +`QVar` is basically a definition of a variable in a class. It stores the name, type, default value, etc. The `size` is used to determine the initial size of the string if the `type` is a `QType_String` + +A `QClass` will store a pointer to a list of these, along with the amount. They are in fact, used as a reference to the `QValue vars[]` which are a 1:1 representation of the `QVar* vars*` in the class. In other words, an index in the `QVar* vars*` array in the `QClass` corresponds to the value in `QValue vars[]` in the QObject. + +--- + +```cpp +enum QFunctionType +{ + QFunction_Native, + QFunction_Scripting, + QFunction_Module, + QFunction_Void, +}; + +struct QFunction +{ + int always_zero; + enum QFunctionType type; + union + { + QCFunc func_native; + QCallback* func_scripting; + QModuleFunction* func_module; + void* func_void; + }; +}; +``` + +`QFunction` is more of a wrapper around multiple types of functions. The each slot in the union has a corresponding `QFunctionType`. But what you might notice is the `always_zero` variable. Why is it there? + +There is this quirk with scripting languages where they will write their entire scripting base libraries in their own C api, and then pass these base library functions as a normal pointer to the language. Which basically means that they will treat every C function as a regular function pointer and not a struct. Function pointers have a very special tendency to not be 0 (DUH). +We can take advantage of that by first checking if the `QFunction` `always_zero` is 0, and if its not, we just CALL the QFunction pointer directly. But if it is 0, we can be 99.9% sure that it is actually a `QFunction` struct and we can treat it as such. + +--- + +```cpp +typedef struct +{ + int count; + enum QType* types; +} QParams; + +typedef struct +{ + int count; + const char** names; + struct QParams* args; +} QInterface; +``` + +A `QInterface` is a list of function declarations. Not definitions. A `QInterface` only stores the name, and arguments of each function. The actual implementation is up to the `QClass`. + +When a `QClass` inherits from another `QClass`, it creates a new `QInterface` the parent `QInterface` **pointers** get copied into the interface array before the new one. Not the `QInterface`s themselves. This saves on memory. + +We plan on adding actual interface functionality to the scripting languages, showing off to functional scripting language developers what modern OOP languages can do. + +--- + +[<- Prev][QScriptRundown2.md] | [Next ->][QScriptRundown4.md] diff --git a/src/QScript/Contributing/Rundown/QScriptRundown4.md b/src/QScript/Contributing/Rundown/QScriptRundown4.md new file mode 100644 index 0000000..d24ce67 --- /dev/null +++ b/src/QScript/Contributing/Rundown/QScriptRundown4.md @@ -0,0 +1,12 @@ +# QScript Rundown Page 4 + +By the nature of QScript, it has been designed to be a appframework interface. It means that anything in the game can use it. + +If you want to use QScript in your own dll, first you have to connect to it. + +Use the `CreateInterfaceFn` function with the `QSCRIPT_INTERFACE_VERSION` parameter which will return a (IQScript*). +$_SMALL Remember to check for null values! _$ +```cpp +qscript = (IQScript*)appSystemFactory(QSCRIPT_INTERFACE_VERSION, NULL) +``` +(appSystemFactory is a `CreateInterfaceFn` you get in the `Init` or `Connect` function of a DLL class)