From: John Hodge Date: Fri, 20 Apr 2012 14:18:51 +0000 (+0800) Subject: Usermode - Removed SpiderScript X-Git-Tag: rel0.15~714^2~1 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=956e8a29de884d0e12351552b6f4b5ad2e3c1b4c;p=tpg%2Facess2.git Usermode - Removed SpiderScript - It had outgrown Acess, and has been removed > Now at git.mutabah.net/spiderscript.git --- diff --git a/Usermode/Applications/init_src/Makefile b/Usermode/Applications/init_src/Makefile index c8a6ddb5..df032bcd 100644 --- a/Usermode/Applications/init_src/Makefile +++ b/Usermode/Applications/init_src/Makefile @@ -5,7 +5,6 @@ CPPFLAGS += CFLAGS += -Wall -Werror -O3 LDFLAGS += -# -lspiderscript BIN = init OBJ = main.o diff --git a/Usermode/Applications/init_src/main.c b/Usermode/Applications/init_src/main.c index 4d66654c..c18e5f8c 100644 --- a/Usermode/Applications/init_src/main.c +++ b/Usermode/Applications/init_src/main.c @@ -4,50 +4,16 @@ #include #include #include -//#include //#include "common.h" // === CONSTANTS === #define NUM_TERMS 4 #define DEFAULT_TERMINAL "/Devices/VTerm/0" #define DEFAULT_SHELL "/Acess/SBin/login" -#define DEFAULT_SCRIPT "/Acess/Conf/BootConf.isc" #define ARRAY_SIZE(x) ((sizeof(x))/(sizeof((x)[0]))) // === PROTOTYPES === -/* -tSpiderVariable *Script_System_IO_Open(tSpiderScript *, int, tSpiderVariable *); -*/ - -// === GLOBALS === -/* -tSpiderFunction gaScriptNS_IO_Fcns[] = { - {"Open", Script_System_IO_Open} -}; -tSpiderNamespace gaScriptNS_System[] = { - { - "IO", - 0, NULL, - ARRAY_SIZE(gaScriptNS_IO_Fcns), gaScriptNS_IO_Fcns, - 0, NULL - } -}; - -tSpiderNamespace gaScriptNamespaces[] = { - { - "System", - ARRAY_SIZE(gaScriptNS_System), gaScriptNS_System, - 0, NULL, - 0, NULL - } -}; - -tSpiderVariant gScriptVariant = { - "init", 0, - ARRAY_SIZE(gaScriptNamespaces), gaScriptNamespaces -}; -*/ // === CODE === /** @@ -85,26 +51,3 @@ int main(int argc, char *argv[]) return 42; } -/** - * \brief Reads and parses the boot configuration script - * \param Filename File to parse and execute - */ -void ExecuteScript(const char *Filename) -{ - /* - tSpiderScript *script; - script = SpiderScript_ParseFile(&gScriptVariant, Filename); - SpiderScript_ExecuteMethod(script, ""); - SpiderScript_Free(script); - */ -} - -/** - * \brief Open a file - */ -/* -tSpiderVariable *Script_System_IO_Open(tSpiderScript *Script, int NArgs, tSpiderVariable *Args) -{ - return NULL; -} -*/ diff --git a/Usermode/Libraries/libspiderscript.so_src/Makefile b/Usermode/Libraries/libspiderscript.so_src/Makefile deleted file mode 100644 index 8988c01a..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# Acess 2 -# - -include ../Makefile.cfg - -CPPFLAGS += -CFLAGS += -Wall -LDFLAGS += -lc -lgcc -soname libspiderscript.so --no-allow-shlib-undefined - -OBJ = main.o lex.o parse.o ast.o exports.o values.o -OBJ += ast_to_bytecode.o bytecode_gen.o bytecode_makefile.o -OBJ += exec.o exec_bytecode.o -BIN = libspiderscript.so - -include ../Makefile.tpl diff --git a/Usermode/Libraries/libspiderscript.so_src/Scripts/sample.isc b/Usermode/Libraries/libspiderscript.so_src/Scripts/sample.isc deleted file mode 100644 index d9ec0205..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/Scripts/sample.isc +++ /dev/null @@ -1,44 +0,0 @@ -# diff --git a/Usermode/Libraries/libspiderscript.so_src/Scripts/sample_static.ssc b/Usermode/Libraries/libspiderscript.so_src/Scripts/sample_static.ssc deleted file mode 100644 index f490fb82..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/Scripts/sample_static.ssc +++ /dev/null @@ -1,29 +0,0 @@ -# diff --git a/Usermode/Libraries/libspiderscript.so_src/ast.c b/Usermode/Libraries/libspiderscript.so_src/ast.c deleted file mode 100644 index eb839961..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/ast.c +++ /dev/null @@ -1,739 +0,0 @@ -/* - * Acess2 Init - * - Script AST Manipulator - */ -#include -#include -#include -#include "common.h" -#include "ast.h" - -// === IMPORTS === -extern void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...); - -// === CODE === -/** - * \brief Append a function to a script - */ -int AST_AppendFunction(tSpiderScript *Script, const char *Name, int ReturnType, tAST_Node *Args, tAST_Node *Code) -{ - tScript_Function *fcn; - int arg_count = 0, arg_bytes = 0; - tAST_Node *arg; - - // Count and size arguments - for(arg = Args; arg; arg = arg->NextSibling) - { - arg_count ++; - arg_bytes += sizeof(fcn->Arguments[0]) + strlen(Args->DefVar.Name) + 1; - } - - // Allocate information - fcn = malloc( sizeof(tScript_Function) + arg_bytes + strlen(Name) + 1 ); - if(!fcn) return -1; - fcn->Next = NULL; - fcn->Name = (char*)&fcn->Arguments[arg_count]; - strcpy(fcn->Name, Name); - fcn->ReturnType = ReturnType; - fcn->ArgumentCount = arg_count; - fcn->ASTFcn = Code; - fcn->BCFcn = NULL; - - // Set arguments - arg_bytes = strlen(Name) + 1; // Used as an offset into fcn->Name - arg_count = 0; - for(arg = Args; arg; arg = arg->NextSibling) - { - fcn->Arguments[arg_count].Name = fcn->Name + arg_bytes; - strcpy(fcn->Arguments[arg_count].Name, arg->DefVar.Name); - fcn->Arguments[arg_count].Type = arg->DefVar.DataType; - arg_bytes += strlen(arg->DefVar.Name) + 1; - arg_count ++; - } - - if(Script->LastFunction == NULL) { - Script->Functions = Script->LastFunction = fcn; - } - else { - Script->LastFunction->Next = fcn; - Script->LastFunction = fcn; - } - - return 0; -} - -/** - * \name Node Manipulation - * \{ - */ -#define WRITE_N(_buffer, _offset, _len, _dataptr) do { \ - if(_buffer) memcpy((char*)_buffer + _offset, _dataptr, _len);\ - _offset += _len; \ -} while(0) - -#define WRITE_8(_buffer, _offset, _val) do {\ - uint8_t v = (_val);\ - WRITE_N(_buffer, _offset, 1, &v);\ -} while(0) -#define WRITE_16(_buffer, _offset, _val) do {\ - uint16_t v = (_val);\ - WRITE_N(_buffer, _offset, 2, &v);\ -} while(0) -#define WRITE_32(_buffer, _offset, _val) do {\ - uint32_t v = (_val);\ - WRITE_N(_buffer, _offset, 4, &v);\ -} while(0) -#define WRITE_64(_buffer, _offset, _val) do {\ - uint64_t v = (_val);\ - WRITE_N(_buffer, _offset, 8, &v);\ -} while(0) -#define WRITE_REAL(_buffer, _offset, _val) do {\ - double v = (_val);\ - WRITE_N(_buffer, _offset, sizeof(double), &v);\ -} while(0) - -#define WRITE_STR(_buffer, _offset, _string) do {\ - int len = strlen(_string);\ - WRITE_16(_buffer, _offset, len);\ - WRITE_N(_buffer, _offset, len, _string);\ - if((_offset & 1) == 1)WRITE_8(_buffer, _offset, 0); \ - if((_offset & 3) == 2)WRITE_16(_buffer, _offset, 0); \ -} while(0) -#define WRITE_NODELIST(_buffer, _offset, _listHead) do {\ - tAST_Node *node; \ - size_t ptr = -1;\ - for(node=(_listHead); node; node = node->NextSibling) {\ - ptr = _offset;\ - _offset += AST_WriteNode(_buffer, _offset, node); \ - WRITE_32(_buffer, ptr, ptr); \ - } \ - if(ptr != -1){ptr -= 4; WRITE_32(_buffer, ptr, 0);} \ -} while(0) - -/** - * \brief Writes a script dump to a buffer - * \return Size of encoded data - * \note If \a Buffer is NULL, no write is done, but the size is still returned - */ -size_t AST_WriteScript(void *Buffer, tSpiderScript *Script) -{ - tScript_Function *fcn; - size_t ret = 0, ptr = 0; - int i; - - for( fcn = Script->Functions; fcn; fcn = fcn->Next ) - { -// printf("fcn = %p, fcn->Name = %p\n", fcn, fcn->Name); - ptr = ret; - WRITE_32(Buffer, ret, 0); // Next - WRITE_STR(Buffer, ret, fcn->Name); - WRITE_32(Buffer, ret, fcn->ArgumentCount); - for( i = 0; i < fcn->ArgumentCount; i ++ ) - { - WRITE_16(Buffer, ret, fcn->Arguments[i].Type); - WRITE_STR(Buffer, ret, fcn->Arguments[i].Name); - } - ret += AST_WriteNode(Buffer, ret, fcn->ASTFcn); - WRITE_32(Buffer, ptr, ret); // Actually set `Next` - } - if( ptr ) - { - ptr -= 4; - WRITE_32(Buffer, ptr, 0); // Clear next for final - } - - return ret; -} - -/** - * \brief Write a node to a file - */ -size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node) -{ - size_t baseOfs = Offset; - - if(!Node) { - //fprintf(stderr, "Possible Bug - NULL passed to AST_WriteNode\n"); - WRITE_32(Buffer, Offset, 0); - WRITE_16(Buffer, Offset, NODETYPE_NOP); - WRITE_16(Buffer, Offset, 0); // Line (0) - return 0; - } - - WRITE_32(Buffer, Offset, 0); // Next - WRITE_16(Buffer, Offset, Node->Type); - // TODO: Scan the buffer for the location of the filename (with NULL byte) - // else, write the string at the end of the node - WRITE_16(Buffer, Offset, Node->Line); // Line - //WRITE_32(Buffer, Offset, 0); // File - - switch(Node->Type) - { - // Block of code - case NODETYPE_BLOCK: - WRITE_NODELIST(Buffer, Offset, Node->Block.FirstChild); - break; - - // Function Call - case NODETYPE_METHODCALL: - Offset += AST_WriteNode(Buffer, Offset, Node->FunctionCall.Object); - case NODETYPE_FUNCTIONCALL: - case NODETYPE_CREATEOBJECT: - // TODO: Search for the same function name and add a pointer - WRITE_STR(Buffer, Offset, Node->FunctionCall.Name); - WRITE_NODELIST(Buffer, Offset, Node->FunctionCall.FirstArg); - break; - - // If node - case NODETYPE_IF: - Offset += AST_WriteNode(Buffer, Offset, Node->If.Condition); - Offset += AST_WriteNode(Buffer, Offset, Node->If.True); - Offset += AST_WriteNode(Buffer, Offset, Node->If.False); - break; - - // Looping Construct (For loop node) - case NODETYPE_LOOP: - WRITE_8(Buffer, Offset, Node->For.bCheckAfter); - WRITE_STR(Buffer, Offset, Node->For.Tag); - Offset += AST_WriteNode(Buffer, Offset, Node->For.Init); - Offset += AST_WriteNode(Buffer, Offset, Node->For.Condition); - Offset += AST_WriteNode(Buffer, Offset, Node->For.Increment); - Offset += AST_WriteNode(Buffer, Offset, Node->For.Code); - break; - - // Asignment - case NODETYPE_ASSIGN: - WRITE_8(Buffer, Offset, Node->Assign.Operation); - Offset += AST_WriteNode(Buffer, Offset, Node->Assign.Dest); - Offset += AST_WriteNode(Buffer, Offset, Node->Assign.Value); - break; - - // Casting - case NODETYPE_CAST: - WRITE_8(Buffer, Offset, Node->Cast.DataType); - Offset += AST_WriteNode(Buffer, Offset, Node->Cast.Value); - break; - - // Define a variable - case NODETYPE_DEFVAR: - WRITE_32(Buffer, Offset, Node->DefVar.DataType); - // TODO: Duplicate compress the strings - WRITE_STR(Buffer, Offset, Node->DefVar.Name); - Offset += AST_WriteNode(Buffer, Offset, Node->DefVar.InitialValue); - break; - - // Scope Reference - case NODETYPE_SCOPE: - case NODETYPE_ELEMENT: - WRITE_STR(Buffer, Offset, Node->Scope.Name); - Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value); - break; - - // Unary Operations - case NODETYPE_RETURN: - case NODETYPE_BWNOT: - case NODETYPE_LOGICALNOT: - case NODETYPE_NEGATE: - case NODETYPE_POSTINC: - case NODETYPE_POSTDEC: - Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value); - break; - - // Binary Operations - case NODETYPE_INDEX: - case NODETYPE_ADD: - case NODETYPE_SUBTRACT: - case NODETYPE_MULTIPLY: - case NODETYPE_DIVIDE: - case NODETYPE_MODULO: - case NODETYPE_BITSHIFTLEFT: - case NODETYPE_BITSHIFTRIGHT: - case NODETYPE_BITROTATELEFT: - case NODETYPE_BWAND: case NODETYPE_LOGICALAND: - case NODETYPE_BWOR: case NODETYPE_LOGICALOR: - case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR: - case NODETYPE_EQUALS: case NODETYPE_NOTEQUALS: - case NODETYPE_LESSTHAN: case NODETYPE_LESSTHANEQUAL: - case NODETYPE_GREATERTHAN: case NODETYPE_GREATERTHANEQUAL: - Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Left); - Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Right); - break; - - // Node types with no children - case NODETYPE_NOP: - break; - case NODETYPE_VARIABLE: - case NODETYPE_CONSTANT: - case NODETYPE_BREAK: - case NODETYPE_CONTINUE: - // TODO: De-Duplicate the strings - WRITE_STR(Buffer, Offset, Node->Variable.Name); - break; - case NODETYPE_STRING: - WRITE_32(Buffer, Offset, Node->Constant.String.Length); - WRITE_N(Buffer, Offset, Node->Constant.String.Length, Node->Constant.String.Data); - break; - case NODETYPE_INTEGER: - WRITE_64(Buffer, Offset, Node->Constant.Integer); - break; - case NODETYPE_REAL: - WRITE_REAL(Buffer, Offset, Node->Constant.Real); - break; - case NODETYPE_NULL: - break; - - //default: - // fprintf(stderr, "AST_WriteNode: Unknown node type %i\n", Node->Type); - // break; - } - - return Offset - baseOfs; -} - -/** - * \brief Free a node and all subnodes - */ -void AST_FreeNode(tAST_Node *Node) -{ - tAST_Node *node; - - if(!Node) return ; - - // Referenced counted file name - (*(int*)(Node->File - sizeof(int))) -= 1; - if( *(int*)(Node->File - sizeof(int)) == 0 ) - free( (void*)(Node->File - sizeof(int)) ); - - switch(Node->Type) - { - // Block of code - case NODETYPE_BLOCK: - for( node = Node->Block.FirstChild; node; ) - { - tAST_Node *savedNext = node->NextSibling; - AST_FreeNode(node); - node = savedNext; - } - break; - - // Function Call - case NODETYPE_METHODCALL: - AST_FreeNode(Node->FunctionCall.Object); - case NODETYPE_FUNCTIONCALL: - case NODETYPE_CREATEOBJECT: - for( node = Node->FunctionCall.FirstArg; node; ) - { - tAST_Node *savedNext = node->NextSibling; - AST_FreeNode(node); - node = savedNext; - } - break; - - // If node - case NODETYPE_IF: - AST_FreeNode(Node->If.Condition); - AST_FreeNode(Node->If.True); - AST_FreeNode(Node->If.False); - break; - - // Looping Construct (For loop node) - case NODETYPE_LOOP: - AST_FreeNode(Node->For.Init); - AST_FreeNode(Node->For.Condition); - AST_FreeNode(Node->For.Increment); - AST_FreeNode(Node->For.Code); - break; - - // Asignment - case NODETYPE_ASSIGN: - AST_FreeNode(Node->Assign.Dest); - AST_FreeNode(Node->Assign.Value); - break; - - // Casting - case NODETYPE_CAST: - AST_FreeNode(Node->Cast.Value); - break; - - case NODETYPE_SCOPE: - case NODETYPE_ELEMENT: - AST_FreeNode(Node->Scope.Element); - break; - - // Define a variable - case NODETYPE_DEFVAR: - AST_FreeNode(Node->DefVar.InitialValue); - break; - - // Unary Operations - case NODETYPE_RETURN: - case NODETYPE_BWNOT: - case NODETYPE_LOGICALNOT: - case NODETYPE_NEGATE: - case NODETYPE_POSTINC: - case NODETYPE_POSTDEC: - AST_FreeNode(Node->UniOp.Value); - break; - - // Binary Operations - case NODETYPE_INDEX: - case NODETYPE_ADD: - case NODETYPE_SUBTRACT: - case NODETYPE_MULTIPLY: - case NODETYPE_DIVIDE: - case NODETYPE_MODULO: - case NODETYPE_BITSHIFTLEFT: - case NODETYPE_BITSHIFTRIGHT: - case NODETYPE_BITROTATELEFT: - case NODETYPE_BWAND: case NODETYPE_LOGICALAND: - case NODETYPE_BWOR: case NODETYPE_LOGICALOR: - case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR: - case NODETYPE_EQUALS: case NODETYPE_NOTEQUALS: - case NODETYPE_LESSTHAN: case NODETYPE_LESSTHANEQUAL: - case NODETYPE_GREATERTHAN: case NODETYPE_GREATERTHANEQUAL: - AST_FreeNode( Node->BinOp.Left ); - AST_FreeNode( Node->BinOp.Right ); - break; - - // Node types with no children - case NODETYPE_NOP: break; - case NODETYPE_NULL: break; - case NODETYPE_VARIABLE: break; - case NODETYPE_CONSTANT: break; - case NODETYPE_BREAK: - case NODETYPE_CONTINUE: break; - - case NODETYPE_STRING: - case NODETYPE_INTEGER: - case NODETYPE_REAL: - if( Node->ValueCache ) - SpiderScript_DereferenceValue(Node->ValueCache); - Node->ValueCache = NULL; - break; - } - free( Node ); -} - -tAST_Node *AST_int_AllocateNode(tParser *Parser, int Type, int ExtraSize) -{ - tAST_Node *ret = malloc( sizeof(tAST_Node) + ExtraSize ); - ret->NextSibling = NULL; - ret->File = Parser->Filename; *(int*)(Parser->Filename - sizeof(int)) += 1; - ret->Line = Parser->CurLine; - ret->Type = Type; - - // Runtime Caching - ret->BlockState = NULL; - ret->BlockIdent = 0; - ret->ValueCache = NULL; - - return ret; -} - -tAST_Node *AST_NewCodeBlock(tParser *Parser) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_BLOCK, 0 ); - - ret->Block.FirstChild = NULL; - ret->Block.LastChild = NULL; - - return ret; -} - -void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child) -{ - // Ignore NULL children - if( !Child ) return ; - - Child->NextSibling = NULL; - switch( Parent->Type ) - { - case NODETYPE_BLOCK: - if(Parent->Block.FirstChild == NULL) { - Parent->Block.FirstChild = Parent->Block.LastChild = Child; - } - else { - Parent->Block.LastChild->NextSibling = Child; - Parent->Block.LastChild = Child; - } - break; - default: - fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type); - break; - } -} - -tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_IF, 0); - ret->If.Condition = Condition; - ret->If.True = True; - ret->If.False = False; - return ret; -} - -tAST_Node *AST_NewLoop(tParser *Parser, const char *Tag, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code) -{ - tAST_Node *ret; - if(!Tag) Tag = ""; - // NOTE: The +3) & ~3 is to align the size to 4 bytes, and shut valgrind up - // - GCC sometimes inlines strlen as a loop of dword reads, triggering valgrind - ret = AST_int_AllocateNode(Parser, NODETYPE_LOOP, (strlen(Tag) + 1 + 3) & ~3); - ret->For.Init = Init; - ret->For.bCheckAfter = !!bPostCheck; - ret->For.Condition = Condition; - ret->For.Increment = Increment; - ret->For.Code = Code; - strcpy(ret->For.Tag, Tag); - return ret; -} - -tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_ASSIGN, 0); - - if( Dest->Type != NODETYPE_VARIABLE && Dest->Type != NODETYPE_ELEMENT && Dest->Type != NODETYPE_INDEX ) - { - free(ret); - SyntaxError(Parser, 1, "Assign target is not a variable or attribute (instead %i)", - Dest->Type); - AST_FreeNode(Dest); - AST_FreeNode(Value); - return NULL; - } - - ret->Assign.Operation = Operation; - ret->Assign.Dest = Dest; - ret->Assign.Value = Value; - - return ret; -} - -tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_CAST, 0); - - ret->Cast.DataType = Target; - ret->Cast.Value = Value; - - return ret; -} - -tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, Operation, 0); - - ret->BinOp.Left = Left; - ret->BinOp.Right = Right; - - return ret; -} - -/** - */ -tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, Operation, 0); - - ret->UniOp.Value = Value; - - return ret; -} - -tAST_Node *AST_NewBreakout(tParser *Parser, int Type, const char *DestTag) -{ - int len = (DestTag ? strlen(DestTag) : 0); - tAST_Node *ret = AST_int_AllocateNode(Parser, Type, len + 1); - - if( DestTag ) - strcpy(ret->Variable.Name, DestTag); - else - ret->Variable.Name[0] = '\0'; - - return ret; -} - -tAST_Node *AST_NewNop(tParser *Parser) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_NOP, 0); - - return ret; -} - -/** - * \brief Create a new string node - */ -tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_STRING, Length + 1); - - ret->Constant.Type = SS_DATATYPE_STRING; - ret->Constant.ReferenceCount = 1; - ret->Constant.String.Length = Length; - memcpy(ret->Constant.String.Data, String, Length); - ret->Constant.String.Data[Length] = '\0'; - - return ret; -} - -/** - * \brief Create a new integer node - */ -tAST_Node *AST_NewInteger(tParser *Parser, int64_t Value) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_INTEGER, 0); - ret->Constant.Type = SS_DATATYPE_INTEGER; - ret->Constant.ReferenceCount = 1; - ret->Constant.Integer = Value; - return ret; -} - -/** - * \brief Create a new real number node - */ -tAST_Node *AST_NewReal(tParser *Parser, double Value) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_REAL, 0); - ret->Constant.Type = SS_DATATYPE_REAL; - ret->Constant.ReferenceCount = 1; - ret->Constant.Real = Value; - return ret; -} - -/** - * \brief Return a null value - */ -tAST_Node *AST_NewNull(tParser *Parser) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_NULL, 0); - - return ret; -} - -/** - * \brief Create a new variable reference node - */ -tAST_Node *AST_NewVariable(tParser *Parser, const char *Name) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_VARIABLE, strlen(Name) + 1 ); - strcpy(ret->Variable.Name, Name); - return ret; -} - -/** - * \brief Create a new variable definition node - */ -tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_DEFVAR, strlen(Name) + 1 ); - - ret->DefVar.DataType = Type; - ret->DefVar.InitialValue = NULL; - strcpy(ret->DefVar.Name, Name); - - return ret; -} - -/** - * \brief Create a new runtime constant reference node - */ -tAST_Node *AST_NewConstant(tParser *Parser, const char *Name) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_CONSTANT, strlen(Name) + 1 ); - - strcpy(ret->Variable.Name, Name); - - return ret; -} - -/** - * \brief Create a function call node - * \note Argument list is manipulated using AST_AppendFunctionCallArg - */ -tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_FUNCTIONCALL, strlen(Name) + 1 ); - - ret->FunctionCall.Object = NULL; - ret->FunctionCall.FirstArg = NULL; - ret->FunctionCall.LastArg = NULL; - ret->FunctionCall.NumArgs = 0; - strcpy(ret->FunctionCall.Name, Name); - - return ret; -} -tAST_Node *AST_NewMethodCall(tParser *Parser, tAST_Node *Object, const char *Name) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_METHODCALL, strlen(Name) + 1 ); - - ret->FunctionCall.Object = Object; - ret->FunctionCall.FirstArg = NULL; - ret->FunctionCall.LastArg = NULL; - ret->FunctionCall.NumArgs = 0; - strcpy(ret->FunctionCall.Name, Name); - - return ret; -} - -tAST_Node *AST_NewCreateObject(tParser *Parser, const char *Name) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_CREATEOBJECT, strlen(Name) + 1 ); - - ret->FunctionCall.Object = NULL; - ret->FunctionCall.FirstArg = NULL; - ret->FunctionCall.LastArg = NULL; - ret->FunctionCall.NumArgs = 0; - strcpy(ret->FunctionCall.Name, Name); - - return ret; -} - -/** - * \brief Append an argument to a function call - */ -void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg) -{ - if( Node->Type != NODETYPE_FUNCTIONCALL - && Node->Type != NODETYPE_CREATEOBJECT - && Node->Type != NODETYPE_METHODCALL) - { - fprintf(stderr, "BUG REPORT: AST_AppendFunctionCallArg on an invalid node type (%i)\n", Node->Type); - return ; - } - - if(Node->FunctionCall.LastArg) { - Node->FunctionCall.LastArg->NextSibling = Arg; - Node->FunctionCall.LastArg = Arg; - } - else { - Node->FunctionCall.FirstArg = Arg; - Node->FunctionCall.LastArg = Arg; - } - Node->FunctionCall.NumArgs ++; -} - -/** - * \brief Add a scope node - */ -tAST_Node *AST_NewScopeDereference(tParser *Parser, const char *Name, tAST_Node *Child) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_SCOPE, strlen(Name) + 1 ); - ret->Scope.Element = Child; - strcpy(ret->Scope.Name, Name); - return ret; -} - -/** - * \brief Add a scope node - */ -tAST_Node *AST_NewClassElement(tParser *Parser, tAST_Node *Object, const char *Name) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_ELEMENT, strlen(Name) + 1 ); - ret->Scope.Element = Object; - strcpy(ret->Scope.Name, Name); - return ret; -} - -/** - * \} - */ diff --git a/Usermode/Libraries/libspiderscript.so_src/ast.h b/Usermode/Libraries/libspiderscript.so_src/ast.h deleted file mode 100644 index a6620fc2..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/ast.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - */ -#ifndef _AST_H_ -#define _AST_H_ - -#include -#include "tokens.h" - -typedef enum eAST_NodeTypes tAST_NodeType; -typedef struct sAST_Script tAST_Script; -typedef struct sAST_Function tAST_Function; -typedef struct sAST_Node tAST_Node; -typedef struct sAST_BlockState tAST_BlockState; -typedef struct sAST_Variable tAST_Variable; - -/** - * \brief Node Types - */ -enum eAST_NodeTypes -{ - NODETYPE_NOP, - - NODETYPE_BLOCK, //!< Node Block - - // 2 - NODETYPE_VARIABLE, //!< Variable - NODETYPE_CONSTANT, //!< Runtime Constant - NODETYPE_STRING, //!< String Constant - NODETYPE_INTEGER, //!< Integer Constant - NODETYPE_REAL, //!< Real Constant - NODETYPE_NULL, - - // 8 - NODETYPE_DEFVAR, //!< Define a variable (Variable) - NODETYPE_SCOPE, //!< Dereference a Namespace/Class static - NODETYPE_ELEMENT, //!< Reference a class attribute - NODETYPE_CAST, //!< Cast a value to another (Uniop) - - // 12 - NODETYPE_RETURN, //!< Return from a function (reserved word) - NODETYPE_BREAK, //!< Break out of a loop - NODETYPE_CONTINUE, //!< Next loop iteration - NODETYPE_ASSIGN, //!< Variable assignment operator - NODETYPE_POSTINC, //!< Post-increment (i++) - Uniop - NODETYPE_POSTDEC, //!< Post-decrement (i--) - Uniop - NODETYPE_FUNCTIONCALL, //!< Call a function - NODETYPE_METHODCALL, //!< Call a class method - NODETYPE_CREATEOBJECT, //!< Create an object - - // 21 - NODETYPE_IF, //!< Conditional - NODETYPE_LOOP, //!< Looping Construct - - // 23 - NODETYPE_INDEX, //!< Index into an array - - // 24 - NODETYPE_LOGICALNOT, //!< Logical NOT operator - NODETYPE_LOGICALAND, //!< Logical AND operator - NODETYPE_LOGICALOR, //!< Logical OR operator - NODETYPE_LOGICALXOR, //!< Logical XOR operator - - NODETYPE_EQUALS, //!< Comparison Equals - NODETYPE_NOTEQUALS, //!< Comparison Not Equals - NODETYPE_LESSTHAN, //!< Comparison Less Than - NODETYPE_LESSTHANEQUAL, //!< Comparison Less Than or Equal - NODETYPE_GREATERTHAN, //!< Comparison Greater Than - NODETYPE_GREATERTHANEQUAL, //!< Comparison Greater Than or Equal - - NODETYPE_BWNOT, //!< Bitwise NOT - NODETYPE_BWAND, //!< Bitwise AND - NODETYPE_BWOR, //!< Bitwise OR - NODETYPE_BWXOR, //!< Bitwise XOR - - NODETYPE_BITSHIFTLEFT, //!< Bitwise Shift Left (Grow) - NODETYPE_BITSHIFTRIGHT, //!< Bitwise Shift Right (Shrink) - NODETYPE_BITROTATELEFT, //!< Bitwise Rotate Left (Grow) - - NODETYPE_NEGATE, //!< Negagte - NODETYPE_ADD, //!< Add - NODETYPE_SUBTRACT, //!< Subtract - NODETYPE_MULTIPLY, //!< Multiply - NODETYPE_DIVIDE, //!< Divide - NODETYPE_MODULO, //!< Modulus -}; - -struct sAST_Node -{ - tAST_Node *NextSibling; - tAST_NodeType Type; - - const char *File; - int Line; - - void *BlockState; //!< BlockState pointer (for cache integrity) - int BlockIdent; //!< Ident (same as above) - void *ValueCache; //!< Cached value / pointer - - union - { - struct { - tAST_Node *FirstChild; - tAST_Node *LastChild; - } Block; - - struct { - int Operation; - tAST_Node *Dest; - tAST_Node *Value; - } Assign; - - struct { - tAST_Node *Value; - } UniOp; - - struct { - tAST_Node *Left; - tAST_Node *Right; - } BinOp; - - struct { - tAST_Node *Object; - tAST_Node *FirstArg; - tAST_Node *LastArg; - int NumArgs; - char Name[]; - } FunctionCall; - - struct { - tAST_Node *Condition; - tAST_Node *True; - tAST_Node *False; - } If; - - struct { - tAST_Node *Init; - int bCheckAfter; - tAST_Node *Condition; - tAST_Node *Increment; - tAST_Node *Code; - char Tag[]; - } For; - - /** - * \note Used for \a NODETYPE_VARIABLE and \a NODETYPE_CONSTANT - */ - struct { - char _unused; // Shut GCC up - char Name[]; - } Variable; - - struct { - tAST_Node *Element; - char Name[]; - } Scope; // Used by NODETYPE_SCOPE and NODETYPE_ELEMENT - - struct { - int DataType; - tAST_Node *InitialValue; - char Name[]; - } DefVar; - - struct { - int DataType; - tAST_Node *Value; - } Cast; - - // Used for NODETYPE_REAL, NODETYPE_INTEGER and NODETYPE_STRING - tSpiderValue Constant; - }; -}; - -/** - * \brief Code Block state (stores local variables) - */ -struct sAST_BlockState -{ - tAST_BlockState *Parent; - tSpiderScript *Script; //!< Script - tAST_Variable *FirstVar; //!< First variable in the list - tSpiderValue *RetVal; - tSpiderNamespace *BaseNamespace; //!< Base namespace (for entire block) - tSpiderNamespace *CurNamespace; //!< Currently selected namespace - int Ident; //!< ID number used for variable lookup caching - const char *BreakTarget; - int BreakType; -}; - -struct sAST_Variable -{ - tAST_Variable *Next; - int Type; // Only used for static typing - tSpiderValue *Object; - char Name[]; -}; - -// === FUNCTIONS === -extern tAST_Script *AST_NewScript(void); -extern size_t AST_WriteScript(void *Buffer, tSpiderScript *Script); -extern size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node); - -extern int AST_AppendFunction(tSpiderScript *Script, const char *Name, int ReturnType, tAST_Node *FirstArg, tAST_Node *Code); - -extern tAST_Node *AST_NewNop(tParser *Parser); - -extern tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length); -extern tAST_Node *AST_NewInteger(tParser *Parser, int64_t Value); -extern tAST_Node *AST_NewReal(tParser *Parser, double Value); -extern tAST_Node *AST_NewNull(tParser *Parser); - -extern tAST_Node *AST_NewVariable(tParser *Parser, const char *Name); -extern tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name); -extern tAST_Node *AST_NewConstant(tParser *Parser, const char *Name); -extern tAST_Node *AST_NewClassElement(tParser *Parser, tAST_Node *Object, const char *Name); - -extern tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name); -extern tAST_Node *AST_NewCreateObject(tParser *Parser, const char *Name); -extern tAST_Node *AST_NewMethodCall(tParser *Parser, tAST_Node *Object, const char *Name); -extern void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg); - -extern tAST_Node *AST_NewCodeBlock(tParser *Parser); -extern void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child); - -extern tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False); -extern tAST_Node *AST_NewLoop(tParser *Parser, const char *Tag, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code); - -extern tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value); -extern tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value); -extern tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right); -extern tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value); -extern tAST_Node *AST_NewBreakout(tParser *Parser, int Type, const char *DestTag); -extern tAST_Node *AST_NewScopeDereference(tParser *Parser, const char *Name, tAST_Node *Child); - -extern void AST_FreeNode(tAST_Node *Node); - -// exec_ast.h -extern void Object_Dereference(tSpiderValue *Object); -extern void Object_Reference(tSpiderValue *Object); -extern tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node); -extern tSpiderValue *AST_ExecuteNode_BinOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Left, tSpiderValue *Right); -extern tSpiderValue *AST_ExecuteNode_UniOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Value); -extern tSpiderValue *AST_ExecuteNode_Index(tSpiderScript *Script, tAST_Node *Node, tSpiderValue *Array, int Index, tSpiderValue *SaveValue); -extern tSpiderValue *AST_ExecuteNode_Element(tSpiderScript *Script, tAST_Node *Node, tSpiderValue *Object, const char *Element, tSpiderValue *SaveValue); - -#endif diff --git a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c deleted file mode 100644 index c45e7a51..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c +++ /dev/null @@ -1,897 +0,0 @@ -/* - * SpiderScript Library - * - * AST to Bytecode Conversion - */ -#include -#include -#include -#include -#include "common.h" -#include "ast.h" -#include "bytecode_gen.h" -#include "bytecode_ops.h" - -#define TRACE_VAR_LOOKUPS 0 -#define TRACE_TYPE_STACK 0 -#define MAX_NAMESPACE_DEPTH 10 -#define MAX_STACK_DEPTH 10 // This is for one function, so shouldn't need more - -// === IMPORTS === -extern tSpiderFunction *gpExports_First; - -// === TYPES === -typedef struct sAST_BlockInfo -{ - struct sAST_BlockInfo *Parent; - void *Handle; - const char *Tag; - - int BreakTarget; - int ContinueTarget; - - int NamespaceDepth; - const char *CurNamespaceStack[MAX_NAMESPACE_DEPTH]; - - int StackDepth; - int Stack[MAX_STACK_DEPTH]; // Stores types of stack values - - tAST_Variable *FirstVar; -} tAST_BlockInfo; - -// === PROTOTYPES === -// Node Traversal - int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue); - int BC_SaveValue(tAST_BlockInfo *Block, tAST_Node *DestNode); -// Variables - int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name); - int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode); - int BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode); -void BC_Variable_Clear(tAST_BlockInfo *Block); -// - Errors -void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...); -void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); -// - Type stack - int _StackPush(tAST_BlockInfo *Block, tAST_Node *Node, int Type); - int _StackPop(tAST_BlockInfo *Block, tAST_Node *Node, int WantedType); - -// === GLOBALS === -// int giNextBlockIdent = 1; - -// === CODE === -int SpiderScript_BytecodeScript(tSpiderScript *Script) -{ - tScript_Function *fcn; - for(fcn = Script->Functions; fcn; fcn = fcn->Next) - { - if( Bytecode_ConvertFunction(fcn) == 0 ) - return -1; - } - return 0; -} - -/** - * \brief Convert a function into bytecode - */ -tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn) -{ - tBC_Function *ret; - tAST_BlockInfo bi = {0}; - int i; - - // TODO: Return BCFcn instead? - if(Fcn->BCFcn) return Fcn->BCFcn; - - ret = Bytecode_CreateFunction(Fcn); - if(!ret) return NULL; - - bi.Handle = ret; - - // Parse arguments - for( i = 0; i < Fcn->ArgumentCount; i ++ ) - { - BC_Variable_Define(&bi, Fcn->Arguments[i].Type, Fcn->Arguments[i].Name); - } - - if( AST_ConvertNode(&bi, Fcn->ASTFcn, 0) ) - { - AST_RuntimeError(Fcn->ASTFcn, "Error in converting function"); - Bytecode_DeleteFunction(ret); - BC_Variable_Clear(&bi); - return NULL; - } - BC_Variable_Clear(&bi); - - - Bytecode_AppendConstInt(ret, 0); // TODO: NULL - Bytecode_AppendReturn(ret); - Fcn->BCFcn = ret; - - return ret; -} - -// Indepotent operation -#define CHECK_IF_NEEDED(b_warn) do { if(!bKeepValue) {\ - if(b_warn)AST_RuntimeMessage(Node, "Bytecode", "Operation without saving");\ - Bytecode_AppendDelete(Block->Handle);\ - _StackPop(Block, Node, SS_DATATYPE_UNDEF);\ -} } while(0) - -/** - * \brief Convert a node into bytecode - * \param Block Execution context - * \param Node Node to execute - */ -int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) -{ - tAST_Node *node; - int ret = 0; - int i, op = 0; - int bAddedValue = 1; // Used to tell if the value needs to be deleted - - switch(Node->Type) - { - // No Operation - case NODETYPE_NOP: - bAddedValue = 0; - break; - - // Code block - case NODETYPE_BLOCK: - Bytecode_AppendEnterContext(Block->Handle); // Create a new block - { - tAST_BlockInfo blockInfo = {0}; - blockInfo.Parent = Block; - blockInfo.Handle = Block->Handle; - // Loop over all nodes, or until the return value is set - for(node = Node->Block.FirstChild; - node; - node = node->NextSibling ) - { - ret = AST_ConvertNode(&blockInfo, node, 0); - if(ret) return ret; - if( blockInfo.StackDepth != 0 ) { - AST_RuntimeError(node, "Stack not reset at end of node"); - blockInfo.StackDepth = 0; - } - } - - BC_Variable_Clear(&blockInfo); - } - Bytecode_AppendLeaveContext(Block->Handle); // Leave this context - break; - - // Assignment - case NODETYPE_ASSIGN: - // Perform assignment operation - if( Node->Assign.Operation != NODETYPE_NOP ) - { - int t1, t2; - - ret = AST_ConvertNode(Block, Node->Assign.Dest, 1); - if(ret) return ret; - t1 = _StackPop(Block, Node, SS_DATATYPE_UNDEF); - if(t1 < 0) return -1; - - ret = AST_ConvertNode(Block, Node->Assign.Value, 1); - if(ret) return ret; - t2 = _StackPop(Block, Node, SS_DATATYPE_UNDEF); - if(t2 < 0) return -1; - - - switch(Node->Assign.Operation) - { - // General Binary Operations - case NODETYPE_ADD: op = BC_OP_ADD; break; - case NODETYPE_SUBTRACT: op = BC_OP_SUBTRACT; break; - case NODETYPE_MULTIPLY: op = BC_OP_MULTIPLY; break; - case NODETYPE_DIVIDE: op = BC_OP_DIVIDE; break; - case NODETYPE_MODULO: op = BC_OP_MODULO; break; - case NODETYPE_BWAND: op = BC_OP_BITAND; break; - case NODETYPE_BWOR: op = BC_OP_BITOR; break; - case NODETYPE_BWXOR: op = BC_OP_BITXOR; break; - case NODETYPE_BITSHIFTLEFT: op = BC_OP_BITSHIFTLEFT; break; - case NODETYPE_BITSHIFTRIGHT: op = BC_OP_BITSHIFTRIGHT; break; - case NODETYPE_BITROTATELEFT: op = BC_OP_BITROTATELEFT; break; - - default: - AST_RuntimeError(Node, "Unknown operation in ASSIGN %i", Node->Assign.Operation); - break; - } -// printf("assign, op = %i\n", op); - ret = _StackPush(Block, Node, t1); - if(ret < 0) return -1; - Bytecode_AppendBinOp(Block->Handle, op); - } - else - { - ret = AST_ConvertNode(Block, Node->Assign.Value, 1); - if(ret) return ret; - } - - if( bKeepValue ) { - ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF); - if(ret < 0) return -1; - ret = _StackPush(Block, Node, ret); - if(ret < 0) return -1; - ret = _StackPush(Block, Node, ret); - if(ret < 0) return -1; - Bytecode_AppendDuplicate(Block->Handle); - } - - ret = BC_SaveValue(Block, Node->Assign.Dest); - if(ret) return ret; - break; - - // Post increment/decrement - case NODETYPE_POSTINC: - case NODETYPE_POSTDEC: - // Save original value if requested - if(bKeepValue) { - ret = BC_Variable_GetValue(Block, Node->UniOp.Value); - if(ret) return ret; - } - - Bytecode_AppendConstInt(Block->Handle, 1); - ret = _StackPush(Block, Node, SS_DATATYPE_INTEGER); - if(ret < 0) return -1; - - ret = AST_ConvertNode(Block, Node->UniOp.Value, 1); - if(ret) return ret; - - if( Node->Type == NODETYPE_POSTDEC ) - Bytecode_AppendBinOp(Block->Handle, BC_OP_SUBTRACT); - else - Bytecode_AppendBinOp(Block->Handle, BC_OP_ADD); - - ret = _StackPop(Block, Node, SS_DATATYPE_INTEGER); // TODO: Check for objects too - if(ret < 0) return -1; - ret = BC_SaveValue(Block, Node->UniOp.Value); - if(ret) return ret; - break; - - // Function Call - case NODETYPE_METHODCALL: { - int nargs = 0; - - ret = AST_ConvertNode(Block, Node->FunctionCall.Object, 1); - if(ret) return ret; - - // Push arguments to the stack - for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) - { - ret = AST_ConvertNode(Block, node, 1); - if(ret) return ret; - nargs ++; - - // TODO: Check arguments? Need to get the types somehow - ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF); - if(ret < 0) return -1; - } - - ret = _StackPop(Block, Node, SS_DATATYPE_OBJECT); - if(ret < 0) return -1; - Bytecode_AppendMethodCall(Block->Handle, Node->FunctionCall.Name, nargs); - - ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF); - if(ret < 0) return -1; - - CHECK_IF_NEEDED(0); // Don't warn - // TODO: Implement warn_unused_ret - - } break; - case NODETYPE_FUNCTIONCALL: - case NODETYPE_CREATEOBJECT: { - int nargs = 0; - - // Get name (mangled into a single string) - int newnamelen = 0; - char *manglename; - for( i = 0; i < Block->NamespaceDepth; i ++ ) - newnamelen += strlen(Block->CurNamespaceStack[i]) + 1; - newnamelen += strlen(Node->FunctionCall.Name) + 1; -// newnamelen += 1; - - manglename = alloca(newnamelen); - newnamelen = 0; - for( i = 0; i < Block->NamespaceDepth; i ++ ) { - strcpy(manglename+newnamelen, Block->CurNamespaceStack[i]); - newnamelen += strlen(Block->CurNamespaceStack[i]) + 1; - manglename[ newnamelen - 1 ] = BC_NS_SEPARATOR; - } - strcpy(manglename + newnamelen, Node->FunctionCall.Name); - newnamelen += strlen(Node->FunctionCall.Name) + 1; -// manglename[ newnamelen ] = '\0'; // Zero length terminator - Block->NamespaceDepth = 0; - - // Push arguments to the stack - for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) - { - // TODO: Type Checking - ret = AST_ConvertNode(Block, node, 1); - if(ret) return ret; - nargs ++; - - // TODO: Check arguments? Need to get the types somehow - ret = _StackPop(Block, node, SS_DATATYPE_UNDEF); - if(ret < 0) return -1; - } - - // Call the function - if( Node->Type == NODETYPE_CREATEOBJECT ) - { - Bytecode_AppendCreateObj(Block->Handle, manglename, nargs); - } - else - { - Bytecode_AppendFunctionCall(Block->Handle, manglename, nargs); - } - - // TODO: Get return type - ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF); - if(ret < 0) return -1; - - CHECK_IF_NEEDED(0); // Don't warn - // TODO: Implement warn_unused_ret - } break; - - // Conditional - case NODETYPE_IF: { - int if_end; - ret = AST_ConvertNode(Block, Node->If.Condition, 1); - if(ret) return ret; - // TODO: Should be boolean/integer, but meh - ret = _StackPop(Block, Node->If.Condition, SS_DATATYPE_UNDEF); - if(ret < 0) return -1; - - if_end = Bytecode_AllocateLabel(Block->Handle); - - if( Node->If.False->Type != NODETYPE_NOP ) - { - int if_true = Bytecode_AllocateLabel(Block->Handle); - - Bytecode_AppendCondJump(Block->Handle, if_true); - - // False - ret = AST_ConvertNode(Block, Node->If.False, 0); - if(ret) return ret; - Bytecode_AppendJump(Block->Handle, if_end); - Bytecode_SetLabel(Block->Handle, if_true); - } - else - { - Bytecode_AppendCondJumpNot(Block->Handle, if_end); - } - - // True - ret = AST_ConvertNode(Block, Node->If.True, 0); - if(ret) return ret; - - // End - Bytecode_SetLabel(Block->Handle, if_end); - } break; - - // Loop - case NODETYPE_LOOP: { - int loop_start, loop_end, code_end; - int saved_break, saved_continue; - const char *saved_tag; - - // Initialise - ret = AST_ConvertNode(Block, Node->For.Init, 0); - if(ret) return ret; - - loop_start = Bytecode_AllocateLabel(Block->Handle); - code_end = Bytecode_AllocateLabel(Block->Handle); - loop_end = Bytecode_AllocateLabel(Block->Handle); - - saved_break = Block->BreakTarget; - saved_continue = Block->ContinueTarget; - saved_tag = Block->Tag; - Block->BreakTarget = loop_end; - Block->ContinueTarget = code_end; - Block->Tag = Node->For.Tag; - - Bytecode_SetLabel(Block->Handle, loop_start); - - // Check initial condition - if( !Node->For.bCheckAfter ) - { - ret = AST_ConvertNode(Block, Node->For.Condition, 1); - if(ret) return ret; - Bytecode_AppendUniOp(Block->Handle, BC_OP_LOGICNOT); - ret = _StackPop(Block, Node->For.Condition, SS_DATATYPE_UNDEF); // Boolean? - if(ret < 0) return -1; - Bytecode_AppendCondJump(Block->Handle, loop_end); - } - - // Code - ret = AST_ConvertNode(Block, Node->For.Code, 0); - if(ret) return ret; - - Bytecode_SetLabel(Block->Handle, code_end); - - // Increment - ret = AST_ConvertNode(Block, Node->For.Increment, 0); - if(ret) return ret; -// ret = _StackPop(Block, Node->For.Increment, SS_DATATYPE_UNDEF); // TODO: Check if needed -// if(ret < 0) return -1; - - // Tail check - if( Node->For.bCheckAfter ) - { - ret = AST_ConvertNode(Block, Node->For.Condition, 1); - if(ret) return ret; - ret = _StackPop(Block, Node->If.Condition, SS_DATATYPE_UNDEF); // Boolean? - if(ret < 0) return ret; - Bytecode_AppendCondJump(Block->Handle, loop_start); - } - else - { - Bytecode_AppendJump(Block->Handle, loop_start); - } - - Bytecode_SetLabel(Block->Handle, loop_end); - - Block->BreakTarget = saved_break; - Block->ContinueTarget = saved_continue; - Block->Tag = saved_tag; - } break; - - // Return - case NODETYPE_RETURN: - ret = AST_ConvertNode(Block, Node->UniOp.Value, 1); - if(ret) return ret; - Bytecode_AppendReturn(Block->Handle); - ret = _StackPop(Block, Node->UniOp.Value, SS_DATATYPE_UNDEF); // - if(ret < 0) return -1; - break; - - case NODETYPE_BREAK: - case NODETYPE_CONTINUE: { - tAST_BlockInfo *bi = Block; - if( Node->Variable.Name[0] ) { - while(bi && (!bi->Tag || strcmp(bi->Tag, Node->Variable.Name) != 0)) - bi = bi->Parent; - } - else { - while(bi && !bi->Tag) - bi = bi->Parent; - } - if( !bi ) return 1; - // TODO: Check if BreakTarget/ContinueTarget are valid - if( Node->Type == NODETYPE_BREAK ) - Bytecode_AppendJump(Block->Handle, bi->BreakTarget); - else - Bytecode_AppendJump(Block->Handle, bi->ContinueTarget); - } break; - - // Define a variable - case NODETYPE_DEFVAR: - ret = BC_Variable_Define(Block, Node->DefVar.DataType, Node->DefVar.Name); - if(ret) return ret; - - if( Node->DefVar.InitialValue ) - { - ret = AST_ConvertNode(Block, Node->DefVar.InitialValue, 1); - if(ret) return ret; - ret = _StackPop(Block, Node->DefVar.InitialValue, Node->DefVar.DataType); - if(ret < 0) return -1; - Bytecode_AppendSaveVar(Block->Handle, Node->DefVar.Name); - } - break; - - // Scope - case NODETYPE_SCOPE: - if( Block->NamespaceDepth == MAX_NAMESPACE_DEPTH ) { - AST_RuntimeError(Node, "Exceeded max explicit namespace depth (%i)", MAX_NAMESPACE_DEPTH); - return 2; - } - Block->CurNamespaceStack[ Block->NamespaceDepth ] = Node->Scope.Name; - Block->NamespaceDepth ++; - ret = AST_ConvertNode(Block, Node->Scope.Element, bKeepValue); - if(ret) return ret; - if( Block->NamespaceDepth != 0 ) { - AST_RuntimeError(Node, "Namespace scope used but no element at the end"); - } - bAddedValue = 0; - break; - - // Variable - case NODETYPE_VARIABLE: - ret = BC_Variable_GetValue( Block, Node ); - CHECK_IF_NEEDED(1); - if(ret) return ret; - break; - - // Element of an Object - case NODETYPE_ELEMENT: - ret = AST_ConvertNode( Block, Node->Scope.Element, 1 ); - if(ret) return ret; - - // TODO: Support elements for non-objects - ret = _StackPop(Block, Node, SS_DATATYPE_OBJECT); - if(ret < 0) return -1; - - Bytecode_AppendElement(Block->Handle, Node->Scope.Name); - - // TODO: Somehow know this at compile time? - ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF); - if(ret < 0) return -1; - CHECK_IF_NEEDED(1); - break; - - // Cast a value to another - case NODETYPE_CAST: - ret = AST_ConvertNode(Block, Node->Cast.Value, 1); - if(ret) return ret; - ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF); - if(ret < 0) return -1; - - Bytecode_AppendCast(Block->Handle, Node->Cast.DataType); - ret = _StackPush(Block, Node, Node->Cast.DataType); - if(ret < 0) return -1; - CHECK_IF_NEEDED(1); - break; - - // Index into an array - case NODETYPE_INDEX: - // - Array - ret = AST_ConvertNode(Block, Node->BinOp.Left, 1); - if(ret) return ret; - // > Type check - ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF); - if(ret < 0) return -1; - if(ret != SS_DATATYPE_ARRAY && SS_GETARRAYDEPTH(ret) == 0) { - AST_RuntimeError(Node, "Type mismatch, Expected an array, got %i", - ret); - return -2; - } - i = ret; // Hackily save the datatype - - // - Offset - ret = AST_ConvertNode(Block, Node->BinOp.Right, 1); - if(ret) return ret; - ret = _StackPop(Block, Node, SS_DATATYPE_INTEGER); - if(ret < 0) return -1; - - Bytecode_AppendIndex(Block->Handle); - - // Update the array depth - if( i != SS_DATATYPE_ARRAY ) { - i = SS_DOWNARRAY(i); // Decrease the array level - } - ret = _StackPush(Block, Node, i); - if(ret < 0) return -1; - - CHECK_IF_NEEDED(1); - break; - - // TODO: Implement runtime constants - case NODETYPE_CONSTANT: - // TODO: Scan namespace for constant name - AST_RuntimeError(Node, "TODO - Runtime Constants"); - Block->NamespaceDepth = 0; - return -1; - - // Constant Values - case NODETYPE_STRING: - Bytecode_AppendConstString(Block->Handle, Node->Constant.String.Data, Node->Constant.String.Length); - ret = _StackPush(Block, Node, SS_DATATYPE_STRING); - if(ret < 0) return -1; - CHECK_IF_NEEDED(1); - break; - case NODETYPE_INTEGER: - Bytecode_AppendConstInt(Block->Handle, Node->Constant.Integer); - ret = _StackPush(Block, Node, SS_DATATYPE_INTEGER); - if(ret < 0) return -1; - CHECK_IF_NEEDED(1); - break; - case NODETYPE_REAL: - Bytecode_AppendConstReal(Block->Handle, Node->Constant.Real); - ret = _StackPush(Block, Node, SS_DATATYPE_REAL); - if(ret < 0) return -1; - CHECK_IF_NEEDED(1); - break; - case NODETYPE_NULL: - Bytecode_AppendConstNull(Block->Handle); - ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF); - if(ret < 0) return -1; - CHECK_IF_NEEDED(1); - break; - - // --- Operations --- - // Boolean Operations - case NODETYPE_LOGICALNOT: // Logical NOT (!) - if(!op) op = BC_OP_LOGICNOT; - case NODETYPE_BWNOT: // Bitwise NOT (~) - if(!op) op = BC_OP_BITNOT; - case NODETYPE_NEGATE: // Negation (-) - if(!op) op = BC_OP_NEG; - ret = AST_ConvertNode(Block, Node->UniOp.Value, 1); - if(ret) return ret; - ret = _StackPop(Block, Node->UniOp.Value, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Undef - if(ret < 0) return -1; - - Bytecode_AppendUniOp(Block->Handle, op); - ret = _StackPush(Block, Node, ret); // TODO: Logic = _INTEGER, Neg = No change - if(ret < 0) return -1; - - CHECK_IF_NEEDED(1); - break; - - // Logic - case NODETYPE_LOGICALAND: if(!op) op = BC_OP_LOGICAND; - case NODETYPE_LOGICALOR: if(!op) op = BC_OP_LOGICOR; - case NODETYPE_LOGICALXOR: if(!op) op = BC_OP_LOGICXOR; - // Comparisons - case NODETYPE_EQUALS: if(!op) op = BC_OP_EQUALS; - case NODETYPE_NOTEQUALS: if(!op) op = BC_OP_NOTEQUALS; - case NODETYPE_LESSTHAN: if(!op) op = BC_OP_LESSTHAN; - case NODETYPE_GREATERTHAN: if(!op) op = BC_OP_GREATERTHAN; - case NODETYPE_LESSTHANEQUAL: if(!op) op = BC_OP_LESSTHANOREQUAL; - case NODETYPE_GREATERTHANEQUAL: if(!op) op = BC_OP_GREATERTHANOREQUAL; - // General Binary Operations - case NODETYPE_ADD: if(!op) op = BC_OP_ADD; - case NODETYPE_SUBTRACT: if(!op) op = BC_OP_SUBTRACT; - case NODETYPE_MULTIPLY: if(!op) op = BC_OP_MULTIPLY; - case NODETYPE_DIVIDE: if(!op) op = BC_OP_DIVIDE; - case NODETYPE_MODULO: if(!op) op = BC_OP_MODULO; - case NODETYPE_BWAND: if(!op) op = BC_OP_BITAND; - case NODETYPE_BWOR: if(!op) op = BC_OP_BITOR; - case NODETYPE_BWXOR: if(!op) op = BC_OP_BITXOR; - case NODETYPE_BITSHIFTLEFT: if(!op) op = BC_OP_BITSHIFTLEFT; - case NODETYPE_BITSHIFTRIGHT: if(!op) op = BC_OP_BITSHIFTRIGHT; - case NODETYPE_BITROTATELEFT: if(!op) op = BC_OP_BITROTATELEFT; - ret = AST_ConvertNode(Block, Node->BinOp.Left, 1); - if(ret) return ret; - ret = _StackPop(Block, Node->BinOp.Left, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Object - if(ret < 0) return -1; - - ret = AST_ConvertNode(Block, Node->BinOp.Right, 1); - if(ret) return ret; - ret = _StackPop(Block, Node->BinOp.Right, SS_DATATYPE_UNDEF); // TODO: Integer/Real/Object - if(ret < 0) return -1; - - Bytecode_AppendBinOp(Block->Handle, op); - _StackPush(Block, Node, ret); - CHECK_IF_NEEDED(1); - break; - - default: - AST_RuntimeError(Node, "BUG - SpiderScript AST_ConvertNode Unimplemented %i", Node->Type); - return -1; - } - - return 0; -} - -int BC_SaveValue(tAST_BlockInfo *Block, tAST_Node *DestNode) -{ - int ret, type; - switch(DestNode->Type) - { - // Variable, simple - case NODETYPE_VARIABLE: - ret = BC_Variable_SetValue( Block, DestNode ); - if(ret) return ret; - break; - // Array index - case NODETYPE_INDEX: - ret = AST_ConvertNode(Block, DestNode->BinOp.Left, 1); // Array - if(ret) return ret; - ret = _StackPop(Block, DestNode->BinOp.Left, SS_DATATYPE_UNDEF); - if(ret < 0) return -1; - if(ret != SS_DATATYPE_ARRAY && SS_GETARRAYDEPTH(ret) == 0) { - AST_RuntimeError(DestNode, "Type mismatch, Expected an array, got %i", - ret); - return -2; - } - type = SS_DOWNARRAY(ret); - - ret = AST_ConvertNode(Block, DestNode->BinOp.Right, 1); // Offset - if(ret) return ret; - ret = _StackPop(Block, DestNode->BinOp.Right, SS_DATATYPE_INTEGER); - if(ret < 0) return -1; - - Bytecode_AppendSetIndex( Block->Handle ); - _StackPop(Block, DestNode, type); - break; - // Object element - case NODETYPE_ELEMENT: - ret = AST_ConvertNode(Block, DestNode->Scope.Element, 1); - if(ret) return ret; - ret = _StackPop(Block, DestNode->Scope.Element, SS_DATATYPE_OBJECT); - if(ret < 0) return -1; - - Bytecode_AppendSetElement( Block->Handle, DestNode->Scope.Name ); - break; - // Anything else - default: - // TODO: Support assigning to object attributes - AST_RuntimeError(DestNode, "Assignment target is not a LValue"); - return -1; - } - return 0; -} - -/** - * \brief Define a variable - * \param Block Current block state - * \param Type Type of the variable - * \param Name Name of the variable - * \return Boolean Failure - */ -int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name) -{ - tAST_Variable *var, *prev = NULL; - - for( var = Block->FirstVar; var; prev = var, var = var->Next ) - { - if( strcmp(var->Name, Name) == 0 ) { - AST_RuntimeError(NULL, "Redefinition of variable '%s'", Name); - return -1; - } - } - - var = malloc( sizeof(tAST_Variable) + strlen(Name) + 1 ); - var->Next = NULL; - var->Type = Type; - strcpy(var->Name, Name); - - if(prev) prev->Next = var; - else Block->FirstVar = var; - - Bytecode_AppendDefineVar(Block->Handle, Name, Type); - return 0; -} - -tAST_Variable *BC_Variable_Lookup(tAST_BlockInfo *Block, tAST_Node *VarNode, int CreateType) -{ - tAST_Variable *var = NULL; - tAST_BlockInfo *bs; - - for( bs = Block; bs; bs = bs->Parent ) - { - for( var = bs->FirstVar; var; var = var->Next ) - { - if( strcmp(var->Name, VarNode->Variable.Name) == 0 ) - break; - } - if(var) break; - } - - if( !var ) - { -// if( Block->Script->Variant->bDyamicTyped && CreateType != SS_DATATYPE_UNDEF ) { -// // Define variable -// var = BC_Variable_Define(Block, CreateType, VarNode->Variable.Name, NULL); -// } -// else -// { - AST_RuntimeError(VarNode, "Variable '%s' is undefined", VarNode->Variable.Name); - return NULL; -// } - } - - #if TRACE_VAR_LOOKUPS - AST_RuntimeMessage(VarNode, "debug", "Variable lookup of '%s' %p type %i", - VarNode->Variable.Name, var, var->Type); - #endif - - return var; -} - -/** - * \brief Set the value of a variable - * \return Boolean Failure - */ -int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode) -{ - tAST_Variable *var; - - // TODO: Implicit definition type - var = BC_Variable_Lookup(Block, VarNode, SS_DATATYPE_UNDEF); - if(!var) return -1; - - // TODO: Check types - - _StackPop(Block, VarNode, var->Type); - Bytecode_AppendSaveVar(Block->Handle, VarNode->Variable.Name); - return 0; -} - -/** - * \brief Get the value of a variable - */ -int BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode) -{ - tAST_Variable *var; - - var = BC_Variable_Lookup(Block, VarNode, 0); - if(!var) return -1; - - _StackPush(Block, VarNode, var->Type); - Bytecode_AppendLoadVar(Block->Handle, VarNode->Variable.Name); - return 0; -} - -void BC_Variable_Clear(tAST_BlockInfo *Block) -{ - tAST_Variable *var; - for( var = Block->FirstVar; var; ) - { - tAST_Variable *tv = var->Next; - free( var ); - var = tv; - } - Block->FirstVar = NULL; -} - -#if 0 -void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...) -{ - va_list args; - - if(Node) { - fprintf(stderr, "%s:%i: ", Node->File, Node->Line); - } - fprintf(stderr, "%s: ", Type); - va_start(args, Format); - vfprintf(stderr, Format, args); - va_end(args); - fprintf(stderr, "\n"); -} -void AST_RuntimeError(tAST_Node *Node, const char *Format, ...) -{ - va_list args; - - if(Node) { - fprintf(stderr, "%s:%i: ", Node->File, Node->Line); - } - fprintf(stderr, "error: "); - va_start(args, Format); - vfprintf(stderr, Format, args); - va_end(args); - fprintf(stderr, "\n"); -} -#endif - -int _StackPush(tAST_BlockInfo *Block, tAST_Node *Node, int Type) -{ - if(Block->StackDepth == MAX_STACK_DEPTH - 1) { - AST_RuntimeError(Node, "BUG - Stack overflow in AST-Bytecode conversion (node=%i)", - Node->Type); - return -1; - } - - #if TRACE_TYPE_STACK - AST_RuntimeMessage(Node, "_StackPush", "%x - NT%i", Type, Node->Type); - #endif - Block->Stack[ ++Block->StackDepth ] = Type; - return Type; -} - -int _StackPop(tAST_BlockInfo *Block, tAST_Node *Node, int WantedType) -{ - if(Block->StackDepth == 0) { - AST_RuntimeError(Node, "BUG - Stack underflow in AST-Bytecode conversion (node=%i)", - Node->Type); - return -1; - } - #if TRACE_TYPE_STACK - AST_RuntimeMessage(Node, "_StackPop", "%x(?==%x) - NT%i", - Block->Stack[ Block->StackDepth ], WantedType, Node->Type); - #endif - if(WantedType != SS_DATATYPE_UNDEF && Block->Stack[ Block->StackDepth ] != SS_DATATYPE_UNDEF) - { - if( Block->Stack[ Block->StackDepth ] != WantedType ) { - AST_RuntimeError(Node, "AST-Bytecode - Type mismatch (wanted %x got %x)", - WantedType, Block->Stack[ Block->StackDepth ]); - // TODO: Message? - return -2; - } - } - return Block->Stack[Block->StackDepth--]; -} - diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode.h b/Usermode/Libraries/libspiderscript.so_src/bytecode.h deleted file mode 100644 index 6f3734d2..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SpiderScript - * - Bytecode definitions - */ -#ifndef _BYTECODE_H_ -#define _BYTECODE_H_ - -#include "bytecode_ops.h" - -#define BC_NS_SEPARATOR '@' - -typedef struct sBC_Op tBC_Op; -typedef struct sBC_Function tBC_Function; - -struct sBC_Op -{ - tBC_Op *Next; - int Operation; - char bUseInteger; // Used for serialisation - char bUseString; // Used for serialisation - - void *CacheEnt; // Used to runtime cache function calls - - union { - struct { - int Integer; - char String[]; - } StringInt; - - uint64_t Integer; - double Real; - } Content; -}; - -struct sBC_Function -{ - int LabelCount; - int LabelSpace; - tBC_Op **Labels; - - int MaxVariableCount; - // NOTE: These fields are invalid after compilation - int VariableCount; - int VariableSpace; - const char **VariableNames; - int CurContextDepth; // Used to get the real var count - - int OperationCount; - tBC_Op *Operations; - tBC_Op *OperationsEnd; -}; - -#endif diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c deleted file mode 100644 index aad172d8..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * SpiderScript Library - * by John Hodge (thePowersGang) - * - * bytecode_gen.c - * - Generate bytecode - */ -#include -#include -#include "bytecode_ops.h" -#include -#include "bytecode_gen.h" -#include -#include "bytecode.h" - -// === IMPORTS === - -// === STRUCTURES === - -// === PROTOTYPES === -tBC_Op *Bytecode_int_AllocateOp(int Operation, int ExtraBytes); - int Bytecode_int_AddVariable(tBC_Function *Handle, const char *Name); - -// === GLOBALS === - -// === CODE === -tBC_Op *Bytecode_int_AllocateOp(int Operation, int ExtraBytes) -{ - tBC_Op *ret; - - ret = malloc(sizeof(tBC_Op) + ExtraBytes); - if(!ret) return NULL; - - ret->Next = NULL; - ret->Operation = Operation; - ret->bUseInteger = 0; - ret->bUseString = (ExtraBytes > 0); - ret->CacheEnt = NULL; - - return ret; -} - -tBC_Function *Bytecode_CreateFunction(tScript_Function *Fcn) -{ - tBC_Function *ret; - int i; - - ret = malloc(sizeof(tBC_Function)); - if(!ret) return NULL; - - ret->LabelSpace = ret->LabelCount = 0; - ret->Labels = NULL; - - ret->MaxVariableCount = 0; - ret->CurContextDepth = 0; - ret->VariableCount = ret->VariableSpace = 0; - ret->VariableNames = NULL; - - ret->OperationCount = 0; - ret->Operations = NULL; - ret->OperationsEnd = (void*)&ret->Operations; - - for( i = 0; i < Fcn->ArgumentCount; i ++ ) - { - Bytecode_int_AddVariable(ret, Fcn->Arguments[i].Name); - } - - return ret; -} - -void Bytecode_DeleteFunction(tBC_Function *Fcn) -{ - tBC_Op *op; - for( op = Fcn->Operations; op; ) - { - tBC_Op *nextop = op->Next; - free(op); - op = nextop; - } - free(Fcn->VariableNames); - free(Fcn->Labels); - free(Fcn); -} - -int StringList_GetString(tStringList *List, const char *String, int Length) -{ - int strIdx = 0; - tString *ent; - for(ent = List->Head; ent; ent = ent->Next, strIdx ++) - { - if(ent->Length == Length && memcmp(ent->Data, String, Length) == 0) break; - } - if( ent ) { - ent->RefCount ++; - } - else { - ent = malloc(sizeof(tString) + Length + 1); - if(!ent) return -1; - ent->Next = NULL; - ent->Length = Length; - ent->RefCount = 1; - memcpy(ent->Data, String, Length); - ent->Data[Length] = '\0'; - - if(List->Head) - List->Tail->Next = ent; - else - List->Head = ent; - List->Tail = ent; - List->Count ++; - } - return strIdx; -} - -int Bytecode_int_Serialize(const tBC_Function *Function, void *Output, int *LabelOffsets, tStringList *Strings) -{ - tBC_Op *op; - int len = 0, idx = 0; - int i; - - void _put_byte(uint8_t byte) - { - uint8_t *buf = Output; - if(Output) buf[len] = byte; - len ++; - } - - void _put_dword(uint32_t value) - { - uint8_t *buf = Output; - if(Output) { - buf[len+0] = value & 0xFF; - buf[len+1] = value >> 8; - buf[len+2] = value >> 16; - buf[len+3] = value >> 24; - } - len += 4; - } - - void _put_index(uint32_t value) - { - if( !Output && !value ) { - len += 5; - return ; - } - if( value < 0x8000 ) { - _put_byte(value >> 8); - _put_byte(value & 0xFF); - } - else if( value < 0x400000 ) { - _put_byte( (value >> 16) | 0x80 ); - _put_byte(value >> 8); - _put_byte(value & 0xFF); - } - else { - _put_byte( 0xC0 ); - _put_byte(value >> 24); - _put_byte(value >> 16); - _put_byte(value >> 8 ); - _put_byte(value & 0xFF); - } - } - - void _put_qword(uint64_t value) - { - if( value < 0x80 ) { // 7 bits into 1 byte - _put_byte(value); - } - else if( !(value >> (8+6)) ) { // 14 bits packed into 2 bytes - _put_byte( 0x80 | ((value >> 8) & 0x3F) ); - _put_byte( value & 0xFF ); - } - else if( !(value >> (32+5)) ) { // 37 bits into 5 bytes - _put_byte( 0xC0 | ((value >> 32) & 0x1F) ); - _put_dword(value & 0xFFFFFFFF); - } - else { - _put_byte( 0xE0 ); // 64 (actually 68) bits into 9 bytes - _put_dword(value & 0xFFFFFFFF); - _put_dword(value >> 32); - } - } - - void _put_double(double value) - { - // TODO: Machine agnostic - if(Output) { - *(double*)( (char*)Output + len ) = value; - } - len += sizeof(double); - } - - void _put_string(const char *str, int len) - { - int strIdx = 0; - if( Output ) { - strIdx = StringList_GetString(Strings, str, len); - } - - // TODO: Relocations - _put_index(strIdx); - } - - for( op = Function->Operations; op; op = op->Next, idx ++ ) - { - // If first run, convert labels into byte offsets - if( !Output ) - { - for( i = 0; i < Function->LabelCount; i ++ ) - { - if(LabelOffsets[i]) continue; - if(op != Function->Labels[i]) continue; - - LabelOffsets[i] = len; - } - } - - _put_byte(op->Operation); - switch(op->Operation) - { - // Relocate jumps (the value only matters if `Output` is non-NULL) - case BC_OP_JUMP: - case BC_OP_JUMPIF: - case BC_OP_JUMPIFNOT: - // TODO: Relocations? - _put_index( LabelOffsets[op->Content.StringInt.Integer] ); - break; - // Special case for inline values - case BC_OP_LOADINT: - _put_qword(op->Content.Integer); - break; - case BC_OP_LOADREAL: - _put_double(op->Content.Real); - break; - case BC_OP_LOADSTR: - _put_string(op->Content.StringInt.String, op->Content.StringInt.Integer); - break; - // Everthing else just gets handled nicely - default: - if( op->bUseString ) - _put_string(op->Content.StringInt.String, strlen(op->Content.StringInt.String)); - if( op->bUseInteger ) - _put_index(op->Content.StringInt.Integer); - break; - } - } - - return len; -} - -char *Bytecode_SerialiseFunction(const tBC_Function *Function, int *Length, tStringList *Strings) -{ - int len; - int *label_offsets; - char *code; - - label_offsets = calloc( sizeof(int), Function->LabelCount ); - if(!label_offsets) return NULL; - - len = Bytecode_int_Serialize(Function, NULL, label_offsets, Strings); - - code = malloc(len); - - // Update length to the correct length (may decrease due to encoding) - len = Bytecode_int_Serialize(Function, code, label_offsets, Strings); - - free(label_offsets); - - *Length = len; - - return code; -} - -int Bytecode_AllocateLabel(tBC_Function *Handle) -{ - int ret; - - if( Handle->LabelCount == Handle->LabelSpace ) { - void *tmp; - Handle->LabelSpace += 20; // TODO: Don't hardcode increment - tmp = realloc(Handle->Labels, Handle->LabelSpace * sizeof(Handle->Labels[0])); - if( !tmp ) { - Handle->LabelSpace -= 20; - return -1; - } - Handle->Labels = tmp; - } - ret = Handle->LabelCount ++; - Handle->Labels[ret] = 0; - return ret; -} - -void Bytecode_SetLabel(tBC_Function *Handle, int Label) -{ - if(Label < 0) return ; - - if(Label >= Handle->LabelCount) return ; - - Handle->Labels[Label] = Handle->OperationsEnd; - return ; -} - -void Bytecode_int_AppendOp(tBC_Function *Fcn, tBC_Op *Op) -{ - Op->Next = NULL; - if( Fcn->Operations ) - Fcn->OperationsEnd->Next = Op; - else - Fcn->Operations = Op; - Fcn->OperationsEnd = Op; -} - -int Bytecode_int_AddVariable(tBC_Function *Handle, const char *Name) -{ - if(Handle->VariableCount == Handle->VariableSpace) { - void *tmp; - Handle->VariableSpace += 10; - tmp = realloc(Handle->VariableNames, Handle->VariableSpace * sizeof(Handle->VariableNames[0])); - if(!tmp) return -1; // TODO: Error - Handle->VariableNames = tmp; - } - Handle->VariableNames[Handle->VariableCount] = Name; - Handle->VariableCount ++; - // Get max count (used when executing to get the frame size) - if(Handle->VariableCount - Handle->CurContextDepth >= Handle->MaxVariableCount) - Handle->MaxVariableCount = Handle->VariableCount - Handle->CurContextDepth; -// printf("_AddVariable: %s given %i\n", Name, Handle->VariableCount - Handle->CurContextDepth - 1); - return Handle->VariableCount - Handle->CurContextDepth - 1; -} - -int Bytecode_int_GetVarIndex(tBC_Function *Handle, const char *Name) -{ - int i, context_depth = Handle->CurContextDepth; - // Get the start of this context - for( i = Handle->VariableCount; i --; ) - { - if( !Handle->VariableNames[i] ) { - context_depth --; - continue ; - } - if( strcmp(Name, Handle->VariableNames[i]) == 0 ) - return i - context_depth; - } - return -1; -} - -#define DEF_BC_NONE(_op) { \ - tBC_Op *op = Bytecode_int_AllocateOp(_op, 0); \ - op->Content.Integer = 0; \ - op->bUseInteger = 0; \ - Bytecode_int_AppendOp(Handle, op);\ -} - -#define DEF_BC_INT(_op, _int) {\ - tBC_Op *op = Bytecode_int_AllocateOp(_op, 0);\ - op->Content.StringInt.Integer = _int;\ - op->bUseInteger = 1;\ - op->bUseString = 0;\ - Bytecode_int_AppendOp(Handle, op);\ -} - -#define DEF_BC_STRINT(_op, _str, _int) { \ - tBC_Op *op = Bytecode_int_AllocateOp(_op, strlen(_str));\ - op->Content.StringInt.Integer = _int;\ - strcpy(op->Content.StringInt.String, _str);\ - op->bUseInteger = 1;\ - op->bUseString = 1;\ - Bytecode_int_AppendOp(Handle, op);\ -} -#define DEF_BC_STR(_op, _str) {\ - tBC_Op *op = Bytecode_int_AllocateOp(_op, strlen(_str));\ - strcpy(op->Content.StringInt.String, _str);\ - op->bUseInteger = 0;\ - Bytecode_int_AppendOp(Handle, op);\ -} - -// --- Flow Control -void Bytecode_AppendJump(tBC_Function *Handle, int Label) - DEF_BC_INT(BC_OP_JUMP, Label) -void Bytecode_AppendCondJump(tBC_Function *Handle, int Label) - DEF_BC_INT(BC_OP_JUMPIF, Label) -void Bytecode_AppendCondJumpNot(tBC_Function *Handle, int Label) - DEF_BC_INT(BC_OP_JUMPIFNOT, Label) -void Bytecode_AppendReturn(tBC_Function *Handle) - DEF_BC_NONE(BC_OP_RETURN); - -// --- Variables -void Bytecode_AppendLoadVar(tBC_Function *Handle, const char *Name) - DEF_BC_INT(BC_OP_LOADVAR, Bytecode_int_GetVarIndex(Handle, Name)) -// DEF_BC_STR(BC_OP_LOADVAR, Name) -void Bytecode_AppendSaveVar(tBC_Function *Handle, const char *Name) // (Obj->)?var = - DEF_BC_INT(BC_OP_SAVEVAR, Bytecode_int_GetVarIndex(Handle, Name)) -// DEF_BC_STR(BC_OP_SAVEVAR, Name) - -// --- Constants -void Bytecode_AppendConstInt(tBC_Function *Handle, uint64_t Value) -{ - tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADINT, 0); - op->Content.Integer = Value; - Bytecode_int_AppendOp(Handle, op); -} -void Bytecode_AppendConstReal(tBC_Function *Handle, double Value) -{ - tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADREAL, 0); - op->Content.Real = Value; - Bytecode_int_AppendOp(Handle, op); -} -void Bytecode_AppendConstString(tBC_Function *Handle, const void *Data, size_t Length) -{ - tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADSTR, Length+1); - op->Content.StringInt.Integer = Length; - memcpy(op->Content.StringInt.String, Data, Length); - op->Content.StringInt.String[Length] = 0; - Bytecode_int_AppendOp(Handle, op); -} -void Bytecode_AppendConstNull(tBC_Function *Handle) - DEF_BC_NONE(BC_OP_LOADNULL) - -// --- Indexing / Scoping -void Bytecode_AppendElement(tBC_Function *Handle, const char *Name) - DEF_BC_STR(BC_OP_ELEMENT, Name) -void Bytecode_AppendSetElement(tBC_Function *Handle, const char *Name) - DEF_BC_STR(BC_OP_SETELEMENT, Name) -void Bytecode_AppendIndex(tBC_Function *Handle) - DEF_BC_NONE(BC_OP_INDEX) -void Bytecode_AppendSetIndex(tBC_Function *Handle) - DEF_BC_NONE(BC_OP_SETINDEX); - -void Bytecode_AppendCreateObj(tBC_Function *Handle, const char *Name, int ArgumentCount) - DEF_BC_STRINT(BC_OP_CREATEOBJ, Name, ArgumentCount) -void Bytecode_AppendMethodCall(tBC_Function *Handle, const char *Name, int ArgumentCount) - DEF_BC_STRINT(BC_OP_CALLMETHOD, Name, ArgumentCount) -void Bytecode_AppendFunctionCall(tBC_Function *Handle, const char *Name, int ArgumentCount) - DEF_BC_STRINT(BC_OP_CALLFUNCTION, Name, ArgumentCount) - -void Bytecode_AppendBinOp(tBC_Function *Handle, int Operation) - DEF_BC_NONE(Operation) -void Bytecode_AppendUniOp(tBC_Function *Handle, int Operation) - DEF_BC_NONE(Operation) -void Bytecode_AppendCast(tBC_Function *Handle, int Type) - DEF_BC_INT(BC_OP_CAST, Type) -void Bytecode_AppendDuplicate(tBC_Function *Handle) - DEF_BC_NONE(BC_OP_DUPSTACK); -void Bytecode_AppendDelete(tBC_Function *Handle) - DEF_BC_NONE(BC_OP_DELSTACK); - -// Does some bookeeping to allocate variable slots at compile time -void Bytecode_AppendEnterContext(tBC_Function *Handle) -{ - Handle->CurContextDepth ++; - Bytecode_int_AddVariable(Handle, NULL); // NULL to record the extent of this - - DEF_BC_NONE(BC_OP_ENTERCONTEXT) -} -void Bytecode_AppendLeaveContext(tBC_Function *Handle) -{ - int i; - for( i = Handle->VariableCount; i --; ) - { - if( Handle->VariableNames[i] == NULL ) break; - } - Handle->CurContextDepth --; - Handle->VariableCount = i; - - DEF_BC_NONE(BC_OP_LEAVECONTEXT); -} -//void Bytecode_AppendImportNamespace(tBC_Function *Handle, const char *Name); -// DEF_BC_STRINT(BC_OP_IMPORTNS, Name, 0) -void Bytecode_AppendDefineVar(tBC_Function *Handle, const char *Name, int Type) -{ - int i; - #if 1 - // Get the start of this context - for( i = Handle->VariableCount; i --; ) - { - if( Handle->VariableNames[i] == NULL ) break; - } - // Check for duplicate allocation - for( i ++; i < Handle->VariableCount; i ++ ) - { - if( strcmp(Name, Handle->VariableNames[i]) == 0 ) - return ; - } - #endif - - i = Bytecode_int_AddVariable(Handle, Name); -// printf("Variable %s given slot %i\n", Name, i); - - DEF_BC_STRINT(BC_OP_DEFINEVAR, Name, (Type&0xFFFF) | (i << 16)) -} diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h deleted file mode 100644 index 71c5af1d..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * SpiderScript Library - * - By John Hodge (thePowersGang) - * - * bytecode_gen.h - * - Bytecode Generation header - */ -#ifndef _BYTECODE_GEN_H_ -#define _BYTECODE_GEN_H_ - -#include "common.h" -#include "ast.h" -#include "bytecode.h" - -typedef struct sStringList tStringList; -typedef struct sString tString; - -struct sString -{ - tString *Next; - int Length; - int RefCount; - char Data[]; -}; - -struct sStringList -{ - tString *Head; - tString *Tail; - int Count; -}; - - -extern int Bytecode_ConvertScript(tSpiderScript *Script, const char *DestFile); -extern tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn); -extern tBC_Function *Bytecode_NewBlankFunction(void); -extern void Bytecode_DeleteFunction(tBC_Function *Fcn); - -extern char *Bytecode_SerialiseFunction(const tBC_Function *Function, int *Length, tStringList *Strings); -extern int StringList_GetString(tStringList *List, const char *String, int Length); -extern tBC_Function *Bytecode_CreateFunction(tScript_Function *Fcn); - -extern int Bytecode_AllocateLabel(tBC_Function *Handle); -extern void Bytecode_SetLabel(tBC_Function *Handle, int Label); -// Bytecode adding -// - Flow Control -extern void Bytecode_AppendJump(tBC_Function *Handle, int Label); -extern void Bytecode_AppendCondJump(tBC_Function *Handle, int Label); -extern void Bytecode_AppendCondJumpNot(tBC_Function *Handle, int Label); -extern void Bytecode_AppendReturn(tBC_Function *Handle); -// - Operation Stack -// > Load/Store -extern void Bytecode_AppendLoadVar(tBC_Function *Handle, const char *Name); -extern void Bytecode_AppendSaveVar(tBC_Function *Handle, const char *Name); // (Obj->)?var = -extern void Bytecode_AppendConstInt(tBC_Function *Handle, uint64_t Value); -extern void Bytecode_AppendConstReal(tBC_Function *Handle, double Value); -extern void Bytecode_AppendConstString(tBC_Function *Handle, const void *Data, size_t Length); -extern void Bytecode_AppendConstNull(tBC_Function *Handle); -// > Scoping -extern void Bytecode_AppendElement(tBC_Function *Handle, const char *Name); // Obj->SubObj -extern void Bytecode_AppendSetElement(tBC_Function *Handle, const char *Name); // Set an object member -extern void Bytecode_AppendIndex(tBC_Function *Handle); // Index into an array -extern void Bytecode_AppendSetIndex(tBC_Function *Handle); // Write an array element -// > Function Calls -extern void Bytecode_AppendCreateObj(tBC_Function *Handle, const char *Name, int ArgumentCount); -extern void Bytecode_AppendMethodCall(tBC_Function *Handle, const char *Name, int ArgumentCount); -extern void Bytecode_AppendFunctionCall(tBC_Function *Handle, const char *Name, int ArgumentCount); -// > Manipulation -extern void Bytecode_AppendBinOp(tBC_Function *Handle, int Operation); -extern void Bytecode_AppendUniOp(tBC_Function *Handle, int Operation); -extern void Bytecode_AppendCast(tBC_Function *Handlde, int Type); -extern void Bytecode_AppendDuplicate(tBC_Function *Handlde); -extern void Bytecode_AppendDelete(tBC_Function *Handle); -// - Context -// TODO: Are contexts needed? Should variables be allocated like labels? -extern void Bytecode_AppendEnterContext(tBC_Function *Handle); -extern void Bytecode_AppendLeaveContext(tBC_Function *Handle); -//extern void Bytecode_AppendImportNamespace(tBC_Function *Handle, const char *Name); -extern void Bytecode_AppendDefineVar(tBC_Function *Handle, const char *Name, int Type); - -#endif - diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c b/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c deleted file mode 100644 index 3c0347bd..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * SpiderScript Library - * by John Hodge (thePowersGang) - * - * bytecode_makefile.c - * - Generate a bytecode file - */ -#include -#include "ast.h" -#include "bytecode_gen.h" -#include -#include - -// === IMPORTS === - -// === PROTOTYPES === - -// === GLOBALS === - -// === CODE === -int SpiderScript_SaveBytecode(tSpiderScript *Script, const char *DestFile) -{ - tStringList strings = {0}; - tScript_Function *fcn; - FILE *fp; - int fcn_hdr_offset = 0; - int fcn_count = 0; - int strtab_ofs; - int i; - - void _put8(uint8_t val) - { - fwrite(&val, 1, 1, fp); - } - void _put32(uint32_t val) - { - _put8(val & 0xFF); - _put8(val >> 8); - _put8(val >> 16); - _put8(val >> 24); - } - - fp = fopen(DestFile, "wb"); - if(!fp) return 1; - // Create header - fwrite("SSBC\r\n\xBC\x55", 8, 1, fp); - _put32(0); // Function count, to be filled - _put32(0); // String count - _put32(0); // String table offset - // TODO: Variant info - - fcn_hdr_offset = ftell(fp); - - // Create function descriptors - for(fcn = Script->Functions; fcn; fcn = fcn->Next, fcn_count ++) - { - _put32( StringList_GetString(&strings, fcn->Name, strlen(fcn->Name)) ); - _put32( 0 ); // Code offset - // TODO: Namespace - _put8( fcn->ReturnType ); - - if(fcn->ArgumentCount > 255) { - // ERROR: Too many args - return 2; - } - _put8( fcn->ArgumentCount ); - - // Argument types? - for( i = 0; i < fcn->ArgumentCount; i ++ ) - { - _put32( StringList_GetString(&strings, fcn->Arguments[i].Name, strlen(fcn->Arguments[i].Name)) ); - _put8( fcn->Arguments[i].Type ); - } - } - - // Put function code in - for(fcn = Script->Functions; fcn; fcn = fcn->Next) - { - char *code; - int len, code_pos; - - // Fix header - code_pos = ftell(fp); - fseek(fp, SEEK_SET, fcn_hdr_offset + 4); - _put32( code_pos ); - fseek(fp, SEEK_SET, code_pos ); - - fcn_hdr_offset += 4+4+1+1+(4+1)*fcn->ArgumentCount; - - // Write code - if( !fcn->BCFcn ) - Bytecode_ConvertFunction(fcn); - if( !fcn->BCFcn ) - { - fclose(fp); - return 1; - } - code = Bytecode_SerialiseFunction(fcn->BCFcn, &len, &strings); - fwrite(code, len, 1, fp); - free(code); - } - - // String table - strtab_ofs = ftell(fp); - { - int string_offset = strtab_ofs + (4+4)*strings.Count; - tString *str; - // Array - for(str = strings.Head; str; str = str->Next) - { - _put32(str->Length); - _put32(string_offset); - string_offset += str->Length + 1; - } - // Data - for(str = strings.Head; str;) - { - tString *nextstr = str->Next; - fwrite(str->Data, str->Length, 1, fp); - _put8(0); // NULL separator - free(str); - str = nextstr; - } - strings.Head = NULL; - strings.Tail = NULL; - } - - // Fix header - fseek(fp, 8, SEEK_SET); - _put32(fcn_count); - _put32(strings.Count); - _put32(strtab_ofs); - - fclose(fp); - - return 0; -} - diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h b/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h deleted file mode 100644 index 4db753ec..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - */ -#ifndef _BYTECODE_OPS_H_ -#define _BYTECODE_OPS_H_ - -enum eBC_Ops -{ - BC_OP_NOP, - - BC_OP_JUMP, - BC_OP_JUMPIF, - BC_OP_JUMPIFNOT, - - BC_OP_RETURN, // = 4 - BC_OP_CALLFUNCTION, - BC_OP_CALLMETHOD, - BC_OP_CREATEOBJ, - - BC_OP_LOADVAR, // = 8 - BC_OP_SAVEVAR, - - BC_OP_LOADINT, // = 10 - BC_OP_LOADREAL, - BC_OP_LOADSTR, - BC_OP_LOADNULL, - - BC_OP_DUPSTACK, // = 14 - BC_OP_DELSTACK, // - BC_OP_CAST, // - - BC_OP_ELEMENT, // = 17 - BC_OP_SETELEMENT, - BC_OP_INDEX, - BC_OP_SETINDEX, - - BC_OP_ENTERCONTEXT, // = 21 - BC_OP_LEAVECONTEXT, - BC_OP_DEFINEVAR, - - // Operations - BC_OP_LOGICNOT, // 24 - BC_OP_LOGICAND, - BC_OP_LOGICOR, - BC_OP_LOGICXOR, - - BC_OP_BITNOT, // 28 - BC_OP_BITAND, - BC_OP_BITOR, - BC_OP_BITXOR, - - BC_OP_BITSHIFTLEFT, // 32 - BC_OP_BITSHIFTRIGHT, - BC_OP_BITROTATELEFT, - - BC_OP_NEG, // 35 - BC_OP_ADD, - BC_OP_SUBTRACT, - BC_OP_MULTIPLY, - BC_OP_DIVIDE, - BC_OP_MODULO, - - BC_OP_EQUALS, // 41 - BC_OP_NOTEQUALS, - BC_OP_LESSTHAN, - BC_OP_LESSTHANOREQUAL, - BC_OP_GREATERTHAN, - BC_OP_GREATERTHANOREQUAL -}; - -#endif diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_optimise.c b/Usermode/Libraries/libspiderscript.so_src/bytecode_optimise.c deleted file mode 100644 index 3da6aa5a..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_optimise.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * SpiderScript Library - * by John Hodge (thePowersGang) - * - * bytecode_gen.c - * - Generate bytecode - */ -#include -#include "bytecode_ops.h" - -// Patterns: -// TODO: Figure out what optimisations can be done - -int Bytecode_OptimizeFunction(tBC_Function *Function) -{ - for( op = Function->Operations; op; op = op->Next, idx ++ ) - { - } -} diff --git a/Usermode/Libraries/libspiderscript.so_src/common.h b/Usermode/Libraries/libspiderscript.so_src/common.h deleted file mode 100644 index f2bb3e63..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/common.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SpiderScript - * - By John Hodge (thePowersGang) - */ -#ifndef _COMMON_H_ -#define _COMMON_H_ - -#include - -typedef struct sScript_Function tScript_Function; -typedef struct sScript_Arg tScript_Arg; - -struct sSpiderScript -{ - tSpiderVariant *Variant; - tScript_Function *Functions; - tScript_Function *LastFunction; - char *CurNamespace; //!< Current namespace prefix (NULL = Root) - No trailing . -}; - -struct sScript_Arg -{ - int Type; - char *Name; -}; - -struct sScript_Function -{ - tScript_Function *Next; - // char *Namespace; - char *Name; - - int ReturnType; - - struct sAST_Node *ASTFcn; - struct sBC_Function *BCFcn; - - int ArgumentCount; - tScript_Arg Arguments[]; -}; - -#endif - diff --git a/Usermode/Libraries/libspiderscript.so_src/exec.c b/Usermode/Libraries/libspiderscript.so_src/exec.c deleted file mode 100644 index 5822d9d5..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/exec.c +++ /dev/null @@ -1,432 +0,0 @@ -/* -* SpiderScript Library -* by John Hodge (thePowersGang) -* -* bytecode_makefile.c -* - Generate a bytecode file -*/ -#include -#include "common.h" -#include "ast.h" -#include -#include -#include - -#define BC_NS_SEPARATOR '@' - -// === IMPORTS === -extern tSpiderFunction *gpExports_First; -extern tSpiderNamespace gExportNamespaceRoot; -extern tSpiderValue *AST_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Arguments); -extern tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args); - -// === PROTOTYPES === -void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...); -void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); - -// === CODE === -void *SpiderScript_int_GetNamespace(tSpiderScript *Script, tSpiderNamespace *RootNamespace, - const char *BasePath, const char *ItemPath, - const char **ItemName - ) -{ - int len; - const char *name; - const char *end; - int bTriedBase; - - tSpiderNamespace *lastns, *ns; - - // Prepend the base namespace - if( BasePath ) { - name = BasePath; - bTriedBase = 0; - } - else { - bTriedBase = 1; - name = ItemPath; - } - - // Scan - lastns = RootNamespace; - do { - end = strchr(name, BC_NS_SEPARATOR); - if(!end) { - if( !bTriedBase ) - len = strlen(name); - else - break; - } - else { - len = end - name; - } - - // Check for this level - for( ns = lastns->FirstChild; ns; ns = ns->Next ) - { -// printf("%p %.*s == %s\n", lastns, len, name, ns->Name); - if( strncmp(name, ns->Name, len) == 0 && ns->Name[len] == 0 ) - break ; - } - - if(!ns) return NULL; - - if(!end && !bTriedBase) { - end = ItemPath - 1; // -1 to counter (name = end + 1) - bTriedBase = 1; - } - - lastns = ns; - name = end + 1; - } while( end ); - - *ItemName = name; - - return lastns; -} - -tSpiderFunction *SpiderScript_int_GetNativeFunction(tSpiderScript *Script, tSpiderNamespace *RootNamespace, - const char *BasePath, const char *FunctionPath) -{ - tSpiderNamespace *ns; - const char *name; - tSpiderFunction *fcn; - - ns = SpiderScript_int_GetNamespace(Script, RootNamespace, BasePath, FunctionPath, &name); - if(!ns) return NULL; - - for( fcn = ns->Functions; fcn; fcn = fcn->Next ) - { - if( strcmp(name, fcn->Name) == 0 ) - return fcn; - } - - return NULL; -} - -tSpiderObjectDef *SpiderScript_int_GetNativeClass(tSpiderScript *Script, tSpiderNamespace *RootNamespace, - const char *BasePath, const char *ClassPath - ) -{ - tSpiderNamespace *ns; - const char *name; - tSpiderObjectDef *class; - - ns = SpiderScript_int_GetNamespace(Script, RootNamespace, BasePath, ClassPath, &name); - if(!ns) return NULL; - - for( class = ns->Classes; class; class = class->Next ) - { - if( strcmp(name, class->Name) == 0 ) - return class; - } - - return NULL; -} - -/** - * \brief Execute a script function - * \param Script Script context to execute in - * \param Namespace Namespace to search for the function - * \param Function Function name to execute - * \param NArguments Number of arguments to pass - * \param Arguments Arguments passed - */ -tSpiderValue *SpiderScript_ExecuteFunction(tSpiderScript *Script, - const char *Function, - const char *DefaultNamespaces[], - int NArguments, tSpiderValue **Arguments, - void **FunctionIdent - ) -{ - tSpiderValue *ret = ERRPTR; - tSpiderFunction *fcn = NULL; - tScript_Function *sfcn; - int i; - - if( FunctionIdent && *FunctionIdent ) { - if( *(intptr_t*)FunctionIdent & 1 ) { - sfcn = (void*)( *(intptr_t*)FunctionIdent & ~1 ); - goto _exec_sfcn; - } - else { - fcn = *FunctionIdent; - goto _exec_fcn; - } - } - - // Scan list, Last item should always be NULL, so abuse that to check non-prefixed - for( i = 0; i == 0 || (DefaultNamespaces && DefaultNamespaces[i-1]); i ++ ) - { - const char *ns = DefaultNamespaces ? DefaultNamespaces[i] : NULL; - fcn = SpiderScript_int_GetNativeFunction(Script, &Script->Variant->RootNamespace, ns, Function); - if( fcn ) break; - - fcn = SpiderScript_int_GetNativeFunction(Script, &gExportNamespaceRoot, ns, Function); - if( fcn ) break; - - // TODO: Script namespacing - } - - // Search the variant's global exports - if( !fcn ) - { - for( fcn = Script->Variant->Functions; fcn; fcn = fcn->Next ) - { - if( strcmp( fcn->Name, Function ) == 0 ) - break; - } - } - - // Fourth: Search language exports - if( !fcn ) - { - for( fcn = gpExports_First; fcn; fcn = fcn->Next ) - { - if( strcmp( fcn->Name, Function ) == 0 ) - break; - } - } - - // Find the function in the script? - // TODO: Script namespacing - if( !fcn && strchr(Function, BC_NS_SEPARATOR) == NULL ) - { - for( sfcn = Script->Functions; sfcn; sfcn = sfcn->Next ) - { - if( strcmp(sfcn->Name, Function) == 0 ) - break; - } - _exec_sfcn: - // Execute! - if(sfcn) - { - if( sfcn->BCFcn ) - ret = Bytecode_ExecuteFunction(Script, sfcn, NArguments, Arguments); - else - ret = AST_ExecuteFunction(Script, sfcn, NArguments, Arguments); - - if( FunctionIdent ) { - *FunctionIdent = sfcn; - // Abuses alignment requirements on almost all platforms - *(intptr_t*)FunctionIdent |= 1; - } - - return ret; - } - } - -_exec_fcn: - if(fcn) - { - // Execute! - // TODO: Type Checking - ret = fcn->Handler( Script, NArguments, Arguments ); - - if( FunctionIdent ) - *FunctionIdent = fcn; - - return ret; - } - else - { - fprintf(stderr, "Undefined reference to function '%s'\n", Function); - return ERRPTR; - } -} - -/** - * \brief Execute an object method function - * \param Script Script context to execute in - * \param Object Object in which to find the method - * \param MethodName Name of method to call - * \param NArguments Number of arguments to pass - * \param Arguments Arguments passed - */ -tSpiderValue *SpiderScript_ExecuteMethod(tSpiderScript *Script, - tSpiderObject *Object, const char *MethodName, - int NArguments, tSpiderValue **Arguments) -{ - tSpiderFunction *fcn; - tSpiderValue this; - tSpiderValue *newargs[NArguments+1]; - int i; - - // TODO: Support program defined objects - - // Search for the function - for( fcn = Object->Type->Methods; fcn; fcn = fcn->Next ) - { - if( strcmp(fcn->Name, MethodName) == 0 ) - break; - } - // Error - if( !fcn ) - { - AST_RuntimeError(NULL, "Class '%s' does not have a method '%s'", - Object->Type->Name, MethodName); - return ERRPTR; - } - - // Create the "this" argument - this.Type = SS_DATATYPE_OBJECT; - this.ReferenceCount = 1; - this.Object = Object; - newargs[0] = &this; - memcpy(&newargs[1], Arguments, NArguments*sizeof(tSpiderValue*)); - - // Check the type of the arguments - for( i = 0; fcn->ArgTypes[i]; i ++ ) - { - if( i >= NArguments ) { - for( ; fcn->ArgTypes[i]; i ++ ) ; - AST_RuntimeError(NULL, "Argument count mismatch (%i passed, %i expected)", - NArguments, i); - return ERRPTR; - } - if( Arguments[i] && Arguments[i]->Type != fcn->ArgTypes[i] ) - { - AST_RuntimeError(NULL, "Argument type mismatch (%i, expected %i)", - Arguments[i]->Type, fcn->ArgTypes[i]); - return ERRPTR; - } - } - - // Call handler - return fcn->Handler(Script, NArguments+1, newargs); -} - -/** - * \brief Execute a script function - * \param Script Script context to execute in - * \param Function Function name to execute - * \param NArguments Number of arguments to pass - * \param Arguments Arguments passed - */ -tSpiderValue *SpiderScript_CreateObject(tSpiderScript *Script, - const char *ClassPath, const char *DefaultNamespaces[], - int NArguments, tSpiderValue **Arguments) -{ - tSpiderValue *ret = ERRPTR; - tSpiderObjectDef *class; - int i; - - // Scan list, Last item should always be NULL, so abuse that to check non-prefixed - for( i = 0; i == 0 || DefaultNamespaces[i-1]; i ++ ) - { - const char *ns = DefaultNamespaces[i]; - class = SpiderScript_int_GetNativeClass(Script, &Script->Variant->RootNamespace, ns, ClassPath); - if( class ) break; - - class = SpiderScript_int_GetNativeClass(Script, &gExportNamespaceRoot, ns, ClassPath); - if( class ) break; - - // TODO: Language defined classes - } - - // First: Find the function in the script - // TODO: Implement script-defined classes - #if 0 - { - tAST_Function *astClass; - for( astClass = Script->Script->Classes; astClass; astClass = astClass->Next ) - { - if( strcmp(astClass->Name, ClassName) == 0 ) - break; - } - // Execute! - if(astClass) - { - tAST_BlockState bs; - tAST_Node *arg; - int i = 0; - - // Build a block State - bs.FirstVar = NULL; - bs.RetVal = NULL; - bs.Parent = NULL; - bs.BaseNamespace = &Script->Variant->RootNamespace; - bs.CurNamespace = NULL; - bs.Script = Script; - bs.Ident = giNextBlockIdent ++; - - for( arg = astFcn->Arguments; arg; arg = arg->NextSibling, i++ ) - { - if( i >= NArguments ) break; // TODO: Return gracefully - // TODO: Type checks - Variable_Define(&bs, - arg->DefVar.DataType, arg->DefVar.Name, - Arguments[i]); - } - - // Execute function - ret = AST_ExecuteNode(&bs, astFcn->Code); - if( ret != ERRPTR ) - { - SpiderScript_DereferenceValue(ret); // Dereference output of last block statement - ret = bs.RetVal; // Set to return value of block - } - bFound = 1; - - while(bs.FirstVar) - { - tAST_Variable *nextVar = bs.FirstVar->Next; - Variable_Destroy( bs.FirstVar ); - bs.FirstVar = nextVar; - } - } - } - #endif - - // Execute! - if(class) - { - tSpiderObject *obj; - // TODO: Type Checking - - // Call constructor - obj = class->Constructor( NArguments, Arguments ); - if( obj == NULL || obj == ERRPTR ) - return (void *)obj; - - // Creatue return object - ret = malloc( sizeof(tSpiderValue) ); - ret->Type = SS_DATATYPE_OBJECT; - ret->ReferenceCount = 1; - ret->Object = obj; - - return ret; - } - else // Not found? - { - fprintf(stderr, "Undefined reference to class '%s'\n", ClassPath); - return ERRPTR; - } -} - -void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...) -{ - va_list args; - - if(Node) { - fprintf(stderr, "%s:%i: ", Node->File, Node->Line); - } - fprintf(stderr, "%s: ", Type); - va_start(args, Format); - vfprintf(stderr, Format, args); - va_end(args); - fprintf(stderr, "\n"); -} -void AST_RuntimeError(tAST_Node *Node, const char *Format, ...) -{ - va_list args; - - if(Node) { - fprintf(stderr, "%s:%i: ", Node->File, Node->Line); - } - fprintf(stderr, "error: "); - va_start(args, Format); - vfprintf(stderr, Format, args); - va_end(args); - fprintf(stderr, "\n"); -} diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c deleted file mode 100644 index a9970ee0..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c +++ /dev/null @@ -1,1146 +0,0 @@ -/* - * SpiderScript Library - * - * AST Execution - */ -#include -#include -#include -#include -#include "common.h" -#include "ast.h" - -#define USE_AST_EXEC 1 -#define TRACE_VAR_LOOKUPS 0 -#define TRACE_NODE_RETURNS 0 - -// === IMPORTS === - -// === PROTOTYPES === -// - Node Execution -tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node); -tSpiderValue *AST_ExecuteNode_BinOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Left, tSpiderValue *Right); -tSpiderValue *AST_ExecuteNode_UniOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Value); -tSpiderValue *AST_ExecuteNode_Index(tSpiderScript *Script, tAST_Node *Node, tSpiderValue *Array, int Index, tSpiderValue *SaveValue); -// - Variables -tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name, tSpiderValue *Value); - int Variable_SetValue(tAST_BlockState *Block, tAST_Node *VarNode, tSpiderValue *Value); -tSpiderValue *Variable_GetValue(tAST_BlockState *Block, tAST_Node *VarNode); -void Variable_Destroy(tAST_Variable *Variable); -// - Errors -void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...); -void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); - -// === GLOBALS === - int giNextBlockIdent = 1; - -// === CODE === -#if USE_AST_EXEC -tSpiderValue *AST_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Arguments) -{ - tAST_BlockState bs; - tSpiderValue *ret; - int i = 0; - - // Build a block State - bs.FirstVar = NULL; - bs.RetVal = NULL; - bs.Parent = NULL; - bs.BaseNamespace = &Script->Variant->RootNamespace; - bs.CurNamespace = NULL; - bs.Script = Script; - bs.Ident = giNextBlockIdent ++; - - // Parse arguments - for( i = 0; i < Fcn->ArgumentCount; i ++ ) - { - if( i >= NArguments ) break; // TODO: Return gracefully - // TODO: Type checks - Variable_Define(&bs, - Fcn->Arguments[i].Type, Fcn->Arguments[i].Name, - Arguments[i]); - } - - // Execute function - ret = AST_ExecuteNode(&bs, Fcn->ASTFcn); - if(ret != ERRPTR) - { - SpiderScript_DereferenceValue(ret); // Dereference output of last block statement - ret = bs.RetVal; // Set to return value of block - } - - while(bs.FirstVar) - { - tAST_Variable *nextVar = bs.FirstVar->Next; - Variable_Destroy( bs.FirstVar ); - bs.FirstVar = nextVar; - } - return ret; -} - -/** - * \brief Execute an AST node and return its value - * \param Block Execution context - * \param Node Node to execute - */ -tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) -{ - tAST_Node *node; - tSpiderValue *ret = NULL, *tmpobj; - tSpiderValue *op1, *op2; // Binary operations - int i; - - switch(Node->Type) - { - // No Operation - case NODETYPE_NOP: - ret = NULL; - break; - - // Code block - case NODETYPE_BLOCK: - { - tAST_BlockState blockInfo; - blockInfo.Parent = Block; - blockInfo.Script = Block->Script; - blockInfo.FirstVar = NULL; - blockInfo.RetVal = NULL; - blockInfo.BaseNamespace = Block->BaseNamespace; - blockInfo.CurNamespace = NULL; - blockInfo.BreakTarget = NULL; - blockInfo.Ident = giNextBlockIdent ++; - ret = NULL; - // Loop over all nodes, or until the return value is set - for(node = Node->Block.FirstChild; - node && !blockInfo.RetVal && !blockInfo.BreakTarget; - node = node->NextSibling ) - { - ret = AST_ExecuteNode(&blockInfo, node); - if(ret == ERRPTR) break; // Error check - if(ret != NULL) SpiderScript_DereferenceValue(ret); // Free unused value - } - // Clean up variables - while(blockInfo.FirstVar) - { - tAST_Variable *nextVar = blockInfo.FirstVar->Next; - Variable_Destroy( blockInfo.FirstVar ); - blockInfo.FirstVar = nextVar; - } - // Clear ret if not an error - if(ret != ERRPTR) ret = NULL; - - // Set parent's return value if needed - if( blockInfo.RetVal ) - Block->RetVal = blockInfo.RetVal; - if( blockInfo.BreakTarget ) { - Block->BreakTarget = blockInfo.BreakTarget; - Block->BreakType = blockInfo.BreakType; - } - - // TODO: Unset break if break type deontes a block break - } - - break; - - // Assignment - case NODETYPE_ASSIGN: - // TODO: Support assigning to object attributes - if( Node->Assign.Dest->Type != NODETYPE_VARIABLE ) { - AST_RuntimeError(Node, "LVALUE of assignment is not a variable"); - return ERRPTR; - } - ret = AST_ExecuteNode(Block, Node->Assign.Value); - if(ret == ERRPTR) return ERRPTR; - - // Perform assignment operation - if( Node->Assign.Operation != NODETYPE_NOP ) - { - tSpiderValue *varVal, *value; - - varVal = Variable_GetValue(Block, Node->Assign.Dest); - if(varVal == ERRPTR) return ERRPTR; - #if 0 - #else - if(varVal && varVal->ReferenceCount == 2) { - SpiderScript_DereferenceValue(varVal); -// printf("pre: (%s) varVal->ReferenceCount = %i\n", -// Node->Assign.Dest->Variable.Name, -// varVal->ReferenceCount); - } - #endif - value = AST_ExecuteNode_BinOp(Block->Script, Node, Node->Assign.Operation, varVal, ret); - if(value == ERRPTR) return ERRPTR; - - if(ret) SpiderScript_DereferenceValue(ret); - #if 0 - if(varVal) SpiderScript_DereferenceValue(varVal); - #else - if(varVal && varVal->ReferenceCount == 1) { - SpiderScript_ReferenceValue(varVal); -// printf("post: varVal->ReferenceCount = %i\n", varVal->ReferenceCount); - break; // If varVal was non-null, it has been updated by _BinOp - } - #endif - // Else, it was NULL, so has to be assigned - ret = value; - } - - // Set the variable value - if( Variable_SetValue( Block, Node->Assign.Dest, ret ) ) { - SpiderScript_DereferenceValue( ret ); - return ERRPTR; - } - break; - - // Post increment/decrement - case NODETYPE_POSTINC: - case NODETYPE_POSTDEC: - { - tSpiderValue *varVal, *value; - static tSpiderValue one = { - .Type = SS_DATATYPE_INTEGER, - .ReferenceCount = 1, - {.Integer = 1} - }; - - // TODO: Support assigning to object attributes - if( Node->UniOp.Value->Type != NODETYPE_VARIABLE ) { - AST_RuntimeError(Node, "LVALUE of assignment is not a variable"); - return ERRPTR; - } - - // Get values (current variable contents and a static one) - varVal = Variable_GetValue(Block, Node->UniOp.Value); - - if( Node->Type == NODETYPE_POSTDEC ) - value = AST_ExecuteNode_BinOp(Block->Script, Node, NODETYPE_SUBTRACT, varVal, &one); - else - value = AST_ExecuteNode_BinOp(Block->Script, Node, NODETYPE_ADD, varVal, &one); - if( value == ERRPTR ) - return ERRPTR; - - ret = varVal; - - if( Variable_SetValue( Block, Node->UniOp.Value, value ) ) { - SpiderScript_DereferenceValue( ret ); - return ERRPTR; - } - SpiderScript_DereferenceValue( value ); - } - break; - - // Function Call - case NODETYPE_METHODCALL: - case NODETYPE_FUNCTIONCALL: - case NODETYPE_CREATEOBJECT: - // Logical block (used to allocate `params`) - { - const char *namespaces[] = {NULL}; // TODO: Default namespaces? - tSpiderValue *params[Node->FunctionCall.NumArgs]; - i = 0; - - // Get arguments - for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) - { - params[i] = AST_ExecuteNode(Block, node); - if( params[i] == ERRPTR ) { - while(i--) SpiderScript_DereferenceValue(params[i]); - ret = ERRPTR; - goto _return; - } - i ++; - } - - // TODO: Check for cached function reference - - // Call the function - if( Node->Type == NODETYPE_CREATEOBJECT ) - { - ret = SpiderScript_CreateObject(Block->Script, - Node->FunctionCall.Name, - namespaces, - Node->FunctionCall.NumArgs, params - ); - } - else if( Node->Type == NODETYPE_METHODCALL ) - { - tSpiderValue *obj = AST_ExecuteNode(Block, Node->FunctionCall.Object); - if( !obj || obj == ERRPTR || obj->Type != SS_DATATYPE_OBJECT ) { - AST_RuntimeError(Node->FunctionCall.Object, - "Type Mismatch - Required SS_DATATYPE_OBJECT for method call"); - while(i--) SpiderScript_DereferenceValue(params[i]); - ret = ERRPTR; - break; - } - ret = SpiderScript_ExecuteMethod(Block->Script, - obj->Object, Node->FunctionCall.Name, - Node->FunctionCall.NumArgs, params - ); - SpiderScript_DereferenceValue(obj); - } - else - { - ret = SpiderScript_ExecuteFunction(Block->Script, - Node->FunctionCall.Name, - namespaces, - Node->FunctionCall.NumArgs, params, - NULL - ); - } - - - // Dereference parameters - while(i--) SpiderScript_DereferenceValue(params[i]); - - // falls out - } - break; - - // Conditional - case NODETYPE_IF: - ret = AST_ExecuteNode(Block, Node->If.Condition); - if( ret == ERRPTR ) break; - if( SpiderScript_IsValueTrue(ret) ) { - tmpobj = AST_ExecuteNode(Block, Node->If.True); - } - else { - tmpobj = AST_ExecuteNode(Block, Node->If.False); - } - SpiderScript_DereferenceValue(ret); - if( tmpobj == ERRPTR ) return ERRPTR; - SpiderScript_DereferenceValue(tmpobj); - ret = NULL; - break; - - // Loop - case NODETYPE_LOOP: - // Initialise - ret = AST_ExecuteNode(Block, Node->For.Init); - if(ret == ERRPTR) break; - - // Check initial condition - if( !Node->For.bCheckAfter ) - { - SpiderScript_DereferenceValue(ret); - - ret = AST_ExecuteNode(Block, Node->For.Condition); - if(ret == ERRPTR) return ERRPTR; - if(!SpiderScript_IsValueTrue(ret)) { - SpiderScript_DereferenceValue(ret); - ret = NULL; - break; - } - } - - // Perform loop - for( ;; ) - { - SpiderScript_DereferenceValue(ret); - - // Code - ret = AST_ExecuteNode(Block, Node->For.Code); - if(ret == ERRPTR) return ERRPTR; - SpiderScript_DereferenceValue(ret); - - if(Block->BreakTarget) - { - if( Block->BreakTarget[0] == '\0' || strcmp(Block->BreakTarget, Node->For.Tag) == 0 ) - { - // Ours - free((void*)Block->BreakTarget); Block->BreakTarget = NULL; - if( Block->BreakType == NODETYPE_CONTINUE ) { - // Continue, just keep going - } - else - break; - } - else - break; // Break out of this loop - } - - // Increment - ret = AST_ExecuteNode(Block, Node->For.Increment); - if(ret == ERRPTR) return ERRPTR; - SpiderScript_DereferenceValue(ret); - - // Check condition - ret = AST_ExecuteNode(Block, Node->For.Condition); - if(ret == ERRPTR) return ERRPTR; - if(!SpiderScript_IsValueTrue(ret)) break; - } - SpiderScript_DereferenceValue(ret); - ret = NULL; - break; - - // Return - case NODETYPE_RETURN: - ret = AST_ExecuteNode(Block, Node->UniOp.Value); - if(ret == ERRPTR) break; - Block->RetVal = ret; // Return value set - ret = NULL; // the `return` statement does not return a value - break; - - case NODETYPE_BREAK: - case NODETYPE_CONTINUE: - Block->BreakTarget = strdup(Node->Variable.Name); - Block->BreakType = Node->Type; - break; - - // Define a variable - case NODETYPE_DEFVAR: - if( Node->DefVar.InitialValue ) { - tmpobj = AST_ExecuteNode(Block, Node->DefVar.InitialValue); - if(tmpobj == ERRPTR) return ERRPTR; - } - else { - tmpobj = NULL; - } - // TODO: Handle arrays - ret = NULL; - if( Variable_Define(Block, Node->DefVar.DataType, Node->DefVar.Name, tmpobj) == ERRPTR ) - ret = ERRPTR; - SpiderScript_DereferenceValue(tmpobj); - break; - - // Scope - case NODETYPE_SCOPE: - { - tSpiderNamespace *ns; - - // Set current namespace if unset - if( !Block->CurNamespace ) - Block->CurNamespace = Block->BaseNamespace; - - // Empty string means use the root namespace - if( Node->Scope.Name[0] == '\0' ) - { - ns = &Block->Script->Variant->RootNamespace; - } - else - { - // Otherwise scan the current namespace for the element - for( ns = Block->CurNamespace->FirstChild; ns; ns = ns->Next ) - { - if( strcmp(ns->Name, Node->Scope.Name) == 0 ) - break; - } - } - if(!ns) { - AST_RuntimeError(Node, "Unknown namespace '%s'", Node->Scope.Name); - ret = ERRPTR; - break; - } - Block->CurNamespace = ns; - - // TODO: Check type of child node (Scope, Constant or Function) - - ret = AST_ExecuteNode(Block, Node->Scope.Element); - } - break; - - // Variable - case NODETYPE_VARIABLE: - ret = Variable_GetValue( Block, Node ); - break; - - // Element of an Object - case NODETYPE_ELEMENT: - tmpobj = AST_ExecuteNode( Block, Node->Scope.Element ); - if(tmpobj == ERRPTR) return ERRPTR; - - ret = AST_ExecuteNode_Element(Block->Script, Node, tmpobj, Node->Scope.Name, ERRPTR); - break; - - // Cast a value to another - case NODETYPE_CAST: - { - tmpobj = AST_ExecuteNode(Block, Node->Cast.Value); - if(tmpobj == ERRPTR) return ERRPTR; - ret = SpiderScript_CastValueTo( Node->Cast.DataType, tmpobj ); - SpiderScript_DereferenceValue(tmpobj); - } - break; - - // Index into an array - case NODETYPE_INDEX: - op1 = AST_ExecuteNode(Block, Node->BinOp.Left); // Array - if(op1 == ERRPTR) return ERRPTR; - op2 = AST_ExecuteNode(Block, Node->BinOp.Right); // Offset - if(op2 == ERRPTR) { - SpiderScript_DereferenceValue(op1); - return ERRPTR; - } - - if( !op2 || op2->Type != SS_DATATYPE_INTEGER ) - { - if( !Block->Script->Variant->bImplicitCasts ) { - AST_RuntimeError(Node, "Array index is not an integer"); - ret = ERRPTR; - break; - } - else { - tmpobj = SpiderScript_CastValueTo(SS_DATATYPE_INTEGER, op2); - SpiderScript_DereferenceValue(op2); - op2 = tmpobj; - } - } - - if( !op1 ) - { - SpiderScript_DereferenceValue(op2); - AST_RuntimeError(Node, "Indexing NULL value"); - ret = ERRPTR; - break; - } - - ret = AST_ExecuteNode_Index(Block->Script, Node, op1, op2->Integer, ERRPTR); - - SpiderScript_DereferenceValue(op1); - SpiderScript_DereferenceValue(op2); - break; - - // TODO: Implement runtime constants - case NODETYPE_CONSTANT: - // TODO: Scan namespace for constant name - AST_RuntimeError(Node, "TODO - Runtime Constants"); - ret = ERRPTR; - break; - - // Constant Values - case NODETYPE_STRING: - case NODETYPE_INTEGER: - case NODETYPE_REAL: - ret = &Node->Constant; - SpiderScript_ReferenceValue(ret); - break; - case NODETYPE_NULL: - ret = NULL; - break; - - // --- Operations --- - // Boolean Operations - case NODETYPE_LOGICALNOT: // Logical NOT (!) - op1 = AST_ExecuteNode(Block, Node->UniOp.Value); - if(op1 == ERRPTR) return ERRPTR; - ret = SpiderScript_CreateInteger( !SpiderScript_IsValueTrue(op1) ); - SpiderScript_DereferenceValue(op1); - break; - case NODETYPE_LOGICALAND: // Logical AND (&&) - case NODETYPE_LOGICALOR: // Logical OR (||) - case NODETYPE_LOGICALXOR: // Logical XOR (^^) - op1 = AST_ExecuteNode(Block, Node->BinOp.Left); - if(op1 == ERRPTR) return ERRPTR; - op2 = AST_ExecuteNode(Block, Node->BinOp.Right); - if(op2 == ERRPTR) { - SpiderScript_DereferenceValue(op1); - return ERRPTR; - } - - switch( Node->Type ) - { - case NODETYPE_LOGICALAND: - ret = SpiderScript_CreateInteger( SpiderScript_IsValueTrue(op1) && SpiderScript_IsValueTrue(op2) ); - break; - case NODETYPE_LOGICALOR: - ret = SpiderScript_CreateInteger( SpiderScript_IsValueTrue(op1) || SpiderScript_IsValueTrue(op2) ); - break; - case NODETYPE_LOGICALXOR: - ret = SpiderScript_CreateInteger( SpiderScript_IsValueTrue(op1) ^ SpiderScript_IsValueTrue(op2) ); - break; - default: break; - } - - // Free intermediate objects - SpiderScript_DereferenceValue(op1); - SpiderScript_DereferenceValue(op2); - break; - - // General Unary Operations - case NODETYPE_BWNOT: // Bitwise NOT (~) - case NODETYPE_NEGATE: // Negation (-) - op1 = AST_ExecuteNode(Block, Node->UniOp.Value); - if(op1 == ERRPTR) return ERRPTR; - ret = AST_ExecuteNode_UniOp(Block->Script, Node, Node->Type, op1); - SpiderScript_DereferenceValue(op1); - break; - - // General Binary Operations - case NODETYPE_ADD: - case NODETYPE_SUBTRACT: - case NODETYPE_MULTIPLY: - case NODETYPE_DIVIDE: - case NODETYPE_MODULO: - case NODETYPE_BWAND: - case NODETYPE_BWOR: - case NODETYPE_BWXOR: - case NODETYPE_BITSHIFTLEFT: - case NODETYPE_BITSHIFTRIGHT: - case NODETYPE_BITROTATELEFT: - case NODETYPE_EQUALS: - case NODETYPE_NOTEQUALS: - case NODETYPE_LESSTHAN: - case NODETYPE_GREATERTHAN: - case NODETYPE_LESSTHANEQUAL: - case NODETYPE_GREATERTHANEQUAL: - // Get operands - op1 = AST_ExecuteNode(Block, Node->BinOp.Left); - if(op1 == ERRPTR) return ERRPTR; - op2 = AST_ExecuteNode(Block, Node->BinOp.Right); - if(op2 == ERRPTR) { - SpiderScript_DereferenceValue(op1); - return ERRPTR; - } - - ret = AST_ExecuteNode_BinOp(Block->Script, Node, Node->Type, op1, op2); - - // Free intermediate objects - SpiderScript_DereferenceValue(op1); - SpiderScript_DereferenceValue(op2); - break; - - //default: - // ret = NULL; - // AST_RuntimeError(Node, "BUG - SpiderScript AST_ExecuteNode Unimplemented %i", Node->Type); - // break; - } -_return: - // Reset namespace when no longer needed - if( Node->Type != NODETYPE_SCOPE ) - Block->CurNamespace = NULL; - - #if TRACE_NODE_RETURNS - if(ret && ret != ERRPTR) { - AST_RuntimeError(Node, "Ret type of %p %i is %i", Node, Node->Type, ret->Type); - } - else { - AST_RuntimeError(Node, "Ret type of %p %i is %p", Node, Node->Type, ret); - } - #endif - - return ret; -} -#endif - -tSpiderValue *AST_ExecuteNode_UniOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Value) -{ - tSpiderValue *ret; - #if 0 - if( Value->Type == SS_DATATYPE_OBJECT ) - { - const char *fcnname; - switch(Operation) - { - case NODETYPE_NEGATE: fcnname = "-ve"; break; - case NODETYPE_BWNOT: fcnname = "~"; break; - default: fcnname = NULL; break; - } - - if( fcnname ) - { - ret = Object_ExecuteMethod(Value->Object, fcnname, ); - if( ret != ERRPTR ) - return ret; - } - } - #endif - switch(Value->Type) - { - // Integer Operations - case SS_DATATYPE_INTEGER: - if( Value->ReferenceCount == 1 ) - SpiderScript_ReferenceValue(ret = Value); - else - ret = SpiderScript_CreateInteger(0); - switch(Operation) - { - case NODETYPE_NEGATE: ret->Integer = -Value->Integer; break; - case NODETYPE_BWNOT: ret->Integer = ~Value->Integer; break; - default: - AST_RuntimeError(Node, "SpiderScript internal error: Exec,UniOP,Integer unknown op %i", Operation); - SpiderScript_DereferenceValue(ret); - ret = ERRPTR; - break; - } - break; - // Real number Operations - case SS_DATATYPE_REAL: - switch(Operation) - { - case NODETYPE_NEGATE: ret = SpiderScript_CreateInteger( -Value->Real ); break; - default: - AST_RuntimeError(Node, "SpiderScript internal error: Exec,UniOP,Real unknown op %i", Operation); - ret = ERRPTR; - break; - } - break; - - default: - AST_RuntimeError(NULL, "Invalid operation (%i) on type (%i)", Operation, Value->Type); - ret = ERRPTR; - break; - } - - return ret; -} - -tSpiderValue *AST_ExecuteNode_BinOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Left, tSpiderValue *Right) -{ - tSpiderValue *preCastValue = Right; - tSpiderValue *ret; - - // Convert types - if( Left && Right && Left->Type != Right->Type ) - { - #if 0 - // Object types - // - Operator overload functions - if( Left->Type == SS_DATATYPE_OBJECT ) - { - const char *fcnname; - switch(Operation) - { - case NODETYPE_ADD: fcnname = "+"; break; - case NODETYPE_SUBTRACT: fcnname = "-"; break; - case NODETYPE_MULTIPLY: fcnname = "*"; break; - case NODETYPE_DIVIDE: fcnname = "/"; break; - case NODETYPE_MODULO: fcnname = "%"; break; - case NODETYPE_BWAND: fcnname = "&"; break; - case NODETYPE_BWOR: fcnname = "|"; break; - case NODETYPE_BWXOR: fcnname = "^"; break; - case NODETYPE_BITSHIFTLEFT: fcnname = "<<"; break; - case NODETYPE_BITSHIFTRIGHT:fcnname = ">>"; break; - case NODETYPE_BITROTATELEFT:fcnname = "<<<"; break; - default: fcnname = NULL; break; - } - - if( fcnname ) - { - ret = Object_ExecuteMethod(Left->Object, fcnname, Right); - if( ret != ERRPTR ) - return ret; - // Fall through and try casting (which will usually fail) - } - } - #endif - - // If implicit casts are allowed, convert Right to Left's type - if(Script->Variant->bImplicitCasts) - { - Right = SpiderScript_CastValueTo(Left->Type, Right); - if(Right == ERRPTR) - return ERRPTR; - } - // If statically typed, this should never happen, but catch it anyway - else { - AST_RuntimeError(Node, "Implicit cast not allowed (from %i to %i)", Right->Type, Left->Type); - return ERRPTR; - } - } - - // NULL Check - if( Left == NULL || Right == NULL ) { - if(Right && Right != preCastValue) free(Right); - return NULL; - } - - // Catch comparisons - switch(Operation) - { - case NODETYPE_EQUALS: - case NODETYPE_NOTEQUALS: - case NODETYPE_LESSTHAN: - case NODETYPE_GREATERTHAN: - case NODETYPE_LESSTHANEQUAL: - case NODETYPE_GREATERTHANEQUAL: { - int cmp; - ret = NULL; - // Do operation - switch(Left->Type) - { - // - String Compare (does a strcmp, well memcmp) - case SS_DATATYPE_STRING: - // Call memcmp to do most of the work - cmp = memcmp( - Left->String.Data, Right->String.Data, - (Left->String.Length < Right->String.Length) ? Left->String.Length : Right->String.Length - ); - // Handle reaching the end of the string - if( cmp == 0 ) { - if( Left->String.Length == Right->String.Length ) - cmp = 0; - else if( Left->String.Length < Right->String.Length ) - cmp = 1; - else - cmp = -1; - } - break; - - // - Integer Comparisons - case SS_DATATYPE_INTEGER: - if( Left->Integer == Right->Integer ) - cmp = 0; - else if( Left->Integer < Right->Integer ) - cmp = -1; - else - cmp = 1; - break; - // - Real Number Comparisons - case SS_DATATYPE_REAL: - cmp = (Left->Real - Right->Real) / Right->Real * 10000; // < 0.1% difference is equality - break; - default: - AST_RuntimeError(Node, "TODO - Comparison of type %i", Left->Type); - ret = ERRPTR; - break; - } - - // Error check - if( ret != ERRPTR ) - { - if(Left->ReferenceCount == 1 && Left->Type != SS_DATATYPE_STRING) - SpiderScript_ReferenceValue(ret = Left); - else - ret = SpiderScript_CreateInteger(0); - - // Create return - switch(Operation) - { - case NODETYPE_EQUALS: ret->Integer = (cmp == 0); break; - case NODETYPE_NOTEQUALS: ret->Integer = (cmp != 0); break; - case NODETYPE_LESSTHAN: ret->Integer = (cmp < 0); break; - case NODETYPE_GREATERTHAN: ret->Integer = (cmp > 0); break; - case NODETYPE_LESSTHANEQUAL: ret->Integer = (cmp <= 0); break; - case NODETYPE_GREATERTHANEQUAL: ret->Integer = (cmp >= 0); break; - default: - AST_RuntimeError(Node, "Exec,CmpOp unknown op %i", Operation); - SpiderScript_DereferenceValue(ret); - ret = ERRPTR; - break; - } - } - if(Right && Right != preCastValue) free(Right); - return ret; - } - - // Fall through and sort by type instead - default: - break; - } - - // Do operation - switch(Left->Type) - { - // String Concatenation - case SS_DATATYPE_STRING: - switch(Operation) - { - case NODETYPE_ADD: // Concatenate - ret = SpiderScript_StringConcat(Left, Right); - break; - // TODO: Support python style 'i = %i' % i ? - // Might do it via a function call - // Implement it via % with an array, but getting past the cast will be fun -// case NODETYPE_MODULUS: -// break; - // TODO: Support string repititions -// case NODETYPE_MULTIPLY: -// break; - - default: - AST_RuntimeError(Node, "SpiderScript internal error: Exec,BinOP,String unknown op %i", Operation); - ret = ERRPTR; - break; - } - break; - // Integer Operations - case SS_DATATYPE_INTEGER: - if( Left->ReferenceCount == 1 ) - SpiderScript_ReferenceValue(ret = Left); - else - ret = SpiderScript_CreateInteger(0); - switch(Operation) - { - case NODETYPE_ADD: ret->Integer = Left->Integer + Right->Integer; break; - case NODETYPE_SUBTRACT: ret->Integer = Left->Integer - Right->Integer; break; - case NODETYPE_MULTIPLY: ret->Integer = Left->Integer * Right->Integer; break; - case NODETYPE_DIVIDE: ret->Integer = Left->Integer / Right->Integer; break; - case NODETYPE_MODULO: ret->Integer = Left->Integer % Right->Integer; break; - case NODETYPE_BWAND: ret->Integer = Left->Integer & Right->Integer; break; - case NODETYPE_BWOR: ret->Integer = Left->Integer | Right->Integer; break; - case NODETYPE_BWXOR: ret->Integer = Left->Integer ^ Right->Integer; break; - case NODETYPE_BITSHIFTLEFT: ret->Integer = Left->Integer << Right->Integer; break; - case NODETYPE_BITSHIFTRIGHT:ret->Integer = Left->Integer >> Right->Integer; break; - case NODETYPE_BITROTATELEFT: - ret->Integer = (Left->Integer << Right->Integer) | (Left->Integer >> (64-Right->Integer)); - break; - default: - AST_RuntimeError(Node, "SpiderScript internal error: Exec,BinOP,Integer unknown op %i", Operation); - SpiderScript_DereferenceValue(ret); - ret = ERRPTR; - break; - } - break; - - // Real Numbers - case SS_DATATYPE_REAL: - if( Left->ReferenceCount == 1 ) - SpiderScript_ReferenceValue(ret = Left); - else - ret = SpiderScript_CreateReal(0); - switch(Operation) - { - case NODETYPE_ADD: ret->Real = Left->Real + Right->Real; break; - case NODETYPE_SUBTRACT: ret->Real = Left->Real - Right->Real; break; - case NODETYPE_MULTIPLY: ret->Real = Left->Real * Right->Real; break; - case NODETYPE_DIVIDE: ret->Real = Left->Real / Right->Real; break; - default: - AST_RuntimeError(Node, "SpiderScript internal error: Exec,BinOP,Real unknown op %i", Operation); - SpiderScript_DereferenceValue(ret); - ret = ERRPTR; - break; - } - break; - - default: - AST_RuntimeError(Node, "BUG - Invalid operation (%i) on type (%i)", Operation, Left->Type); - ret = ERRPTR; - break; - } - - if(Right && Right != preCastValue) free(Right); - - return ret; -} - -tSpiderValue *AST_ExecuteNode_Index(tSpiderScript *Script, tAST_Node *Node, - tSpiderValue *Array, int Index, tSpiderValue *SaveValue) -{ - // Quick sanity check - if( !Array ) - { - AST_RuntimeError(Node, "Indexing NULL, not a good idea"); - return ERRPTR; - } - - // Array? - if( SS_GETARRAYDEPTH(Array->Type) ) - { - if( Index < 0 || Index >= Array->Array.Length ) { - AST_RuntimeError(Node, "Array index out of bounds %i not in (0, %i]", - Index, Array->Array.Length); - return ERRPTR; - } - - if( SaveValue != ERRPTR ) - { - if( SaveValue && SaveValue->Type != SS_DOWNARRAY(Array->Type) ) { - // TODO: Implicit casting - AST_RuntimeError(Node, "Type mismatch assiging to array element"); - return ERRPTR; - } - SpiderScript_DereferenceValue( Array->Array.Items[Index] ); - Array->Array.Items[Index] = SaveValue; - SpiderScript_ReferenceValue( Array->Array.Items[Index] ); - return NULL; - } - else - { - SpiderScript_ReferenceValue( Array->Array.Items[Index] ); - return Array->Array.Items[Index]; - } - } - else - { - AST_RuntimeError(Node, "TODO - Implement indexing on non-arrays (type = %x)", - Array->Type); - return ERRPTR; - } -} - -/** - * \brief Get/Set the value of an element/attribute of a class - * \param Script Executing script - * \param Node Current execution node (only used for AST_RuntimeError) - * \param Object Object value - * \param ElementName Name of the attribute to be accessed - * \param SaveValue Value to set the element to (if ERRPTR, element value is returned) - */ -tSpiderValue *AST_ExecuteNode_Element(tSpiderScript *Script, tAST_Node *Node, - tSpiderValue *Object, const char *ElementName, tSpiderValue *SaveValue) -{ - int i; - tSpiderValue *ret; - - if( !Object ) { - AST_RuntimeError(Node, "Tried to access an element of NULL"); - return ERRPTR; - } - - switch( Object->Type ) - { - case SS_DATATYPE_OBJECT: { - tSpiderObjectDef *class = Object->Object->Type; - for( i = 0; i < class->NAttributes; i ++ ) - { - if( strcmp(ElementName, class->AttributeDefs[i].Name) == 0 ) - { - if( SaveValue != ERRPTR ) { - Object->Object->Attributes[i] = SaveValue; - SpiderScript_ReferenceValue(SaveValue); - return NULL; - } - else { - ret = Object->Object->Attributes[i]; - SpiderScript_ReferenceValue(ret); - return ret; - } - } - } - AST_RuntimeError(Node, "Unknown attribute '%s' of class '%s'", - ElementName, class->Name); - return ERRPTR; } - default: - AST_RuntimeError(Node, "Unable to get element of type %i", Object->Type); - return ERRPTR; - } -} - -#if USE_AST_EXEC -/** - * \brief Define a variable - * \param Block Current block state - * \param Type Type of the variable - * \param Name Name of the variable - * \return Boolean Failure - */ -tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name, tSpiderValue *Value) -{ - tAST_Variable *var, *prev = NULL; - - for( var = Block->FirstVar; var; prev = var, var = var->Next ) - { - if( strcmp(var->Name, Name) == 0 ) { - AST_RuntimeError(NULL, "Redefinition of variable '%s'", Name); - return ERRPTR; - } - } - - var = malloc( sizeof(tAST_Variable) + strlen(Name) + 1 ); - var->Next = NULL; - var->Type = Type; - var->Object = Value; - if(Value) SpiderScript_ReferenceValue(Value); - strcpy(var->Name, Name); - - if(prev) prev->Next = var; - else Block->FirstVar = var; - - //printf("Defined variable %s (%i)\n", Name, Type); - - return var; -} - -tAST_Variable *Variable_Lookup(tAST_BlockState *Block, tAST_Node *VarNode, int CreateType) -{ - tAST_Variable *var = NULL; - - // Speed hack - if( VarNode->BlockState == Block && VarNode->BlockIdent == Block->Ident ) { - var = VarNode->ValueCache; - #if TRACE_VAR_LOOKUPS - AST_RuntimeMessage(VarNode, "debug", "Fast var fetch on '%s' %p (%p:%i)", - VarNode->Variable.Name, var, - VarNode->BlockState, VarNode->BlockIdent - ); - #endif - } - else - { - tAST_BlockState *bs; - for( bs = Block; bs; bs = bs->Parent ) - { - for( var = bs->FirstVar; var; var = var->Next ) - { - if( strcmp(var->Name, VarNode->Variable.Name) == 0 ) - break; - } - if(var) break; - } - - if( !var ) - { - if( Block->Script->Variant->bDyamicTyped && CreateType != SS_DATATYPE_UNDEF ) { - // Define variable - var = Variable_Define(Block, CreateType, VarNode->Variable.Name, NULL); - } - else - { - AST_RuntimeError(VarNode, "Variable '%s' is undefined", VarNode->Variable.Name); - return NULL; - } - } - - #if TRACE_VAR_LOOKUPS - AST_RuntimeMessage(VarNode, "debug", "Saved variable lookup of '%s' %p (%p:%i)", - VarNode->Variable.Name, var, - Block, Block->Ident); - #endif - - VarNode->ValueCache = var; - VarNode->BlockState = Block; - VarNode->BlockIdent = Block->Ident; - } - - return var; -} - -/** - * \brief Set the value of a variable - * \return Boolean Failure - */ -int Variable_SetValue(tAST_BlockState *Block, tAST_Node *VarNode, tSpiderValue *Value) -{ - tAST_Variable *var; - - var = Variable_Lookup(Block, VarNode, (Value ? Value->Type : SS_DATATYPE_UNDEF)); - - if( !var ) return -1; - - if( !Block->Script->Variant->bDyamicTyped && (Value && var->Type != Value->Type) ) - { - AST_RuntimeError(VarNode, "Type mismatch assigning to '%s'", - VarNode->Variable.Name); - return -2; - } - -// printf("Assign %p to '%s'\n", Value, var->Name); - SpiderScript_ReferenceValue(Value); - SpiderScript_DereferenceValue(var->Object); - var->Object = Value; - return 0; -} - -/** - * \brief Get the value of a variable - */ -tSpiderValue *Variable_GetValue(tAST_BlockState *Block, tAST_Node *VarNode) -{ - tAST_Variable *var = Variable_Lookup(Block, VarNode, 0); - - if( !var ) return ERRPTR; - - SpiderScript_ReferenceValue(var->Object); - return var->Object; -} - -/** - * \brief Destorys a variable - */ -void Variable_Destroy(tAST_Variable *Variable) -{ -// printf("Variable_Destroy: (%p'%s')\n", Variable, Variable->Name); - SpiderScript_DereferenceValue(Variable->Object); - free(Variable); -} -#endif - diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c deleted file mode 100644 index 9de7281e..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c +++ /dev/null @@ -1,984 +0,0 @@ -/* - * SpiderScript Library - * by John Hodge (thePowersGang) - * - * exec_bytecode.c - * - Execute bytecode - */ -#include -#include -#include "common.h" -#include "bytecode.h" -#include -#include -#include "ast.h" -#include - -#define TRACE 0 - -#if TRACE -# define DEBUG_F(v...) printf(v) -#else -# define DEBUG_F(v...) -#endif - -// === IMPORTS === -extern void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); - -// === TYPES === -typedef struct sBC_StackEnt tBC_StackEnt; -typedef struct sBC_Stack tBC_Stack; - -enum eBC_StackEntTypes -{ - ET_NULL, // Start of the stack - // SS_DATATYPE_* - ET_FUNCTION_START = NUM_SS_DATATYPES, - ET_REFERENCE // Reference to a tSpiderValue -}; - -struct sBC_StackEnt -{ - uint8_t Type; - union { - int64_t Integer; - double Real; - tSpiderValue *Reference; // Used for everything else - tSpiderObject *Object; - tSpiderNamespace *Namespace; - }; -}; - -struct sBC_Stack -{ - int EntrySpace; - int EntryCount; - tBC_StackEnt Entries[]; -}; - -// === PROTOTYPES === -tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args); - int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, tBC_Stack *Stack, int ArgCount); - -// === CODE === -int Bytecode_int_StackPop(tBC_Stack *Stack, tBC_StackEnt *Dest) -{ - if( Stack->EntryCount == 0 ) return 1; - Stack->EntryCount --; - *Dest = Stack->Entries[Stack->EntryCount]; - return 0; -} - -int Bytecode_int_StackPush(tBC_Stack *Stack, tBC_StackEnt *Src) -{ - if( Stack->EntryCount == Stack->EntrySpace ) return 1; - Stack->Entries[Stack->EntryCount] = *Src; - Stack->EntryCount ++; - return 0; -} - -int Bytecode_int_IsStackEntTrue(tBC_StackEnt *Ent) -{ - switch(Ent->Type) - { - case SS_DATATYPE_INTEGER: - return !!Ent->Integer; - case SS_DATATYPE_REAL: - return !(-.5f < Ent->Real && Ent->Real < 0.5f); - case SS_DATATYPE_OBJECT: - return Ent->Object != NULL; - case ET_FUNCTION_START: - return -1; - default: - return SpiderScript_IsValueTrue(Ent->Reference); - } -} - -tSpiderValue *Bytecode_int_GetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *tmp) -{ - switch(Ent->Type) - { - case SS_DATATYPE_INTEGER: - case SS_DATATYPE_REAL: - case SS_DATATYPE_OBJECT: - if(!tmp) { - tmp = malloc(sizeof(tSpiderValue)); - tmp->ReferenceCount = 1; - } else { - // Stops a stack value from having free() called on it - tmp->ReferenceCount = 2; - } - break; - default: - break; - } - switch(Ent->Type) - { - case SS_DATATYPE_INTEGER: - tmp->Type = SS_DATATYPE_INTEGER; - tmp->Integer = Ent->Integer; - return tmp; - case SS_DATATYPE_REAL: - tmp->Type = SS_DATATYPE_REAL; - tmp->Real = Ent->Real; - return tmp; - case SS_DATATYPE_OBJECT: - tmp->Type = SS_DATATYPE_OBJECT; - tmp->Object = Ent->Object; - return tmp; - case ET_FUNCTION_START: - AST_RuntimeError(NULL, "_GetSpiderValue on ET_FUNCTION_START"); - return NULL; - default: - SpiderScript_ReferenceValue(Ent->Reference); - return Ent->Reference; - } -} - -void Bytecode_int_SetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *Value) -{ - if(!Value) { - Ent->Type = ET_REFERENCE; - Ent->Reference = NULL; - return ; - } - switch(Value->Type) - { - case SS_DATATYPE_INTEGER: - Ent->Type = SS_DATATYPE_INTEGER; - Ent->Integer = Value->Integer; - break; - case SS_DATATYPE_REAL: - Ent->Type = SS_DATATYPE_REAL; - Ent->Real = Value->Real; - break; - case SS_DATATYPE_OBJECT: - Ent->Type = SS_DATATYPE_OBJECT; - Ent->Object = Value->Object; - Ent->Object->ReferenceCount ++; - break; - default: - SpiderScript_ReferenceValue(Value); - Ent->Type = ET_REFERENCE; - Ent->Reference = Value; - break; - } -} - -void Bytecode_int_DerefStackValue(tBC_StackEnt *Ent) -{ - switch(Ent->Type) - { - case SS_DATATYPE_INTEGER: - case SS_DATATYPE_REAL: - break; - case SS_DATATYPE_OBJECT: - if(Ent->Object) { - Ent->Object->ReferenceCount --; - if(Ent->Object->ReferenceCount == 0) { - Ent->Object->Type->Destructor( Ent->Object ); - } -// printf("Object %p derefed (obj refcount = %i)\n", Ent->Object, Ent->Object->ReferenceCount); - } - Ent->Object = NULL; - break; - default: - if(Ent->Reference) - SpiderScript_DereferenceValue(Ent->Reference); - Ent->Reference = NULL; - break; - } -} -void Bytecode_int_RefStackValue(tBC_StackEnt *Ent) -{ - switch(Ent->Type) - { - case SS_DATATYPE_INTEGER: - case SS_DATATYPE_REAL: - break; - case SS_DATATYPE_OBJECT: - if(Ent->Object) { - Ent->Object->ReferenceCount ++; -// printf("Object %p referenced (count = %i)\n", Ent->Object, Ent->Object->ReferenceCount); - } - break; - default: - if(Ent->Reference) - SpiderScript_ReferenceValue(Ent->Reference); - break; - } -} - -void Bytecode_int_PrintStackValue(tBC_StackEnt *Ent) -{ - switch(Ent->Type) - { - case SS_DATATYPE_INTEGER: - printf("0x%"PRIx64, Ent->Integer); - break; - case SS_DATATYPE_REAL: - printf("%lf", Ent->Real); - break; - case SS_DATATYPE_OBJECT: - printf("Obj %p", Ent->Object); - break; - default: - if( Ent->Reference ) - printf("*%p (%i refs)", Ent->Reference, Ent->Reference->ReferenceCount); - else - printf("NULL"); - break; - } -} - -#if TRACE -# define PRINT_STACKVAL(val) Bytecode_int_PrintStackValue(&val) -#else -# define PRINT_STACKVAL(val) -#endif - -#define GET_STACKVAL(dst) if((ret = Bytecode_int_StackPop(Stack, &dst))) { \ - AST_RuntimeError(NULL, "Stack pop failed, empty stack");\ - return ret; \ -} -#define PUT_STACKVAL(src) if((ret = Bytecode_int_StackPush(Stack, &src))) { \ - AST_RuntimeError(NULL, "Stack push failed, full stack");\ - return ret; \ -} -#define OP_INDX(op_ptr) ((op_ptr)->Content.StringInt.Integer) -#define OP_STRING(op_ptr) ((op_ptr)->Content.StringInt.String) - -tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args) -{ - const int stack_size = 100; - tSpiderValue *ret, tmpsval; - tBC_Stack *stack; - tBC_StackEnt val; - int i; - - stack = malloc(sizeof(tBC_Stack) + stack_size*sizeof(tBC_StackEnt)); - stack->EntrySpace = stack_size; - stack->EntryCount = 0; - - // Push arguments in order (so top is last arg) - for( i = 0; i < NArguments; i ++ ) - { - Bytecode_int_SetSpiderValue(&val, Args[i]); - Bytecode_int_StackPush(stack, &val); - } - - // Call - Bytecode_int_ExecuteFunction(Script, Fcn, stack, NArguments); - - // Get return value - if( Bytecode_int_StackPop(stack, &val) ) { - free(stack); - return NULL; - } - free(stack); - - ret = Bytecode_int_GetSpiderValue(&val, &tmpsval); - // Ensure it's a heap value - if(ret == &tmpsval) { - ret = malloc(sizeof(tSpiderValue)); - memcpy(ret, &tmpsval, sizeof(tSpiderValue)); - // Set to 2 in _GetSpiderValue, so stack doesn't have free() called - ret->ReferenceCount = 1; - } - - return ret; -} - -tSpiderNamespace *Bytecode_int_ResolveNamespace(tSpiderNamespace *Start, const char *Name, const char **FinalName) -{ - char *pos; - tSpiderNamespace *ns = Start; - while( (pos = strchr(Name, BC_NS_SEPARATOR)) ) - { - int len = pos - Name; - for( ns = ns->FirstChild; ns; ns = ns->Next ) - { - if(memcmp(ns->Name, Name, len) == 0 && ns->Name[len] == 0) - break; - } - if(!ns) { - return NULL; - } - Name += len + 1; - } - if(FinalName) *FinalName = Name; - return ns; -} - -/** - * \brief Call an external function (may recurse into Bytecode_ExecuteFunction, but may not) - */ -int Bytecode_int_CallExternFunction(tSpiderScript *Script, tBC_Stack *Stack, tSpiderNamespace *DefaultNS, tBC_Op *op ) -{ - const char *name = OP_STRING(op); - int arg_count = OP_INDX(op); - int i, ret = 0; - tSpiderValue *args[arg_count]; - tSpiderValue *rv; - tBC_StackEnt val1; - const char *namespaces[] = {NULL}; // TODO: Default/imported namespaces - - DEBUG_F("CALL (general) %s %i args\n", name, arg_count); - - // Read arguments - for( i = arg_count; i --; ) - { - GET_STACKVAL(val1); - args[i] = Bytecode_int_GetSpiderValue(&val1, NULL); - Bytecode_int_DerefStackValue(&val1); - } - - // Call the function etc. - if( op->Operation == BC_OP_CALLFUNCTION ) - { - rv = SpiderScript_ExecuteFunction(Script, name, namespaces, arg_count, args, &op->CacheEnt); - } - else if( op->Operation == BC_OP_CREATEOBJ ) - { - rv = SpiderScript_CreateObject(Script, name, namespaces, arg_count, args); - } - else if( op->Operation == BC_OP_CALLMETHOD ) - { - tSpiderObject *obj; - GET_STACKVAL(val1); - - if(val1.Type == SS_DATATYPE_OBJECT) - obj = val1.Object; - else if(val1.Type == ET_REFERENCE && val1.Reference && val1.Reference->Type == SS_DATATYPE_OBJECT) - obj = val1.Reference->Object; - else { - // Error - AST_RuntimeError(NULL, "OP_CALLMETHOD on non object"); - return -1; - } - rv = SpiderScript_ExecuteMethod(Script, obj, name, arg_count, args); - Bytecode_int_DerefStackValue(&val1); - } - else - { - AST_RuntimeError(NULL, "BUG - Unknown operation for CALL/CREATEOBJ (%i)", op->Operation); - rv = ERRPTR; - } - if(rv == ERRPTR) { - AST_RuntimeError(NULL, "SpiderScript_ExecuteFunction returned ERRPTR"); - return -1; - } - // Clean up args - for( i = arg_count; i --; ) - SpiderScript_DereferenceValue(args[i]); - // Get and push return - Bytecode_int_SetSpiderValue(&val1, rv); - PUT_STACKVAL(val1); - // Deref return - SpiderScript_DereferenceValue(rv); - - #if 0 - if(!rv) { - printf("%s returned NULL\n", name); - } - if( rv && rv != ERRPTR && rv->ReferenceCount != 1 ) { - printf("Return value from %s reference count fail (%i)\n", - name, rv->ReferenceCount); - } - #endif - - return 0; -} - -int Bytecode_int_LocalBinOp_Integer(int Operation, tBC_StackEnt *Val1, tBC_StackEnt *Val2) -{ - switch(Operation) - { - case BC_OP_ADD: Val1->Integer = Val1->Integer + Val2->Integer; break; - case BC_OP_SUBTRACT: Val1->Integer = Val1->Integer - Val2->Integer; break; - case BC_OP_MULTIPLY: Val1->Integer = Val1->Integer * Val2->Integer; break; - case BC_OP_DIVIDE: Val1->Integer = Val1->Integer / Val2->Integer; break; - - case BC_OP_EQUALS: Val1->Integer = (Val1->Integer == Val2->Integer); break; - case BC_OP_NOTEQUALS: Val1->Integer = (Val1->Integer != Val2->Integer); break; - case BC_OP_LESSTHAN: Val1->Integer = (Val1->Integer < Val2->Integer); break; - case BC_OP_LESSTHANOREQUAL: Val1->Integer = (Val1->Integer <= Val2->Integer); break; - case BC_OP_GREATERTHAN: Val1->Integer = (Val1->Integer > Val2->Integer); break; - case BC_OP_GREATERTHANOREQUAL: Val1->Integer = (Val1->Integer >= Val2->Integer); break; - - case BC_OP_BITAND: Val1->Integer = Val1->Integer & Val2->Integer; break; - case BC_OP_BITOR: Val1->Integer = Val1->Integer | Val2->Integer; break; - case BC_OP_BITXOR: Val1->Integer = Val1->Integer ^ Val2->Integer; break; - case BC_OP_MODULO: Val1->Integer = Val1->Integer % Val2->Integer; break; - default: AST_RuntimeError(NULL, "Invalid operation on datatype Integer"); return -1; - } - return 0; -} - -int Bytecode_int_LocalBinOp_Real(int Operation, tBC_StackEnt *Val1, tBC_StackEnt *Val2) -{ - switch(Operation) - { - // Real = Real OP Real - case BC_OP_ADD: Val1->Real = Val1->Real + Val2->Real; return 0; - case BC_OP_SUBTRACT: Val1->Real = Val1->Real - Val2->Real; return 0; - case BC_OP_MULTIPLY: Val1->Real = Val1->Real * Val2->Real; return 0; - case BC_OP_DIVIDE: Val1->Real = Val1->Real / Val2->Real; return 0; - - // Bool/Integer = Real OP Real - case BC_OP_EQUALS: Val1->Integer = (Val1->Real == Val2->Real); break; - case BC_OP_NOTEQUALS: Val1->Integer = (Val1->Real != Val2->Real); break; - case BC_OP_LESSTHAN: Val1->Integer = (Val1->Real < Val2->Real); break; - case BC_OP_LESSTHANOREQUAL: Val1->Integer = (Val1->Real <= Val2->Real); break; - case BC_OP_GREATERTHAN: Val1->Integer = (Val1->Real > Val2->Real); break; - case BC_OP_GREATERTHANOREQUAL: Val1->Integer = (Val1->Real >= Val2->Real); break; - - default: AST_RuntimeError(NULL, "Invalid operation on datatype Real"); return -1; - } - Val1->Type = SS_DATATYPE_INTEGER; // Becomes logical - return 0; -} - -#define STATE_HDR() DEBUG_F("%p %2i ", op, Stack->EntryCount) - -/** - * \brief Execute a bytecode function with a stack - */ -int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, tBC_Stack *Stack, int ArgCount) -{ - int ret, ast_op, i; - tBC_Op *op; - tBC_StackEnt val1, val2; - int local_var_count = Fcn->BCFcn->MaxVariableCount; - tBC_StackEnt local_vars[local_var_count]; // Includes arguments - tSpiderValue tmpVal1, tmpVal2; // temp storage - tSpiderValue *pval1, *pval2, *ret_val; - tSpiderNamespace *default_namespace = &Script->Variant->RootNamespace; - - // Initialise local vars - for( i = 0; i < local_var_count; i ++ ) - local_vars[i].Type = ET_NULL; - - // Pop off arguments - if( ArgCount > Fcn->ArgumentCount ) return -1; - DEBUG_F("Fcn->ArgumentCount = %i\n", Fcn->ArgumentCount); - // - Handle optional arguments - for( i = Fcn->ArgumentCount; i > ArgCount; ) - { - i --; - local_vars[i].Integer = 0; - local_vars[i].Type = Fcn->Arguments[i].Type; - } - for( ; i --; ) - { - GET_STACKVAL(local_vars[i]); - // TODO: Type checks / enforcing - } - - // Mark the start - memset(&val1, 0, sizeof(val1)); - val1.Type = ET_FUNCTION_START; - PUT_STACKVAL(val1); - - // Execute! - op = Fcn->BCFcn->Operations; - while(op) - { - const char *opstr = ""; - tBC_Op *nextop = op->Next, *jmp_target; - ast_op = 0; - switch(op->Operation) - { - case BC_OP_NOP: - STATE_HDR(); - DEBUG_F("NOP\n"); - break; - // Jumps - case BC_OP_JUMP: - STATE_HDR(); - jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next; - DEBUG_F("JUMP #%i %p\n", OP_INDX(op), jmp_target); - nextop = jmp_target; - break; - case BC_OP_JUMPIF: - STATE_HDR(); - jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next; - DEBUG_F("JUMPIF #%i %p\n", OP_INDX(op), jmp_target); - GET_STACKVAL(val1); - if( Bytecode_int_IsStackEntTrue(&val1) ) - nextop = jmp_target; - break; - case BC_OP_JUMPIFNOT: - STATE_HDR(); - jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next; - DEBUG_F("JUMPIFNOT #%i %p\n", OP_INDX(op), jmp_target); - GET_STACKVAL(val1); - if( !Bytecode_int_IsStackEntTrue(&val1) ) - nextop = jmp_target; - break; - - // Define variables - case BC_OP_DEFINEVAR: { - int type, slot; - type = OP_INDX(op) & 0xFFFF; - slot = OP_INDX(op) >> 16; - if(slot < 0 || slot >= local_var_count) { - DEBUG_F("ERROR: slot %i out of range (max %i)\n", slot, local_var_count); - return -1; - } - STATE_HDR(); - DEBUG_F("DEFVAR %i of type %i\n", slot, type); - if( local_vars[slot].Type != ET_NULL ) { - Bytecode_int_DerefStackValue( &local_vars[slot] ); - local_vars[slot].Type = ET_NULL; - } - memset(&local_vars[slot], 0, sizeof(local_vars[0])); - local_vars[slot].Type = type; - } break; - - // Enter/Leave context - // - NOP now - case BC_OP_ENTERCONTEXT: - STATE_HDR(); - DEBUG_F("ENTERCONTEXT\n"); - break; - case BC_OP_LEAVECONTEXT: - STATE_HDR(); - DEBUG_F("LEAVECONTEXT\n"); - break; - - // Variables - case BC_OP_LOADVAR: { - int slot = OP_INDX(op); - STATE_HDR(); - DEBUG_F("LOADVAR %i ", slot); - if( slot < 0 || slot >= local_var_count ) { - AST_RuntimeError(NULL, "Loading from invalid slot %i", slot); - return -1; - } - DEBUG_F("("); PRINT_STACKVAL(local_vars[slot]); DEBUG_F(")\n"); - PUT_STACKVAL(local_vars[slot]); - Bytecode_int_RefStackValue( &local_vars[slot] ); - } break; - case BC_OP_SAVEVAR: { - int slot = OP_INDX(op); - STATE_HDR(); - DEBUG_F("SAVEVAR %i = ", slot); - if( slot < 0 || slot >= local_var_count ) { - AST_RuntimeError(NULL, "Loading from invalid slot %i", slot); - return -1; - } - // Remove whatever was in there before - DEBUG_F("[Deref "); PRINT_STACKVAL(local_vars[slot]); DEBUG_F("] "); - Bytecode_int_DerefStackValue( &local_vars[slot] ); - // Place new in - GET_STACKVAL(local_vars[slot]); - PRINT_STACKVAL(local_vars[slot]); - DEBUG_F("\n"); - } break; - - // Array index (get or set) - case BC_OP_INDEX: - case BC_OP_SETINDEX: - STATE_HDR(); - GET_STACKVAL(val1); // Index - // TODO: Check that index is an integer - if( val1.Type != SS_DATATYPE_INTEGER ) { - nextop = NULL; - break; - } - - // Get array as raw spider value - GET_STACKVAL(val2); // Array - pval1 = Bytecode_int_GetSpiderValue(&val2, &tmpVal1); - Bytecode_int_DerefStackValue(&val2); - - if( op->Operation == BC_OP_SETINDEX ) { - GET_STACKVAL(val2); - pval2 = Bytecode_int_GetSpiderValue(&val2, NULL); - Bytecode_int_DerefStackValue(&val2); - - DEBUG_F("SETINDEX %i ", val1.Integer); PRINT_STACKVAL(val2); DEBUG_F("\n"); - - ret_val = AST_ExecuteNode_Index(Script, NULL, pval1, val1.Integer, pval2); - if(ret_val == ERRPTR) { nextop = NULL; break; } - SpiderScript_DereferenceValue(pval2); - } - else { - DEBUG_F("INDEX %i ", val1.Integer); - ret_val = AST_ExecuteNode_Index(Script, NULL, pval1, val1.Integer, ERRPTR); - if(ret_val == ERRPTR) { nextop = NULL; break; } - - Bytecode_int_SetSpiderValue(&val1, ret_val); - SpiderScript_DereferenceValue(ret_val); - PUT_STACKVAL(val1); - - DEBUG_F("[Got "); PRINT_STACKVAL(val1); DEBUG_F("]\n"); - - } - // Dereference the array (or object, ...) - if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1); - break; - - // Object element (get or set) - case BC_OP_ELEMENT: - case BC_OP_SETELEMENT: - STATE_HDR(); - - GET_STACKVAL(val1); - // - Integers/Reals can't have elements :) - if( val1.Type != ET_REFERENCE ) { - nextop = NULL; - break; - } - - pval1 = Bytecode_int_GetSpiderValue(&val1, NULL); - Bytecode_int_DerefStackValue(&val1); - - if( op->Operation == BC_OP_SETELEMENT ) { - GET_STACKVAL(val2); - pval2 = Bytecode_int_GetSpiderValue(&val2, &tmpVal2); - Bytecode_int_DerefStackValue(&val2); - - DEBUG_F("SETELEMENT %s ", OP_STRING(op)); PRINT_STACKVAL(val2); DEBUG_F("\n"); - - ret_val = AST_ExecuteNode_Element(Script, NULL, pval1, OP_STRING(op), pval2); - if(ret_val == ERRPTR) { nextop = NULL; break; } - - if(pval2 != &tmpVal2) SpiderScript_DereferenceValue(pval2); - } - else { - DEBUG_F("ELEMENT %s ", OP_STRING(op)); - - ret_val = AST_ExecuteNode_Element(Script, NULL, pval1, OP_STRING(op), ERRPTR); - if(ret_val == ERRPTR) { nextop = NULL; break; } - - Bytecode_int_SetSpiderValue(&val2, ret_val); - SpiderScript_DereferenceValue(ret_val); - PUT_STACKVAL(val2); - - DEBUG_F("[Got "); PRINT_STACKVAL(val2); DEBUG_F("]\n"); - } - - SpiderScript_DereferenceValue(pval1); - break; - - // Constants: - case BC_OP_LOADINT: - STATE_HDR(); - DEBUG_F("LOADINT 0x%lx\n", op->Content.Integer); - val1.Type = SS_DATATYPE_INTEGER; - val1.Integer = op->Content.Integer; - PUT_STACKVAL(val1); - break; - case BC_OP_LOADREAL: - STATE_HDR(); - DEBUG_F("LOADREAL %lf\n", op->Content.Real); - val1.Type = SS_DATATYPE_REAL; - val1.Real = op->Content.Real; - PUT_STACKVAL(val1); - break; - case BC_OP_LOADSTR: - STATE_HDR(); - DEBUG_F("LOADSTR %i \"%s\"\n", OP_INDX(op), OP_STRING(op)); - val1.Type = SS_DATATYPE_STRING; - val1.Reference = SpiderScript_CreateString(OP_INDX(op), OP_STRING(op)); - PUT_STACKVAL(val1); - break; - case BC_OP_LOADNULL: - STATE_HDR(); - DEBUG_F("LOADNULL\n"); - val1.Type = ET_REFERENCE; - val1.Reference = NULL; - PUT_STACKVAL(val1); - break; - - case BC_OP_CAST: - STATE_HDR(); - val2.Type = OP_INDX(op); - DEBUG_F("CAST to %i\n", val2.Type); - GET_STACKVAL(val1); - if(val1.Type == val2.Type) { - PUT_STACKVAL(val1); - break; - } - if( val2.Type == SS_DATATYPE_INTEGER && val1.Type == SS_DATATYPE_REAL ) { - val2.Integer = val1.Real; - } - else if( val2.Type == SS_DATATYPE_REAL && val2.Type == SS_DATATYPE_INTEGER ) { - val2.Real = val1.Integer; - } - else { - pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1); - pval2 = SpiderScript_CastValueTo(val2.Type, pval1); - - Bytecode_int_SetSpiderValue(&val2, pval2); - SpiderScript_DereferenceValue(pval2); - - if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1); - Bytecode_int_DerefStackValue(&val1); -// printf("CAST (%x->%x) - Original %i references remaining\n", -// pval1->Type, OP_INDX(op), -// pval1->ReferenceCount); - } - PUT_STACKVAL(val2); - break; - - case BC_OP_DUPSTACK: - STATE_HDR(); - DEBUG_F("DUPSTACK "); - GET_STACKVAL(val1); - PRINT_STACKVAL(val1); - DEBUG_F("\n"); - PUT_STACKVAL(val1); - PUT_STACKVAL(val1); - Bytecode_int_RefStackValue(&val1); - break; - - // Discard the top item from the stack - case BC_OP_DELSTACK: - STATE_HDR(); - DEBUG_F("DELSTACK\n"); - GET_STACKVAL(val1); - break; - - // Unary Operations - case BC_OP_LOGICNOT: - STATE_HDR(); - DEBUG_F("LOGICNOT\n"); - - GET_STACKVAL(val1); - val2.Type = SS_DATATYPE_INTEGER; - val2.Integer = !Bytecode_int_IsStackEntTrue(&val1); - Bytecode_int_StackPush(Stack, &val2); - Bytecode_int_DerefStackValue(&val1); - break; - - case BC_OP_BITNOT: - if(!ast_op) ast_op = NODETYPE_BWNOT, opstr = "BITNOT"; - case BC_OP_NEG: - if(!ast_op) ast_op = NODETYPE_NEGATE, opstr = "NEG"; - - STATE_HDR(); - DEBUG_F("%s\n", opstr); - - GET_STACKVAL(val1); - pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1); - Bytecode_int_DerefStackValue(&val1); - - ret_val = AST_ExecuteNode_UniOp(Script, NULL, ast_op, pval1); - if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1); - Bytecode_int_SetSpiderValue(&val1, ret_val); - if(ret_val != &tmpVal1) SpiderScript_DereferenceValue(ret_val); - Bytecode_int_StackPush(Stack, &val1); - - break; - - // Binary Operations - case BC_OP_LOGICAND: - if(!ast_op) ast_op = NODETYPE_LOGICALAND, opstr = "LOGICAND"; - case BC_OP_LOGICOR: - if(!ast_op) ast_op = NODETYPE_LOGICALOR, opstr = "LOGICOR"; - case BC_OP_LOGICXOR: - if(!ast_op) ast_op = NODETYPE_LOGICALXOR, opstr = "LOGICXOR"; - - STATE_HDR(); - DEBUG_F("%s\n", opstr); - - GET_STACKVAL(val1); - GET_STACKVAL(val2); - - switch(op->Operation) - { - case BC_OP_LOGICAND: - i = Bytecode_int_IsStackEntTrue(&val1) && Bytecode_int_IsStackEntTrue(&val2); - break; - case BC_OP_LOGICOR: - i = Bytecode_int_IsStackEntTrue(&val1) || Bytecode_int_IsStackEntTrue(&val2); - break; - case BC_OP_LOGICXOR: - i = Bytecode_int_IsStackEntTrue(&val1) ^ Bytecode_int_IsStackEntTrue(&val2); - break; - } - Bytecode_int_DerefStackValue(&val1); - Bytecode_int_DerefStackValue(&val2); - - val1.Type = SS_DATATYPE_INTEGER; - val1.Integer = i; - Bytecode_int_StackPush(Stack, &val1); - break; - - case BC_OP_BITAND: - if(!ast_op) ast_op = NODETYPE_BWAND, opstr = "BITAND"; - case BC_OP_BITOR: - if(!ast_op) ast_op = NODETYPE_BWOR, opstr = "BITOR"; - case BC_OP_BITXOR: - if(!ast_op) ast_op = NODETYPE_BWXOR, opstr = "BITXOR"; - - case BC_OP_BITSHIFTLEFT: - if(!ast_op) ast_op = NODETYPE_BITSHIFTLEFT, opstr = "BITSHIFTLEFT"; - case BC_OP_BITSHIFTRIGHT: - if(!ast_op) ast_op = NODETYPE_BITSHIFTRIGHT, opstr = "BITSHIFTRIGHT"; - case BC_OP_BITROTATELEFT: - if(!ast_op) ast_op = NODETYPE_BITROTATELEFT, opstr = "BITROTATELEFT"; - - case BC_OP_ADD: - if(!ast_op) ast_op = NODETYPE_ADD, opstr = "ADD"; - case BC_OP_SUBTRACT: - if(!ast_op) ast_op = NODETYPE_SUBTRACT, opstr = "SUBTRACT"; - case BC_OP_MULTIPLY: - if(!ast_op) ast_op = NODETYPE_MULTIPLY, opstr = "MULTIPLY"; - case BC_OP_DIVIDE: - if(!ast_op) ast_op = NODETYPE_DIVIDE, opstr = "DIVIDE"; - case BC_OP_MODULO: - if(!ast_op) ast_op = NODETYPE_MODULO, opstr = "MODULO"; - - case BC_OP_EQUALS: - if(!ast_op) ast_op = NODETYPE_EQUALS, opstr = "EQUALS"; - case BC_OP_NOTEQUALS: - if(!ast_op) ast_op = NODETYPE_NOTEQUALS, opstr = "NOTEQUALS"; - case BC_OP_LESSTHAN: - if(!ast_op) ast_op = NODETYPE_LESSTHAN, opstr = "LESSTHAN"; - case BC_OP_LESSTHANOREQUAL: - if(!ast_op) ast_op = NODETYPE_LESSTHANEQUAL, opstr = "LESSTHANOREQUAL"; - case BC_OP_GREATERTHAN: - if(!ast_op) ast_op = NODETYPE_GREATERTHAN, opstr = "GREATERTHAN"; - case BC_OP_GREATERTHANOREQUAL: - if(!ast_op) ast_op = NODETYPE_GREATERTHANEQUAL, opstr = "GREATERTHANOREQUAL"; - - STATE_HDR(); - DEBUG_F("BINOP %i %s (bc %i)\n", ast_op, opstr, op->Operation); - - GET_STACKVAL(val2); // Right - GET_STACKVAL(val1); // Left - - DEBUG_F(" ("); PRINT_STACKVAL(val1); DEBUG_F(")"); - DEBUG_F(" ("); PRINT_STACKVAL(val2); DEBUG_F(")\n"); - - // Perform integer operations locally - if( val1.Type == SS_DATATYPE_INTEGER && val2.Type == SS_DATATYPE_INTEGER ) - { - if( Bytecode_int_LocalBinOp_Integer(op->Operation, &val1, &val2) ) { - nextop = NULL; - break; - } - PUT_STACKVAL(val1); - break; - } - - if(val1. Type == SS_DATATYPE_REAL && val2.Type == SS_DATATYPE_REAL ) - { - if( Bytecode_int_LocalBinOp_Real(op->Operation, &val1, &val2) ) { - nextop = NULL; - break; - } - PUT_STACKVAL(val1); - break; - } - - pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1); - pval2 = Bytecode_int_GetSpiderValue(&val2, &tmpVal2); - Bytecode_int_DerefStackValue(&val1); - Bytecode_int_DerefStackValue(&val2); - - // Hand to AST execution code - ret_val = AST_ExecuteNode_BinOp(Script, NULL, ast_op, pval1, pval2); - if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1); - if(pval2 != &tmpVal2) SpiderScript_DereferenceValue(pval2); - - if(ret_val == ERRPTR) { - AST_RuntimeError(NULL, "_BinOp returned ERRPTR"); - nextop = NULL; - break; - } - Bytecode_int_SetSpiderValue(&val1, ret_val); - if(ret_val != &tmpVal1) SpiderScript_DereferenceValue(ret_val); - PUT_STACKVAL(val1); - break; - - // Functions etc - case BC_OP_CREATEOBJ: - case BC_OP_CALLFUNCTION: - case BC_OP_CALLMETHOD: - STATE_HDR(); - - if( op->Operation == BC_OP_CALLFUNCTION ) - { - tScript_Function *fcn = NULL; - const char *name = OP_STRING(op); - int arg_count = OP_INDX(op); - DEBUG_F("CALL (local) %s %i args\n", name, arg_count); - // Check current script functions (for fast call) - for(fcn = Script->Functions; fcn; fcn = fcn->Next) - { - if(strcmp(name, fcn->Name) == 0) { - break; - } - } - if(fcn && fcn->BCFcn) - { - DEBUG_F(" - Fast call\n"); - Bytecode_int_ExecuteFunction(Script, fcn, Stack, arg_count); - break; - } - } - - // Slower call - if( Bytecode_int_CallExternFunction( Script, Stack, default_namespace, op ) ) { - nextop = NULL; - break; - } - break; - - case BC_OP_RETURN: - STATE_HDR(); - - DEBUG_F("RETURN\n"); - nextop = NULL; - break; - - default: - // TODO: - STATE_HDR(); - AST_RuntimeError(NULL, "Unknown operation %i\n", op->Operation); - nextop = NULL; - break; - } - op = nextop; - } - - // Clean up - // - Delete local vars - for( i = 0; i < local_var_count; i ++ ) - { - if( local_vars[i].Type != ET_NULL ) - { - DEBUG_F("Var %i - ", i); - PRINT_STACKVAL(local_vars[i]); - Bytecode_int_DerefStackValue(&local_vars[i]); - DEBUG_F("\n"); - } - else - DEBUG_F("Var %i - empty\n", i); - } - - // - Restore stack - if( Stack->Entries[Stack->EntryCount - 1].Type == ET_FUNCTION_START ) - Stack->EntryCount --; - else - { - int n_rolled = 1; - GET_STACKVAL(val1); - while( Stack->EntryCount && Stack->Entries[ --Stack->EntryCount ].Type != ET_FUNCTION_START ) - { - Bytecode_int_DerefStackValue( &Stack->Entries[Stack->EntryCount] ); - n_rolled ++; - } - PUT_STACKVAL(val1); - DEBUG_F("Rolled back %i entries\n", n_rolled); - } - - - return 0; -} - diff --git a/Usermode/Libraries/libspiderscript.so_src/exports.c b/Usermode/Libraries/libspiderscript.so_src/exports.c deleted file mode 100644 index edf64391..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/exports.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Acess2 - SpiderScript - * - Script Exports (Lang. Namespace) - */ -#define _GNU_SOURCE // HACK! -#include -#include -#include -#include - -// === PROTOTYPES === -tSpiderValue *Exports_sizeof(tSpiderScript *Script, int NArgs, tSpiderValue **Args); -tSpiderValue *Exports_array(tSpiderScript *Script, int NArgs, tSpiderValue **Args); -tSpiderValue *Exports_Lang_Strings_Split(tSpiderScript *Script, int NArgs, tSpiderValue **Args); -tSpiderValue *Exports_Lang_Struct(tSpiderScript *Script, int NArgs, tSpiderValue **Args); - -// === GLOBALS === -tSpiderFunction gExports_Lang_Strings_Split = { - .Name = "Split", - .Handler = Exports_Lang_Strings_Split, - .ReturnType = SS_MAKEARRAY(SS_DATATYPE_STRING), - .ArgTypes = {SS_DATATYPE_STRING, SS_DATATYPE_STRING, -1} -}; -tSpiderNamespace gExports_NS_Lang_Strings = { - .Name = "Strings", - .Functions = &gExports_Lang_Strings_Split - }; - -tSpiderFunction gExports_Lang_Struct = { - .Name = "Struct", - .Handler = Exports_Lang_Struct, - .ReturnType = SS_DATATYPE_OPAQUE, - .ArgTypes = {SS_DATATYPE_STRING, -1} -}; -// - Lang Namespace -tSpiderNamespace gExports_NS_Lang = { - .Name = "Lang", - .Functions = &gExports_Lang_Struct, - .FirstChild = &gExports_NS_Lang_Strings - }; -tSpiderNamespace gExportNamespaceRoot = { - .FirstChild = &gExports_NS_Lang -}; - -// -- Global Functions -tSpiderFunction gExports_array = { - .Next = NULL, - .Name = "array", - .Handler = Exports_array, - .ReturnType = SS_DATATYPE_DYNAMIC, - .ArgTypes = {SS_DATATYPE_INTEGER, -1} -}; -tSpiderFunction gExports_sizeof = { - .Next = &gExports_array, - .Name = "sizeof", - .Handler = Exports_sizeof, - .ReturnType = SS_DATATYPE_INTEGER, - .ArgTypes = {SS_DATATYPE_UNDEF, -1} -}; -tSpiderFunction *gpExports_First = &gExports_sizeof; - -// === CODE === -tSpiderValue *Exports_sizeof(tSpiderScript *Script, int NArgs, tSpiderValue **Args) -{ - if(NArgs != 1 || !Args[0]) return NULL; - - switch( Args[0]->Type ) - { - case SS_DATATYPE_STRING: - return SpiderScript_CreateInteger(Args[0]->String.Length); - case SS_DATATYPE_ARRAY: - return SpiderScript_CreateInteger(Args[0]->Array.Length); - default: - return NULL; - } -} - -tSpiderValue *Exports_array(tSpiderScript *Script, int NArgs, tSpiderValue **Args) -{ - if(NArgs != 2) return ERRPTR; - if(!Args[0] || !Args[1]) return ERRPTR; - - if(Args[0]->Type != SS_DATATYPE_INTEGER || Args[1]->Type != SS_DATATYPE_INTEGER) - return ERRPTR; - - int type = Args[1]->Integer; - int size = Args[0]->Integer; - - if( type != SS_DATATYPE_ARRAY ) - { - if( !SS_GETARRAYDEPTH(type) ) { - // ERROR - This should never happen - return ERRPTR; - } - type = SS_DOWNARRAY(type); - } - - return SpiderScript_CreateArray(type, size); -} - -tSpiderValue *Exports_Lang_Strings_Split(tSpiderScript *Script, int NArgs, tSpiderValue **Args) -{ - int len, ofs, slen; - void *haystack, *end; - int nSubStrs = 0; - tSpiderValue **strings = NULL; - tSpiderValue *ret; - - // Error checking - if( NArgs != 2 ) - return ERRPTR; - if( !Args[0] || !Args[1] ) - return ERRPTR; - if( Args[0]->Type != SS_DATATYPE_STRING ) - return ERRPTR; - if( Args[1]->Type != SS_DATATYPE_STRING ) - return ERRPTR; - - // Split the string - len = Args[0]->String.Length; - haystack = Args[0]->String.Data; - ofs = 0; - do { - end = memmem(haystack + ofs, len - ofs, Args[1]->String.Data, Args[1]->String.Length); - if( end ) - slen = end - (haystack + ofs); - else - slen = len - ofs; - - strings = realloc(strings, (nSubStrs+1)*sizeof(tSpiderValue*)); - strings[nSubStrs] = SpiderScript_CreateString(slen, haystack + ofs); - nSubStrs ++; - - ofs += slen + Args[1]->String.Length; - } while(end); - - // Create output array - ret = SpiderScript_CreateArray(SS_DATATYPE_STRING, nSubStrs); - memcpy(ret->Array.Items, strings, nSubStrs*sizeof(tSpiderValue*)); - free(strings); - - return ret; -} - -tSpiderValue *Exports_Lang_Struct(tSpiderScript *Script, int NArgs, tSpiderValue **Args) -{ - int i; - printf("Exports_Lang_Struct: (Script=%p, NArgs=%i, Args=%p)\n", Script, NArgs, Args); - - for( i = 0; i < NArgs; i ++ ) - { - printf(" Args[%i] = {Type: %i, ", i, Args[i]->Type); - switch(Args[i]->Type) - { - case SS_DATATYPE_INTEGER: - printf(" Integer: 0x%lx", Args[i]->Integer); - break; - case SS_DATATYPE_REAL: - printf(" Real: %f", Args[i]->Real); - break; - case SS_DATATYPE_STRING: - printf(" Length: %i, Data = '%s'", Args[i]->String.Length, Args[i]->String.Data); - break; - default: - break; - } - printf("}\n"); - } - - return NULL; -} diff --git a/Usermode/Libraries/libspiderscript.so_src/lex.c b/Usermode/Libraries/libspiderscript.so_src/lex.c deleted file mode 100644 index b659e34c..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/lex.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * SpiderScript - * - Script Lexer - */ -#include "tokens.h" -#include -#include -#include - -#define DEBUG 0 - -#define ARRAY_SIZE(x) ((sizeof(x))/(sizeof((x)[0]))) - -// === PROTOTYPES === - int is_ident(char ch); - int isdigit(int ch); - int isspace(int ch); - int GetToken(tParser *File); - -// === CONSTANTS === -const struct { - const int Value; - const char *Name; -} csaReservedWords[] = { - {TOK_RWD_FUNCTION, "function"}, - - {TOK_RWD_RETURN, "return"}, - {TOK_RWD_BREAK, "break"}, - {TOK_RWD_CONTINUE, "continue"}, - {TOK_RWD_NEW, "new"}, - - {TOK_RWD_IF, "if"}, - {TOK_RWD_ELSE, "else"}, - {TOK_RWD_DO, "do"}, - {TOK_RWD_WHILE, "while"}, - {TOK_RWD_FOR, "for"}, - - {TOK_RWD_NULL, "null"}, - {TOK_RWD_VOID, "void"}, - {TOK_RWD_OBJECT, "Object"}, - {TOK_RWD_OPAQUE, "Opaque"}, - {TOK_RWD_INTEGER, "Integer"}, - {TOK_RWD_REAL, "Real"}, - {TOK_RWD_STRING, "String"} -}; - -// === CODE === -/** - * \brief Read a token from a buffer - * \param File Parser state - */ -int GetToken(tParser *File) -{ - int ret; - - if( File->NextToken != -1 ) { - // Save Last - File->LastToken = File->Token; - File->LastTokenStr = File->TokenStr; - File->LastTokenLen = File->TokenLen; - File->LastLine = File->CurLine; - // Restore Next - File->Token = File->NextToken; - File->TokenStr = File->NextTokenStr; - File->TokenLen = File->NextTokenLen; - File->CurLine = File->NextLine; - // Set State - File->CurPos = File->TokenStr + File->TokenLen; - File->NextToken = -1; - { - char buf[ File->TokenLen + 1]; - memcpy(buf, File->TokenStr, File->TokenLen); - buf[File->TokenLen] = 0; - #if DEBUG - printf(" GetToken: FAST Return %i (%i long) (%s)\n", File->Token, File->TokenLen, buf); - #endif - } - return File->Token; - } - - //printf(" GetToken: File=%p, File->CurPos = %p\n", File, File->CurPos); - - // Clear whitespace (including comments) - for( ;; ) - { - // Whitespace - while( isspace( *File->CurPos ) ) - { - //printf("whitespace 0x%x, line = %i\n", *File->CurPos, File->CurLine); - if( *File->CurPos == '\n' ) - File->CurLine ++; - File->CurPos ++; - } - - // # Line Comments - if( *File->CurPos == '#' ) { - while( *File->CurPos && *File->CurPos != '\n' ) - File->CurPos ++; - continue ; - } - - // C-Style Line Comments - if( *File->CurPos == '/' && File->CurPos[1] == '/' ) { - while( *File->CurPos && *File->CurPos != '\n' ) - File->CurPos ++; - continue ; - } - - // C-Style Block Comments - if( *File->CurPos == '/' && File->CurPos[1] == '*' ) { - File->CurPos += 2; // Eat the '/*' - while( *File->CurPos && !(File->CurPos[-1] == '*' && *File->CurPos == '/') ) - { - if( *File->CurPos == '\n' ) File->CurLine ++; - File->CurPos ++; - } - File->CurPos ++; // Eat the '/' - continue ; - } - - // No more "whitespace" - break; - } - - // Save previous tokens (speeds up PutBack and LookAhead) - File->LastToken = File->Token; - File->LastTokenStr = File->TokenStr; - File->LastTokenLen = File->TokenLen; - File->LastLine = File->CurLine; - - // Read token - File->TokenStr = File->CurPos; - switch( *File->CurPos++ ) - { - case '\0': ret = TOK_EOF; break; - - // Operations - case '^': - if( *File->CurPos == '^' ) { - File->CurPos ++; - ret = TOK_LOGICXOR; - break; - } - ret = TOK_XOR; - break; - - case '|': - if( *File->CurPos == '|' ) { - File->CurPos ++; - ret = TOK_LOGICOR; - break; - } - ret = TOK_OR; - break; - - case '&': - if( *File->CurPos == '&' ) { - File->CurPos ++; - ret = TOK_LOGICAND; - break; - } - ret = TOK_AND; - break; - - case '/': - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_ASSIGN_DIV; - break; - } - ret = TOK_DIV; - break; - case '*': - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_ASSIGN_MUL; - break; - } - ret = TOK_MUL; - break; - case '+': - if( *File->CurPos == '+' ) { - File->CurPos ++; - ret = TOK_INCREMENT; - break; - } - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_ASSIGN_PLUS; - break; - } - ret = TOK_PLUS; - break; - case '-': - if( *File->CurPos == '-' ) { - File->CurPos ++; - ret = TOK_DECREMENT; - break; - } - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_ASSIGN_MINUS; - break; - } - if( *File->CurPos == '>' ) { - File->CurPos ++; - ret = TOK_ELEMENT; - break; - } - ret = TOK_MINUS; - break; - - // Strings - case '"': - while( *File->CurPos && !(*File->CurPos == '"' && *File->CurPos != '\\') ) - File->CurPos ++; - if( *File->CurPos ) - { - File->CurPos ++; - ret = TOK_STR; - } - else - ret = TOK_EOF; - break; - - // Brackets - case '(': ret = TOK_PAREN_OPEN; break; - case ')': ret = TOK_PAREN_CLOSE; break; - case '{': ret = TOK_BRACE_OPEN; break; - case '}': ret = TOK_BRACE_CLOSE; break; - case '[': ret = TOK_SQUARE_OPEN; break; - case ']': ret = TOK_SQUARE_CLOSE; break; - - // Core symbols - case ';': ret = TOK_SEMICOLON; break; - case ',': ret = TOK_COMMA; break; - #if USE_SCOPE_CHAR - case '.': ret = TOK_SCOPE; break; - #endif - - // Equals - case '=': - // Comparison Equals - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_EQUALS; - break; - } - // Assignment Equals - ret = TOK_ASSIGN; - break; - - // Less-Than - case '<': - // Less-Than or Equal - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_LTE; - break; - } - ret = TOK_LT; - break; - - // Greater-Than - case '>': - // Greater-Than or Equal - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_GTE; - break; - } - ret = TOK_GT; - break; - - // Logical NOT - case '!': - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_NOTEQUALS; - break; - } - ret = TOK_LOGICNOT; - break; - // Bitwise NOT - case '~': - ret = TOK_BWNOT; - break; - - // Variables - // \$[0-9]+ or \$[_a-zA-Z][_a-zA-Z0-9]* - case '$': - // Numeric Variable - if( isdigit( *File->CurPos ) ) { - while( isdigit(*File->CurPos) ) - File->CurPos ++; - } - // Ident Variable - else { - while( is_ident(*File->CurPos) || isdigit(*File->CurPos) ) - File->CurPos ++; - } - ret = TOK_VARIABLE; - break; - - // Default (Numbers and Identifiers) - default: - File->CurPos --; - - // Numbers - if( isdigit(*File->CurPos) ) - { - ret = TOK_INTEGER; - if( *File->CurPos == '0' && File->CurPos[1] == 'x' ) - { - File->CurPos += 2; - while(('0' <= *File->CurPos && *File->CurPos <= '9') - || ('A' <= *File->CurPos && *File->CurPos <= 'F') - || ('a' <= *File->CurPos && *File->CurPos <= 'f') ) - { - File->CurPos ++; - } - } - else - { - while( isdigit(*File->CurPos) ) - File->CurPos ++; - -// printf("*File->CurPos = '%c'\n", *File->CurPos); - - // Decimal - if( *File->CurPos == '.' ) - { - ret = TOK_REAL; - File->CurPos ++; - while( isdigit(*File->CurPos) ) - File->CurPos ++; - } - // Exponent - if( *File->CurPos == 'e' || *File->CurPos == 'E' ) - { - ret = TOK_REAL; - File->CurPos ++; - if(*File->CurPos == '-' || *File->CurPos == '+') - File->CurPos ++; - while( isdigit(*File->CurPos) ) - File->CurPos ++; - } - -// printf(" ret = %i\n", ret); - } - break; - } - - // Identifier - if( is_ident(*File->CurPos) ) - { - ret = TOK_IDENT; - - // Identifier - while( is_ident(*File->CurPos) || isdigit(*File->CurPos) ) - File->CurPos ++; - - // This is set later too, but we use it below - File->TokenLen = File->CurPos - File->TokenStr; - - // Check if it's a reserved word - { - char buf[File->TokenLen + 1]; - int i; - memcpy(buf, File->TokenStr, File->TokenLen); - buf[File->TokenLen] = 0; - for( i = 0; i < ARRAY_SIZE(csaReservedWords); i ++ ) - { - if(strcmp(csaReservedWords[i].Name, buf) == 0) { - ret = csaReservedWords[i].Value; - break ; - } - } - } - // If there's no match, just keep ret as TOK_IDENT - - break; - } - // Syntax Error - File->Token = TOK_INVAL; - - fprintf(stderr, "Syntax Error: Unknown symbol '%c'\n", *File->CurPos); - longjmp(File->JmpTarget, 1); - - break; - } - // Return - File->Token = ret; - File->TokenLen = File->CurPos - File->TokenStr; - - #if DEBUG - { - char buf[ File->TokenLen + 1]; - memcpy(buf, File->TokenStr, File->TokenLen); - buf[File->TokenLen] = 0; - //printf(" GetToken: File->CurPos = %p\n", File->CurPos); - printf(" GetToken: Return %i (%i long) (%s)\n", ret, File->TokenLen, buf); - } - #endif - return ret; -} - -void PutBack(tParser *File) -{ - if( File->LastToken == -1 ) { - // ERROR: - fprintf(stderr, "INTERNAL ERROR: Putback when LastToken==-1\n"); - longjmp( File->JmpTarget, -1 ); - return ; - } - #if DEBUG - printf(" PutBack: Was on %i\n", File->Token); - #endif - // Save - File->NextLine = File->CurLine; - File->NextToken = File->Token; - File->NextTokenStr = File->TokenStr; - File->NextTokenLen = File->TokenLen; - // Restore - File->CurLine = File->LastLine; - File->Token = File->LastToken; - File->TokenStr = File->LastTokenStr; - File->TokenLen = File->LastTokenLen; - File->CurPos = File->NextTokenStr; - // Invalidate - File->LastToken = -1; -} - -int LookAhead(tParser *File) -{ - // TODO: Should I save the entire state here? - int ret = GetToken(File); - PutBack(File); - return ret; -} - -// --- Helpers --- -/** - * \brief Check for ident characters - * \note Matches Regex [a-zA-Z_] - */ -int is_ident(char ch) -{ - if('a' <= ch && ch <= 'z') return 1; - if('A' <= ch && ch <= 'Z') return 1; - if(ch == '_') return 1; - #if !USE_SCOPE_CHAR - if(ch == '.') return 1; - #endif - if(ch < 0) return 1; - return 0; -} - -int isdigit(int ch) -{ - if('0' <= ch && ch <= '9') return 1; - return 0; -} - -int isspace(int ch) -{ - if(' ' == ch) return 1; - if('\t' == ch) return 1; - if('\b' == ch) return 1; - if('\n' == ch) return 1; - if('\r' == ch) return 1; - return 0; -} diff --git a/Usermode/Libraries/libspiderscript.so_src/main.c b/Usermode/Libraries/libspiderscript.so_src/main.c deleted file mode 100644 index 17f5a3c1..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/main.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Acess2 - SpiderScript - * Interpreter Library - */ -#include -#include -#include -#include -#include "common.h" -#include "ast.h" -#include "bytecode_gen.h" - -// === IMPORTS === -extern int Parse_Buffer(tSpiderScript *Script, const char *Buffer, const char *Filename); -extern tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name); -extern void Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value); -extern void Variable_Destroy(tAST_Variable *Variable); - -// === CODE === -/** - * \brief Library Entry Point - */ -int SoMain() -{ - return 0; -} - -/** - * \brief Parse a script - */ -tSpiderScript *SpiderScript_ParseFile(tSpiderVariant *Variant, const char *Filename) -{ - char *data; - int fLen; - FILE *fp; - tSpiderScript *ret; - - fp = fopen(Filename, "r"); - if( !fp ) { - return NULL; - } - - fseek(fp, 0, SEEK_END); - fLen = ftell(fp); - fseek(fp, 0, SEEK_SET); - - // Allocate and read data - data = malloc(fLen + 1); - if(!data) return NULL; - fLen = fread(data, 1, fLen, fp); - fclose(fp); - if( fLen < 0 ) { - free(data); - return NULL; - } - data[fLen] = '\0'; - - - // Create the script - ret = malloc(sizeof(tSpiderScript)); - ret->Variant = Variant; - ret->Functions = NULL; - ret->LastFunction = NULL; - - ret->CurNamespace = NULL; - if( Parse_Buffer(ret, data, Filename) ) { - free(data); - free(ret); - return NULL; - } - - free(data); - - - // HACK!! - #if 1 - // - Save AST to a file - { - char cacheFilename[strlen(Filename)+6+1]; - strcpy(cacheFilename, Filename); - strcat(cacheFilename, ".ast"); - - SpiderScript_SaveAST(ret, cacheFilename); - } - #endif - // - Save Bytecode too - { - char cacheFilename[strlen(Filename)+6+1]; - strcpy(cacheFilename, Filename); - strcat(cacheFilename, ".bc"); - - SpiderScript_SaveBytecode(ret, cacheFilename); - } - - return ret; -} - -int SpiderScript_SaveAST(tSpiderScript *Script, const char *Filename) -{ - size_t size; - FILE *fp; - void *data; - - size = AST_WriteScript(NULL, Script); - - fp = fopen(Filename, "wb"); - if(!fp) return 1; - - data = malloc(size); - if(!data) { - fclose(fp); - return -1; - } - - size = AST_WriteScript(data, Script); - fwrite(data, size, 1, fp); - free(data); - - fclose(fp); - return 0; -} - -/** - * \brief Free a script - */ -void SpiderScript_Free(tSpiderScript *Script) -{ - tScript_Function *fcn = Script->Functions; - tScript_Function *nextFcn; - - // Free functions - while(fcn) - { - if(fcn->ASTFcn) AST_FreeNode( fcn->ASTFcn ); - if(fcn->BCFcn) Bytecode_DeleteFunction( fcn->BCFcn ); - - nextFcn = fcn->Next; - free( fcn ); - fcn = nextFcn; - } - - free(Script); -} diff --git a/Usermode/Libraries/libspiderscript.so_src/parse.c b/Usermode/Libraries/libspiderscript.so_src/parse.c deleted file mode 100644 index 45eafb2b..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/parse.c +++ /dev/null @@ -1,1130 +0,0 @@ -/* - * Acess2 - SpiderScript - * - Parser - */ -#include -#include -#include -#include -#include -#define WANT_TOKEN_STRINGS 1 -#include "tokens.h" -#include "ast.h" -#include "common.h" - -#define DEBUG 0 -#define SUPPORT_BREAK_TAGS 1 - -// === PROTOTYPES === - int Parse_Buffer(tSpiderScript *Script, const char *Buffer, const char *Filename); -void *Parse_FunctionDefinition(tSpiderScript *Script, tParser *Parser, int Type); -tAST_Node *Parse_DoCodeBlock(tParser *Parser, tAST_Node *CodeNode); -tAST_Node *Parse_DoBlockLine(tParser *Parser, tAST_Node *CodeNode); -tAST_Node *Parse_VarDefList(tParser *Parser, tAST_Node *CodeNode, int Type); -tAST_Node *Parse_GetVarDef(tParser *Parser, int Type); - -tAST_Node *Parse_DoExpr0(tParser *Parser); // Assignment -tAST_Node *Parse_DoExpr1(tParser *Parser); // Boolean Operators -tAST_Node *Parse_DoExpr2(tParser *Parser); // Comparison Operators -tAST_Node *Parse_DoExpr3(tParser *Parser); // Bitwise Operators -tAST_Node *Parse_DoExpr4(tParser *Parser); // Bit Shifts -tAST_Node *Parse_DoExpr5(tParser *Parser); // Arithmatic -tAST_Node *Parse_DoExpr6(tParser *Parser); // Mult & Div -tAST_Node *Parse_DoExpr7(tParser *Parser); // Right Unary Operations -tAST_Node *Parse_DoExpr8(tParser *Parser); // Left Unary Operations - -tAST_Node *Parse_DoParen(tParser *Parser); // Parenthesis (Always Last) -tAST_Node *Parse_DoValue(tParser *Parser); // Values - -tAST_Node *Parse_GetString(tParser *Parser); -tAST_Node *Parse_GetNumeric(tParser *Parser); -tAST_Node *Parse_GetVariable(tParser *Parser); -tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate); - -void SyntaxAssert(tParser *Parser, int Have, int Want); -void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...); - -#if 0 -#define SyntaxAssert(_parser, _have, _want) SyntaxAssertV(_parser, _have, _want, NULL) -#define SyntaxAssertV(_parser, _have, _want, _rv) do { \ - int have = (_have), want = (_want); \ - if( (have) != (want) ) { \ - SyntaxError(Parser, 1, "Unexpected %s(%i), expecting %s(%i)\n", \ - csaTOKEN_NAMES[have], have, csaTOKEN_NAMES[want], want); \ - return _rv; \ - } \ -}while(0) -#endif - -#define TODO(Parser, message...) do {\ - fprintf(stderr, "TODO: "message);\ - longjmp(Parser->JmpTarget, -1);\ -}while(0) - -// === CODE === -/** - * \brief Parse a buffer into a syntax tree - */ -int Parse_Buffer(tSpiderScript *Script, const char *Buffer, const char *Filename) -{ - tParser parser = {0}; - tParser *Parser = &parser; //< Keeps code consistent - tAST_Node *mainCode, *node; - int type; - tScript_Function *fcn; - - #if DEBUG >= 2 - printf("Parse_Buffer: (Variant=%p, Buffer=%p)\n", Variant, Buffer); - #endif - - // Initialise parser - parser.LastToken = -1; - parser.NextToken = -1; - parser.CurLine = 1; - parser.BufStart = Buffer; - parser.CurPos = Buffer; - // hackery to do reference counting - parser.Filename = malloc(sizeof(int)+strlen(Filename)+1); - strcpy(parser.Filename + sizeof(int), Filename); - *(int*)(parser.Filename) = 0; // Set reference count - parser.Filename += sizeof(int); // Move filename - parser.ErrorHit = 0; - parser.Variant = Script->Variant; - - mainCode = AST_NewCodeBlock(&parser); - - // Give us an error fallback - if( setjmp( parser.JmpTarget ) != 0 ) - { - AST_FreeNode( mainCode ); - - for(fcn = Script->Functions; fcn; ) - { - tScript_Function *nextFcn; - - AST_FreeNode( fcn->ASTFcn ); - - nextFcn = fcn->Next; - free( fcn ); - fcn = nextFcn; - } - return -1; - } - - // Parse the file! - while(Parser->Token != TOK_EOF) - { - switch( GetToken(Parser) ) - { - case TOK_EOF: - break; - - // Typed variables/functions - case TOKEN_GROUP_TYPES: - TOKEN_GET_DATATYPE(type, Parser->Token); - - switch(LookAhead(Parser)) - { - // Define a function (pass on to the other function definition code) - case TOK_IDENT: - if( Parse_FunctionDefinition(Script, Parser, type) == NULL ) - longjmp(Parser->JmpTarget, -1); - break ; - // Define a variable (pass back to _DoBlockLine) - case TOK_VARIABLE: - node = Parse_VarDefList(Parser, mainCode, type); - AST_AppendNode(mainCode, node); - SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON); - break; - default: - SyntaxError(Parser, 1, "Unexpected %s, expected TOK_IDENT or TOK_VARIABLE\n", - csaTOKEN_NAMES[Parser->Token]); - break; - } - break; - - // Define a function - case TOK_RWD_FUNCTION: - if( !Script->Variant->bDyamicTyped ) { - SyntaxError(Parser, 1, "Dynamic functions are invalid in static mode"); - longjmp(Parser->JmpTarget, -1); - } - - type = SS_DATATYPE_DYNAMIC; - - if( Parse_FunctionDefinition(Script, Parser, SS_DATATYPE_DYNAMIC) == NULL ) - longjmp(Parser->JmpTarget, -1); - - break; - - // Ordinary Statement - default: - PutBack(Parser); - node = Parse_DoBlockLine(Parser, mainCode); - if(!node) longjmp(Parser->JmpTarget, -1); - AST_AppendNode( mainCode, node ); - break; - } - - // Jump to error handler on error - if(Parser->ErrorHit) - longjmp(Parser->JmpTarget, -1); - } - - AST_AppendFunction( Script, "", SS_DATATYPE_INTEGER, NULL, mainCode ); - - //printf("---- %p parsed as SpiderScript ----\n", Buffer); - - return 0; -} - -void *Parse_FunctionDefinition(tSpiderScript *Script, tParser *Parser, int Type) -{ - char *name; - int rv; - tAST_Node *first_arg, *last_arg, *code; - - last_arg = (void*)&first_arg; // HACK - - SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT ); - - name = strndup( Parser->TokenStr, Parser->TokenLen ); - #if DEBUG - printf("DefFCN %s\n", name); - #endif - - // Get arguments - SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN ); - if( LookAhead(Parser) != TOK_PAREN_CLOSE ) - { - do { - int type = SS_DATATYPE_DYNAMIC; - GetToken(Parser); - // Non dynamic typed variants must use data types - if( !Script->Variant->bDyamicTyped ) { - TOKEN_GET_DATATYPE(type, Parser->Token); - GetToken(Parser); - } - last_arg->NextSibling = Parse_GetVarDef(Parser, type); - last_arg = last_arg->NextSibling; - last_arg->NextSibling = NULL; - } while(GetToken(Parser) == TOK_COMMA); - } - else - GetToken(Parser); - SyntaxAssert(Parser, Parser->Token, TOK_PAREN_CLOSE ); - - code = Parse_DoCodeBlock(Parser, NULL); - - rv = AST_AppendFunction( Script, name, Type, first_arg, code ); - - // Clean up argument definition nodes - { - tAST_Node *nextarg; - for( ; first_arg; first_arg = nextarg ) - { - nextarg = first_arg->NextSibling; - AST_FreeNode(first_arg); - } - } - - free(name); - - return rv == 0 ? (void*)1 : NULL; -} - -/** - * \brief Parse a block of code surrounded by { } - */ -tAST_Node *Parse_DoCodeBlock(tParser *Parser, tAST_Node *CodeNode) -{ - tAST_Node *ret; - - // Check if we are being called for a one-liner - if( GetToken(Parser) != TOK_BRACE_OPEN ) { - PutBack(Parser); - return Parse_DoBlockLine(Parser, CodeNode); - } - - ret = AST_NewCodeBlock(Parser); - - while( LookAhead(Parser) != TOK_BRACE_CLOSE ) - { - tAST_Node *node = Parse_DoBlockLine(Parser, ret); - if(!node) { - AST_FreeNode(ret); - return NULL; - } - AST_AppendNode( ret, node ); - } - GetToken(Parser); // Omnomnom - return ret; -} - -/** - * \brief Parse a line in a block - */ -tAST_Node *Parse_DoBlockLine(tParser *Parser, tAST_Node *CodeNode) -{ - tAST_Node *ret; - - //printf("Parse_DoBlockLine: Line %i\n", Parser->CurLine); - - switch(LookAhead(Parser)) - { - // New block - case TOK_BRACE_OPEN: - return Parse_DoCodeBlock(Parser, CodeNode); - - // Empty statement - case TOK_SEMICOLON: - GetToken(Parser); - return NULL; - - // Return from a method - case TOK_RWD_RETURN: - GetToken(Parser); - ret = AST_NewUniOp(Parser, NODETYPE_RETURN, Parse_DoExpr0(Parser)); - break; - - // Break / Continue (end a loop / go to next iteration) - case TOK_RWD_CONTINUE: - case TOK_RWD_BREAK: - { - int tok; - char *ident = NULL; - tok = GetToken(Parser); - // Get the number of nesting levels to break - if(LookAhead(Parser) == TOK_IDENT) - { - GetToken(Parser); - ident = strndup(Parser->TokenStr, Parser->TokenLen); - } - // Get the action - switch(tok) - { - case TOK_RWD_BREAK: ret = AST_NewBreakout(Parser, NODETYPE_BREAK, ident); break; - case TOK_RWD_CONTINUE: ret = AST_NewBreakout(Parser, NODETYPE_CONTINUE, ident); break; - default: - SyntaxError(Parser, 1, "BUG Unhandled break/continue (%s)", - csaTOKEN_NAMES[tok]); - return NULL; - } - if(ident) free(ident); - } - break; - - // Control Statements - case TOK_RWD_IF: - { - tAST_Node *cond, *true, *false = NULL; - GetToken(Parser); // eat the if - - SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN); - cond = Parse_DoExpr0(Parser); // Get condition - SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE); - true = Parse_DoCodeBlock(Parser, CodeNode); - if( LookAhead(Parser) == TOK_RWD_ELSE ) { - GetToken(Parser); - false = Parse_DoCodeBlock(Parser, CodeNode); - } - else - false = AST_NewNop(Parser); - ret = AST_NewIf(Parser, cond, true, false); - } - return ret; - - case TOK_RWD_FOR: - { - char *tag = NULL; - tAST_Node *init=NULL, *cond=NULL, *inc=NULL, *code; - GetToken(Parser); // Eat 'for' - - #if SUPPORT_BREAK_TAGS - if(LookAhead(Parser) == TOK_LT) - { - GetToken(Parser); - SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT); - tag = strndup(Parser->TokenStr, Parser->TokenLen); - SyntaxAssert(Parser, GetToken(Parser), TOK_GT); - } - #endif - - SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN); - - if(LookAhead(Parser) != TOK_SEMICOLON) - init = Parse_DoExpr0(Parser); - - SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON); - - if(LookAhead(Parser) != TOK_SEMICOLON) - cond = Parse_DoExpr0(Parser); - - SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON); - - if(LookAhead(Parser) != TOK_PAREN_CLOSE) - inc = Parse_DoExpr0(Parser); - - SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE); - - code = Parse_DoCodeBlock(Parser, CodeNode); - ret = AST_NewLoop(Parser, tag, init, 0, cond, inc, code); - if(tag) free(tag); - } - return ret; - - case TOK_RWD_DO: - { - const char *tag = ""; - tAST_Node *code, *cond; - GetToken(Parser); // Eat 'do' - - #if SUPPORT_BREAK_TAGS - if(LookAhead(Parser) == TOK_LT) - { - GetToken(Parser); - SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT); - tag = strndup(Parser->TokenStr, Parser->TokenLen); - SyntaxAssert(Parser, GetToken(Parser), TOK_GT); - } - #endif - - code = Parse_DoCodeBlock(Parser, CodeNode); - SyntaxAssert( Parser, GetToken(Parser), TOK_RWD_WHILE ); - SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN ); - cond = Parse_DoExpr0(Parser); - SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE ); - ret = AST_NewLoop(Parser, tag, AST_NewNop(Parser), 1, cond, AST_NewNop(Parser), code); - } - break; - case TOK_RWD_WHILE: - { - const char *tag = ""; - tAST_Node *code, *cond; - GetToken(Parser); // Eat 'while' - - #if SUPPORT_BREAK_TAGS - if(LookAhead(Parser) == TOK_LT) - { - GetToken(Parser); - SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT); - tag = strndup(Parser->TokenStr, Parser->TokenLen); - SyntaxAssert(Parser, GetToken(Parser), TOK_GT); - } - #endif - - SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN ); - cond = Parse_DoExpr0(Parser); - SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE ); - code = Parse_DoCodeBlock(Parser, CodeNode); - ret = AST_NewLoop(Parser, tag, AST_NewNop(Parser), 0, cond, AST_NewNop(Parser), code); - } - return ret; - - // Define Variables - case TOKEN_GROUP_TYPES: - { - int type; - GetToken(Parser); - TOKEN_GET_DATATYPE(type, Parser->Token); - ret = Parse_VarDefList(Parser, CodeNode, type); - } - break; - - // Default - default: - //printf("exp0\n"); - ret = Parse_DoExpr0(Parser); - break; - } - - SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON ); - return ret; -} - -tAST_Node *Parse_VarDefList(tParser *Parser, tAST_Node *CodeNode, int Type) -{ - tAST_Node *ret; - - ret = NULL; - do { - if(ret) AST_AppendNode( CodeNode, ret ); - SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE); - - ret = Parse_GetVarDef(Parser, Type); - if(!ret) longjmp(Parser->JmpTarget, -1); - } while(GetToken(Parser) == TOK_COMMA); - PutBack(Parser); // Semicolon is checked by caller - - return ret; -} - -/** - * \brief Get a variable definition - */ -tAST_Node *Parse_GetVarDef(tParser *Parser, int Type) -{ - char name[Parser->TokenLen]; - tAST_Node *ret; - int level; - - SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE); - - // copy the name (trimming the $) - memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1); - name[Parser->TokenLen-1] = 0; - - // Define the variable - ret = AST_NewDefineVar(Parser, Type, name); - // Handle arrays - level = 0; - if( LookAhead(Parser) == TOK_SQUARE_OPEN ) - { - GetToken(Parser); - if( LookAhead(Parser) != TOK_SQUARE_CLOSE ) - { - ret->DefVar.InitialValue = AST_NewFunctionCall(Parser, "array"); - AST_AppendFunctionCallArg(ret->DefVar.InitialValue, Parse_DoExpr0(Parser)); - } - SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE); - - level ++; - } - while( LookAhead(Parser) == TOK_SQUARE_OPEN ) - { - GetToken(Parser); - SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE); - level ++; - } - - // Maul the type to denote the dereference level - if( Parser->Variant->bDyamicTyped ) { - ret->DefVar.DataType = SS_DATATYPE_ARRAY; - } - else { - ret->DefVar.DataType |= (level << 16); - } - - // Initial value - if( LookAhead(Parser) == TOK_ASSIGN ) - { - if( ret->DefVar.InitialValue ) - { - SyntaxError(Parser, 1, "Cannot assign and set array size at the same time"); - } - GetToken(Parser); - ret->DefVar.InitialValue = Parse_DoExpr0(Parser); - if(!ret->DefVar.InitialValue) { - AST_FreeNode(ret); - return NULL; - } - } - else if( ret->DefVar.InitialValue ) - { - AST_AppendFunctionCallArg(ret->DefVar.InitialValue, AST_NewInteger(Parser, ret->DefVar.DataType)); - } - - return ret; -} - -/** - * \brief Assignment Operations - */ -tAST_Node *Parse_DoExpr0(tParser *Parser) -{ - #define _next Parse_DoExpr1 - tAST_Node *ret = _next(Parser); - int cont = 1; - - while( cont ) - { - // Check Assignment - switch(GetToken(Parser)) - { - case TOK_ASSIGN: - ret = AST_NewAssign(Parser, NODETYPE_NOP, ret, _next(Parser)); - break; - case TOK_ASSIGN_DIV: - ret = AST_NewAssign(Parser, NODETYPE_DIVIDE, ret, _next(Parser)); - break; - case TOK_ASSIGN_MUL: - ret = AST_NewAssign(Parser, NODETYPE_MULTIPLY, ret, _next(Parser)); - break; - case TOK_ASSIGN_PLUS: - ret = AST_NewAssign(Parser, NODETYPE_ADD, ret, _next(Parser)); - break; - case TOK_ASSIGN_MINUS: - ret = AST_NewAssign(Parser, NODETYPE_SUBTRACT, ret, _next(Parser)); - break; - default: - #if DEBUG >= 2 - printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token); - #endif - PutBack(Parser); - cont = 0; - break; - } - } - return ret; - #undef _next -} - -/** - * \brief Logical/Boolean Operators - */ -tAST_Node *Parse_DoExpr1(tParser *Parser) -{ - #define _next Parse_DoExpr2 - tAST_Node *ret = _next(Parser); - int cont = 1; - - while( cont ) - { - switch(GetToken(Parser)) - { - case TOK_LOGICAND: - ret = AST_NewBinOp(Parser, NODETYPE_LOGICALAND, ret, _next(Parser)); - break; - case TOK_LOGICOR: - ret = AST_NewBinOp(Parser, NODETYPE_LOGICALOR, ret, _next(Parser)); - break; - case TOK_LOGICXOR: - ret = AST_NewBinOp(Parser, NODETYPE_LOGICALXOR, ret, _next(Parser)); - break; - default: - PutBack(Parser); - cont = 0; - break; - } - } - return ret; - #undef _next -} - -// -------------------- -// Expression 2 - Comparison Operators -// -------------------- -tAST_Node *Parse_DoExpr2(tParser *Parser) -{ - #define _next Parse_DoExpr3 - tAST_Node *ret = _next(Parser); - int cont = 1; - - while( cont ) - { - // Check token - switch(GetToken(Parser)) - { - case TOK_EQUALS: - ret = AST_NewBinOp(Parser, NODETYPE_EQUALS, ret, _next(Parser)); - break; - case TOK_NOTEQUALS: - ret = AST_NewBinOp(Parser, NODETYPE_NOTEQUALS, ret, _next(Parser)); - break; - case TOK_LT: - ret = AST_NewBinOp(Parser, NODETYPE_LESSTHAN, ret, _next(Parser)); - break; - case TOK_GT: - ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, _next(Parser)); - break; - case TOK_LTE: - ret = AST_NewBinOp(Parser, NODETYPE_LESSTHANEQUAL, ret, _next(Parser)); - break; - case TOK_GTE: - ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHANEQUAL, ret, _next(Parser)); - break; - default: - PutBack(Parser); - cont = 0; - break; - } - } - return ret; - #undef _next -} - -/** - * \brief Bitwise Operations - */ -tAST_Node *Parse_DoExpr3(tParser *Parser) -{ - #define _next Parse_DoExpr4 - tAST_Node *ret = _next(Parser); - int cont = 1; - - while( cont ) - { - // Check Token - switch(GetToken(Parser)) - { - case TOK_OR: - ret = AST_NewBinOp(Parser, NODETYPE_BWOR, ret, _next(Parser)); - break; - case TOK_AND: - ret = AST_NewBinOp(Parser, NODETYPE_BWAND, ret, _next(Parser)); - break; - case TOK_XOR: - ret = AST_NewBinOp(Parser, NODETYPE_BWXOR, ret, _next(Parser)); - break; - default: - PutBack(Parser); - cont = 0; - break; - } - } - return ret; - #undef _next -} - -// -------------------- -// Expression 4 - Shifts -// -------------------- -tAST_Node *Parse_DoExpr4(tParser *Parser) -{ - #define _next Parse_DoExpr5 - tAST_Node *ret = _next(Parser); - int cont = 1; - - while( cont ) - { - switch(GetToken(Parser)) - { - case TOK_SHL: - ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTLEFT, ret, _next(Parser)); - break; - case TOK_SHR: - ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTRIGHT, ret, _next(Parser)); - break; - default: - PutBack(Parser); - cont = 0; - break; - } - } - - return ret; - #undef _next -} - -// -------------------- -// Expression 5 - Arithmatic -// -------------------- -tAST_Node *Parse_DoExpr5(tParser *Parser) -{ - #define _next Parse_DoExpr6 - tAST_Node *ret = _next(Parser); - int cont = 1; - - // While loop is added to ensure that the evaluation order ends up as - // right to left. - // E.g. a + b + c + d ends up as (((a + b) + c) + d) for casting - while( cont ) - { - switch(GetToken(Parser)) - { - case TOK_PLUS: - ret = AST_NewBinOp(Parser, NODETYPE_ADD, ret, _next(Parser)); - break; - case TOK_MINUS: - ret = AST_NewBinOp(Parser, NODETYPE_SUBTRACT, ret, _next(Parser)); - break; - default: - PutBack(Parser); - cont = 0; - break; - } - } - - return ret; - #undef _next -} - -// -------------------- -// Expression 6 - Multiplcation & Division -// -------------------- -tAST_Node *Parse_DoExpr6(tParser *Parser) -{ - #define _next Parse_DoExpr7 - tAST_Node *ret = _next(Parser); - int cont = 1; - - while( cont ) - { - switch(GetToken(Parser)) - { - case TOK_MUL: - ret = AST_NewBinOp(Parser, NODETYPE_MULTIPLY, ret, _next(Parser)); - break; - case TOK_DIV: - ret = AST_NewBinOp(Parser, NODETYPE_DIVIDE, ret, _next(Parser)); - break; - default: - PutBack(Parser); - cont = 0; - break; - } - } - - return ret; - #undef _next -} - -// -------------------- -// Expression 7 - Right Unary Operations -// -------------------- -tAST_Node *Parse_DoExpr7(tParser *Parser) -{ - tAST_Node *ret = Parse_DoExpr8(Parser); - - switch(GetToken(Parser)) - { - case TOK_INCREMENT: - ret = AST_NewUniOp(Parser, NODETYPE_POSTINC, ret); - break; - case TOK_DECREMENT: - ret = AST_NewUniOp(Parser, NODETYPE_POSTDEC, ret); - break; - default: - PutBack(Parser); - break; - } - return ret; -} - -// -------------------- -// Expression 8 - Left Unary Operations -// -------------------- -tAST_Node *Parse_DoExpr8(tParser *Parser) -{ - switch(GetToken(Parser)) - { - case TOK_INCREMENT: - return AST_NewAssign(Parser, NODETYPE_ADD, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1)); - case TOK_DECREMENT: - return AST_NewAssign(Parser, NODETYPE_SUBTRACT, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1)); - case TOK_MINUS: - return AST_NewUniOp(Parser, NODETYPE_NEGATE, Parse_DoExpr8(Parser)); - case TOK_LOGICNOT: - return AST_NewUniOp(Parser, NODETYPE_LOGICALNOT, Parse_DoExpr8(Parser)); - case TOK_BWNOT: - return AST_NewUniOp(Parser, NODETYPE_BWNOT, Parse_DoExpr8(Parser)); - default: - PutBack(Parser); - return Parse_DoParen(Parser); - } -} - -// -------------------- -// 2nd Last Expression - Parens -// -------------------- -tAST_Node *Parse_DoParen(tParser *Parser) -{ - #if DEBUG >= 2 - printf("Parse_DoParen: (Parser=%p)\n", Parser); - #endif - if(LookAhead(Parser) == TOK_PAREN_OPEN) - { - tAST_Node *ret; - int type; - GetToken(Parser); - - // TODO: Handle casts here - switch(LookAhead(Parser)) - { - case TOKEN_GROUP_TYPES: - GetToken(Parser); - TOKEN_GET_DATATYPE(type, Parser->Token); - SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE); - ret = AST_NewCast(Parser, type, Parse_DoParen(Parser)); - break; - default: - ret = Parse_DoExpr0(Parser); - SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE); - break; - } - return ret; - } - else - return Parse_DoValue(Parser); -} - -// -------------------- -// Last Expression - Value -// -------------------- -tAST_Node *Parse_DoValue(tParser *Parser) -{ - int tok = LookAhead(Parser); - - #if DEBUG >= 2 - printf("Parse_DoValue: tok = %i\n", tok); - #endif - - switch(tok) - { - case TOK_STR: - return Parse_GetString(Parser); - case TOK_INTEGER: - return Parse_GetNumeric(Parser); - - case TOK_REAL: - GetToken(Parser); - return AST_NewReal( Parser, atof(Parser->TokenStr) ); - - case TOK_IDENT: - return Parse_GetIdent(Parser, 0); - case TOK_VARIABLE: - return Parse_GetVariable(Parser); - case TOK_RWD_NULL: - GetToken(Parser); - return AST_NewNull(Parser); // nODETYPE_NOP returns NULL - case TOK_RWD_NEW: - GetToken(Parser); - return Parse_GetIdent(Parser, 1); - - default: - fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n", - csaTOKEN_NAMES[tok], Parser->CurLine); - longjmp( Parser->JmpTarget, -1 ); - } -} - -/** - * \brief Get a string - */ -tAST_Node *Parse_GetString(tParser *Parser) -{ - tAST_Node *ret; - int i, j; - GetToken( Parser ); - - { - char data[ Parser->TokenLen - 2 ]; - j = 0; - - for( i = 1; i < Parser->TokenLen - 1; i++ ) - { - if( Parser->TokenStr[i] == '\\' ) { - i ++; - switch( Parser->TokenStr[i] ) - { - case 'n': data[j++] = '\n'; break; - case 'r': data[j++] = '\r'; break; - default: - // TODO: Octal Codes - // TODO: Error/Warning? - break; - } - } - else { - data[j++] = Parser->TokenStr[i]; - } - } - - // TODO: Parse Escape Codes - ret = AST_NewString( Parser, data, j ); - } - return ret; -} - -/** - * \brief Get a numeric value - */ -tAST_Node *Parse_GetNumeric(tParser *Parser) -{ - uint64_t value = 0; - const char *pos; - SyntaxAssert( Parser, GetToken( Parser ), TOK_INTEGER ); - pos = Parser->TokenStr; - //printf("pos = %p, *pos = %c\n", pos, *pos); - - if( *pos == '0' ) - { - pos ++; - if(*pos == 'x') { - pos ++; - for( ;; pos++) - { - value *= 16; - if( '0' <= *pos && *pos <= '9' ) { - value += *pos - '0'; - continue; - } - if( 'A' <= *pos && *pos <= 'F' ) { - value += *pos - 'A' + 10; - continue; - } - if( 'a' <= *pos && *pos <= 'f' ) { - value += *pos - 'a' + 10; - continue; - } - break; - } - } - else { - while( '0' <= *pos && *pos <= '7' ) { - value = value*8 + *pos - '0'; - pos ++; - } - } - } - else { - while( '0' <= *pos && *pos <= '9' ) { - value = value*10 + *pos - '0'; - pos ++; - } - } - - return AST_NewInteger( Parser, value ); -} - -/** - * \brief Get a variable - */ -tAST_Node *Parse_GetVariable(tParser *Parser) -{ - tAST_Node *ret; - SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE ); - { - char name[Parser->TokenLen]; - memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1); - name[Parser->TokenLen-1] = 0; - ret = AST_NewVariable( Parser, name ); - #if DEBUG >= 2 - printf("Parse_GetVariable: name = '%s'\n", name); - #endif - } - for(;;) - { - GetToken(Parser); - if( Parser->Token == TOK_SQUARE_OPEN ) - { - ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser)); - SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE); - continue ; - } - if( Parser->Token == TOK_ELEMENT ) - { - SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT); - // Method Call - if( LookAhead(Parser) == TOK_PAREN_OPEN ) - { - char name[Parser->TokenLen+1]; - memcpy(name, Parser->TokenStr, Parser->TokenLen); - name[Parser->TokenLen] = 0; - ret = AST_NewMethodCall(Parser, ret, name); - GetToken(Parser); // Eat the '(' - // Read arguments - if( GetToken(Parser) != TOK_PAREN_CLOSE ) - { - PutBack(Parser); - do { - AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) ); - } while(GetToken(Parser) == TOK_COMMA); - SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE ); - } - - } - // Attribute - else - { - char name[Parser->TokenLen]; - memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1); - name[Parser->TokenLen-1] = 0; - ret = AST_NewClassElement(Parser, ret, name); - } - continue ; - } - - break ; - } - PutBack(Parser); - return ret; -} - -/** - * \brief Get an identifier (constant or function call) - */ -tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate) -{ - tAST_Node *ret = NULL; - char *name; - SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT ); - name = strndup( Parser->TokenStr, Parser->TokenLen ); - - #if USE_SCOPE_CHAR - if( GetToken(Parser) == TOK_SCOPE ) - { - ret = AST_NewScopeDereference( Parser, name, Parse_GetIdent(Parser, bObjectCreate) ); - free(name); - return ret; - } - PutBack(Parser); - #endif - - if( GetToken(Parser) == TOK_PAREN_OPEN ) - { - #if DEBUG >= 2 - printf("Parse_GetIdent: Calling '%s'\n", name); - #endif - // Function Call - if( bObjectCreate ) - ret = AST_NewCreateObject( Parser, name ); - else - ret = AST_NewFunctionCall( Parser, name ); - // Read arguments - if( GetToken(Parser) != TOK_PAREN_CLOSE ) - { - PutBack(Parser); - do { - #if DEBUG >= 2 - printf(" Parse_GetIdent: Argument\n"); - #endif - AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) ); - } while(GetToken(Parser) == TOK_COMMA); - SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE ); - #if DEBUG >= 2 - printf(" Parse_GetIdent: All arguments parsed\n"); - #endif - } - } - else - { - // Runtime Constant / Variable (When implemented) - #if DEBUG >= 2 - printf("Parse_GetIdent: Referencing '%s'\n", name); - #endif - PutBack(Parser); - if( bObjectCreate ) // Void constructor (TODO: Should this be an error?) - ret = AST_NewCreateObject( Parser, name ); - else - ret = AST_NewConstant( Parser, name ); - } - - free(name); - return ret; -} - - -void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...) -{ - va_list args; - va_start(args, Message); - fprintf(stderr, "%s:%i: error: ", Parser->Filename, Parser->CurLine); - vfprintf(stderr, Message, args); - fprintf(stderr, "\n"); - va_end(args); - - if( bFatal ) { - //longjmp(Parser->JmpTarget, -1); - Parser->ErrorHit = 1; - } -} - -void SyntaxAssert(tParser *Parser, int Have, int Want) -{ - if( Have != Want ) - { - SyntaxError(Parser, 1, "Unexpected %s(%i), expecting %s(%i)\n", - csaTOKEN_NAMES[Have], Have, csaTOKEN_NAMES[Want], Want); - } -} diff --git a/Usermode/Libraries/libspiderscript.so_src/spiderscript.h b/Usermode/Libraries/libspiderscript.so_src/spiderscript.h deleted file mode 100644 index 3d58a8cd..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/spiderscript.h +++ /dev/null @@ -1,347 +0,0 @@ -/* - * - */ -#ifndef _SPIDERSCRIPT_H_ -#define _SPIDERSCRIPT_H_ - -#include - -#define ERRPTR ((void*)((intptr_t)0-1)) - -/** - * \brief Opaque script handle - */ -typedef struct sSpiderScript tSpiderScript; - -typedef struct sSpiderVariant tSpiderVariant; -typedef struct sSpiderNamespace tSpiderNamespace; -typedef struct sSpiderFunction tSpiderFunction; -typedef struct sSpiderValue tSpiderValue; -typedef struct sSpiderObjectDef tSpiderObjectDef; -typedef struct sSpiderObject tSpiderObject; - - -/** - * \brief SpiderScript Variable Datatypes - * \todo Expand the descriptions - */ -enum eSpiderScript_DataTypes -{ - /** - * \brief Undefined data - * \note Default type of an undefined dynamic variable - */ - SS_DATATYPE_UNDEF, - /** - * \brief Dynamically typed variable - * \note Used to dentote a non-fixed type for function parameters - */ - SS_DATATYPE_DYNAMIC, - /** - * \brief Opaque Data Pointer - * - * Opaque data types are used for resource handles or for system buffers. - */ - SS_DATATYPE_OPAQUE, - /** - * \brief Object reference - * - * A reference to a SpiderScript class instance. Can be accessed - * using the -> operator. - */ - SS_DATATYPE_OBJECT, - /** - * \brief Array data type (invalid when using static typing) - */ - SS_DATATYPE_ARRAY, - /** - * \brief Integer datatype - * - * 64-bit integer - */ - SS_DATATYPE_INTEGER, - SS_DATATYPE_REAL, //!< Real Number (double) - SS_DATATYPE_STRING, //!< String - NUM_SS_DATATYPES -}; - -#define SS_MAKEARRAY(_type) ((_type) + 0x10000) -#define SS_DOWNARRAY(_type) ((_type) - 0x10000) -#define SS_GETARRAYDEPTH(_type) ((_type) >> 16) - -enum eSpiderValueOps -{ - SS_VALUEOP_NOP, - - SS_VALUEOP_ADD, - SS_VALUEOP_SUBTRACT, - SS_VALUEOP_NEGATE, - SS_VALUEOP_MULIPLY, - SS_VALUEOP_DIVIDE, - SS_VALUEOP_MODULO, - - SS_VALUEOP_BITNOT, - SS_VALUEOP_BITAND, - SS_VALUEOP_BITOR, - SS_VALUEOP_BITXOR, - - SS_VALUEOP_SHIFTLEFT, - SS_VALUEOP_SHIFTRIGHT, - SS_VALUEOP_ROTATELEFT -}; - -/** - * \brief Namespace definition - */ -struct sSpiderNamespace -{ - tSpiderNamespace *Next; - - tSpiderNamespace *FirstChild; - - tSpiderFunction *Functions; - - tSpiderObjectDef *Classes; - - int NConstants; //!< Number of constants - tSpiderValue *Constants; //!< Number of constants - - const char Name[]; -}; - -/** - * \brief Variant of SpiderScript - */ -struct sSpiderVariant -{ - const char *Name; // Just for debug - - int bDyamicTyped; //!< Use dynamic typing - int bImplicitCasts; //!< Allow implicit casts (casts to lefthand side) - - tSpiderFunction *Functions; //!< Functions (Linked List) - - int NConstants; //!< Number of constants - tSpiderValue *Constants; //!< Number of constants - - tSpiderNamespace RootNamespace; -}; - -/** - * \brief SpiderScript data object - */ -struct sSpiderValue -{ - enum eSpiderScript_DataTypes Type; //!< Variable type - int ReferenceCount; //!< Reference count - - union { - int64_t Integer; //!< Integer data - double Real; //!< Real Number data - /** - * \brief String data - */ - struct { - int Length; //!< Length - char Data[]; //!< Actual string (\a Length bytes) - } String; - /** - * \brief Variable data - */ - struct { - int Length; //!< Length of the array - tSpiderValue *Items[]; //!< Array elements (\a Length long) - } Array; - - /** - * \brief Opaque data - */ - struct { - void *Data; //!< Data (can be anywhere) - void (*Destroy)(void *Data); //!< Called on GC - } Opaque; - - /** - * \brief Object Instance - */ - tSpiderObject *Object; - }; -}; - -/** - * \brief Object Definition - * - * Internal representation of an arbitary object. - */ -struct sSpiderObjectDef -{ - /** - */ - struct sSpiderObjectDef *Next; //!< Internal linked list - /** - * \brief Object type name - */ - const char * const Name; - /** - * \brief Construct an instance of the object - * \param NArgs Number of arguments - * \param Args Argument array - * \return Pointer to an object instance (which must be fully valid) - * \retval NULL Invalid parameter (usually, actually just a NULL value) - * \retval ERRPTR Invalid parameter count - */ - tSpiderObject *(*Constructor)(int NArgs, tSpiderValue **Args); - - /** - * \brief Clean up and destroy the object - * \param This Object instace - * \note The object pointer (\a This) should be invalidated and freed - * by this function. - */ - void (*Destructor)(tSpiderObject *This); - - - /** - * \brief Get/Set an attribute's value - */ - tSpiderValue *(*GetSetAttribute)(tSpiderObject *This, int AttibuteID, tSpiderValue *NewValue); - - /** - * \brief Method Definitions (linked list) - */ - tSpiderFunction *Methods; - - /** - * \brief Number of attributes - */ - int NAttributes; - - //! Attribute definitions - struct { - const char *Name; //!< Attribute Name - int Type; //!< Datatype - char bReadOnly; //!< Allow writes to the attribute? - char bMethod; //!< IO Goes via GetSetAttribute function - } AttributeDefs[]; -}; - -/** - * \brief Object Instance - */ -struct sSpiderObject -{ - tSpiderObjectDef *Type; //!< Object Type - int ReferenceCount; //!< Number of references - void *OpaqueData; //!< Pointer to the end of the \a Attributes array - tSpiderValue *Attributes[]; //!< Attribute Array -}; - -/** - * \brief Represents a function avaliable to a script - */ -struct sSpiderFunction -{ - /** - * \brief Next function in list - */ - struct sSpiderFunction *Next; - - /** - * \brief Function name - */ - const char *Name; - /** - * \brief Function handler - */ - tSpiderValue *(*Handler)(tSpiderScript *Script, int nParams, tSpiderValue **Parameters); - - /** - * \brief What type is returned - */ - int ReturnType; - - /** - * \brief Argument types - * - * Zero or -1 terminated array of \a eSpiderScript_DataTypes. - * If the final entry is zero, the function has a fixed number of - * parameters, if the final entry is -1, the function has a variable - * number of arguments. - */ - int ArgTypes[]; // Zero (or -1) terminated array of parameter types -}; - - -// === FUNCTIONS === -/** - * \brief Parse a file into a script - * \param Variant Variant structure - * \param Filename File to parse - * \return Script suitable for execution - */ -extern tSpiderScript *SpiderScript_ParseFile(tSpiderVariant *Variant, const char *Filename); -/** - * \brief Execute a function from a script - * \param Script Script to run - * \param Function Name of function to run ("" for the 'main') - * \return Return value - */ -extern tSpiderValue *SpiderScript_ExecuteFunction(tSpiderScript *Script, - const char *Function, const char *DefaultNamespaces[], - int NArguments, tSpiderValue **Arguments, - void **FunctionIdent - ); -/** - * \brief Execute an object method - */ -extern tSpiderValue *SpiderScript_ExecuteMethod(tSpiderScript *Script, - tSpiderObject *Object, const char *MethodName, - int NArguments, tSpiderValue **Arguments - ); -/** - * \brief Creates an object instance - */ -extern tSpiderValue *SpiderScript_CreateObject(tSpiderScript *Script, - const char *ClassName, const char *DefaultNamespaces[], - int NArguments, tSpiderValue **Arguments - ); - -/** - * \brief Convert a script to bytecode and save to a file - */ -extern int SpiderScript_SaveBytecode(tSpiderScript *Script, const char *DestFile); -/** - * \brief Save the AST of a script to a file - */ -extern int SpiderScript_SaveAST(tSpiderScript *Script, const char *Filename); - -/** - * \brief Free a script - * \param Script Script structure to free - */ -extern void SpiderScript_Free(tSpiderScript *Script); - -extern tSpiderObject *SpiderScript_AllocateObject(tSpiderObjectDef *Class, int ExtraBytes); - -/** - * \name tSpiderValue Manipulation functions - * \{ - */ -extern void SpiderScript_DereferenceValue(tSpiderValue *Object); -extern void SpiderScript_ReferenceValue(tSpiderValue *Object); -extern tSpiderValue *SpiderScript_CreateInteger(uint64_t Value); -extern tSpiderValue *SpiderScript_CreateReal(double Value); -extern tSpiderValue *SpiderScript_CreateString(int Length, const char *Data); -extern tSpiderValue *SpiderScript_CreateArray(int InnerType, int ItemCount); -extern tSpiderValue *SpiderScript_StringConcat(const tSpiderValue *Str1, const tSpiderValue *Str2); -extern tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source); -extern int SpiderScript_IsValueTrue(tSpiderValue *Value); -extern void SpiderScript_FreeValue(tSpiderValue *Value); -extern char *SpiderScript_DumpValue(tSpiderValue *Value); - -extern tSpiderValue *SpiderScript_DoOp(tSpiderValue *Left, enum eSpiderValueOps Op, int bCanCast, tSpiderValue *Right); -/** - * \} - */ - -#endif diff --git a/Usermode/Libraries/libspiderscript.so_src/tokens.h b/Usermode/Libraries/libspiderscript.so_src/tokens.h deleted file mode 100644 index 4b2acb20..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/tokens.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - */ -#ifndef _TOKENS_H_ -#define _TOKENS_H_ - -#include - -// Make the scope character ('.') be a symbol, otherwise it's just -// a ident character -#define USE_SCOPE_CHAR 1 - -// === TYPES === -typedef struct -{ - // Lexer State - const char *BufStart; - const char *CurPos; - - char *Filename; - - int LastLine; - int LastToken, LastTokenLen; - const char *LastTokenStr; - - int NextLine; - int NextToken, NextTokenLen; - const char *NextTokenStr; - - int CurLine; - int Token, TokenLen; - const char *TokenStr; - - jmp_buf JmpTarget; - int ErrorHit; - - struct sSpiderVariant *Variant; -} tParser; - -// === FUNCTIONS === - int GetToken(tParser *File); -void PutBack(tParser *File); - int LookAhead(tParser *File); - -// === CONSTANTS === -enum eTokens -{ - TOK_INVAL, - TOK_EOF, - - // Primitives - TOK_STR, - TOK_INTEGER, - TOK_REAL, - TOK_VARIABLE, - TOK_IDENT, - - // Reserved Words - // - Definitions - TOK_RWD_FUNCTION, - TOK_RWD_NAMESPACE, - // - Control Flow - TOK_RWD_NEW, - TOK_RWD_RETURN, - TOK_RWD_BREAK, - TOK_RWD_CONTINUE, - // - Blocks - TOK_RWD_IF, - TOK_RWD_ELSE, - TOK_RWD_DO, - TOK_RWD_WHILE, - TOK_RWD_FOR, - // - Value - TOK_RWD_NULL, - // - Types - TOK_RWD_VOID, - TOK_RWD_OBJECT, - TOK_RWD_OPAQUE, - TOK_RWD_STRING, - TOK_RWD_INTEGER, - TOK_RWD_REAL, - - // - TOK_ASSIGN, - TOK_SEMICOLON, - TOK_COMMA, - TOK_SCOPE, - TOK_ELEMENT, - - // Comparisons - TOK_EQUALS, TOK_NOTEQUALS, - TOK_LT, TOK_LTE, - TOK_GT, TOK_GTE, - - // Operations - TOK_BWNOT, TOK_LOGICNOT, - TOK_DIV, TOK_MUL, - TOK_PLUS, TOK_MINUS, - TOK_SHL, TOK_SHR, - TOK_LOGICAND, TOK_LOGICOR, TOK_LOGICXOR, - TOK_AND, TOK_OR, TOK_XOR, - - // Assignment Operations - TOK_INCREMENT, TOK_DECREMENT, - TOK_ASSIGN_DIV, TOK_ASSIGN_MUL, - TOK_ASSIGN_PLUS, TOK_ASSIGN_MINUS, - TOK_ASSIGN_SHL, TOK_ASSIGN_SHR, - TOK_ASSIGN_LOGICAND, TOK_ASSIGN_LOGICOR, TOK_ASSIGN_LOGXICOR, - TOK_ASSIGN_AND, TOK_ASSIGN_OR, TOK_ASSIGN_XOR, - - TOK_PAREN_OPEN, TOK_PAREN_CLOSE, - TOK_BRACE_OPEN, TOK_BRACE_CLOSE, - TOK_SQUARE_OPEN, TOK_SQUARE_CLOSE, - - TOK_LAST -}; - -#define TOKEN_GROUP_TYPES TOK_RWD_VOID:\ - case TOK_RWD_OBJECT:\ - case TOK_RWD_OPAQUE:\ - case TOK_RWD_INTEGER:\ - case TOK_RWD_STRING:\ - case TOK_RWD_REAL -#define TOKEN_GROUP_TYPES_STR "TOK_RWD_VOID, TOK_RWD_OBJECT, TOK_RWD_OPAQUE, TOK_RWD_INTEGER, TOK_RWD_STRING or TOK_RWD_REAL" - -#define TOKEN_GET_DATATYPE(_type, _tok) do { switch(_tok) {\ - case TOK_RWD_VOID: _type = SS_DATATYPE_UNDEF; break;\ - case TOK_RWD_INTEGER:_type = SS_DATATYPE_INTEGER; break;\ - case TOK_RWD_OPAQUE: _type = SS_DATATYPE_OPAQUE; break;\ - case TOK_RWD_OBJECT: _type = SS_DATATYPE_OBJECT; break;\ - case TOK_RWD_REAL: _type = SS_DATATYPE_REAL; break;\ - case TOK_RWD_STRING: _type = SS_DATATYPE_STRING; break;\ - default:_type=SS_DATATYPE_UNDEF;fprintf(stderr,\ - "ERROR: Unexpected %s, expected "TOKEN_GROUP_TYPES_STR"\n",csaTOKEN_NAMES[Parser->Token]);\ - break;\ - } } while(0) - -# if WANT_TOKEN_STRINGS -const char * const csaTOKEN_NAMES[] = { - "TOK_INVAL", - "TOK_EOF", - - "TOK_STR", - "TOK_INTEGER", - "TOK_REAL", - "TOK_VARIABLE", - "TOK_IDENT", - - "TOK_RWD_FUNCTION", - "TOK_RWD_NAMESPACE", - - "TOK_RWD_NEW", - "TOK_RWD_RETURN", - "TOK_RWD_BREAK", - "TOK_RWD_CONTINUE", - - "TOK_RWD_IF", - "TOK_RWD_ELSE", - "TOK_RWD_DO", - "TOK_RWD_WHILE", - "TOK_RWD_FOR", - - "TOK_RWD_NULL", - "TOK_RWD_VOID", - "TOK_RWD_OBJECT", - "TOK_RWD_OPAUQE", - "TOK_RWD_STRING", - "TOK_RWD_INTEGER", - "TOK_RWD_REAL", - - "TOK_ASSIGN", - "TOK_SEMICOLON", - "TOK_COMMA", - "TOK_SCOPE", - "TOK_ELEMENT", - - "TOK_EQUALS", "TOK_NOTEQUALS", - "TOK_LT", "TOK_LTE", - "TOK_GT", "TOK_GTE", - - "TOK_BWNOT", "TOK_LOGICNOT", - "TOK_DIV", "TOK_MUL", - "TOK_PLUS", "TOK_MINUS", - "TOK_SHL", "TOK_SHR", - "TOK_LOGICAND", "TOK_LOGICOR", "TOK_LOGICXOR", - "TOK_AND", "TOK_OR", "TOK_XOR", - - "TOK_INCREMENT", "TOK_DECREMENT", - "TOK_ASSIGN_DIV", "TOK_ASSIGN_MUL", - "TOK_ASSIGN_PLUS", "TOK_ASSIGN_MINUS", - "TOK_ASSIGN_SHL", "TOK_ASSIGN_SHR", - "TOK_ASSIGN_LOGICAND", "TOK_ASSIGN_LOGICOR", "TOK_ASSIGN_LOGICXOR", - "TOK_ASSIGN_AND", "TOK_ASSIGN_OR", "TOK_ASSIGN_XOR", - - "TOK_PAREN_OPEN", "TOK_PAREN_CLOSE", - "TOK_BRACE_OPEN", "TOK_BRACE_CLOSE", - "TOK_SQUARE_OPEN", "TOK_SQUARE_CLOSE", - - "TOK_LAST" -}; -# endif - -#endif diff --git a/Usermode/Libraries/libspiderscript.so_src/values.c b/Usermode/Libraries/libspiderscript.so_src/values.c deleted file mode 100644 index 019ff5f0..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/values.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - * SpiderScript Library - * by John Hodge (thePowersGang) - * - * values.c - * - Manage tSpiderValue objects - */ -#include -#include -#include -#include "spiderscript.h" - -// === IMPORTS === -extern void AST_RuntimeError(void *Node, const char *Format, ...); - -// === PROTOTYPES === -void SpiderScript_DereferenceValue(tSpiderValue *Object); -void SpiderScript_ReferenceValue(tSpiderValue *Object); -tSpiderValue *SpiderScript_CreateInteger(uint64_t Value); -tSpiderValue *SpiderScript_CreateReal(double Value); -tSpiderValue *SpiderScript_CreateString(int Length, const char *Data); -tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source); - int SpiderScript_IsValueTrue(tSpiderValue *Value); -void SpiderScript_FreeValue(tSpiderValue *Value); -char *SpiderScript_DumpValue(tSpiderValue *Value); -// --- Operations -tSpiderValue *SpiderScript_DoOp(tSpiderValue *Left, enum eSpiderValueOps, int bCanCast, tSpiderValue *Right); -tSpiderValue *SpiderScript_int_DoOpInt(tSpiderValue *Left, enum eSpiderValueOps, int bCanCast, tSpiderValue *Right); -tSpiderValue *SpiderScript_int_DoOpReal(tSpiderValue *Left, enum eSpiderValueOps, int bCanCast, tSpiderValue *Right); -tSpiderValue *SpiderScript_int_DoOpString(tSpiderValue *Left, enum eSpiderValueOps, int bCanCast, tSpiderValue *Right); - - -// === CODE === -/** - * \brief Dereference a created object - */ -void SpiderScript_DereferenceValue(tSpiderValue *Object) -{ - if(!Object || Object == ERRPTR) return ; - Object->ReferenceCount --; - if( Object->ReferenceCount == 0 ) - { - int i; - - if( Object->Type == SS_DATATYPE_ARRAY || SS_GETARRAYDEPTH(Object->Type) ) - { - for( i = 0; i < Object->Array.Length; i ++ ) - { - if( Object->Array.Items[i] ) { - SpiderScript_DereferenceValue(Object->Array.Items[i]); - } - Object->Array.Items[i] = NULL; - } - } - else - { - switch( (enum eSpiderScript_DataTypes) Object->Type ) - { - case SS_DATATYPE_OBJECT: - Object->Object->ReferenceCount --; - if(Object->Object->ReferenceCount == 0) { - Object->Object->Type->Destructor( Object->Object ); - } - Object->Object = NULL; - break; - - case SS_DATATYPE_OPAQUE: - Object->Opaque.Destroy( Object->Opaque.Data ); - break; - default: - break; - } - } - free(Object); - } -} - -/** - * \brief Reference a value - */ -void SpiderScript_ReferenceValue(tSpiderValue *Object) -{ - if(!Object || Object == ERRPTR) return ; - Object->ReferenceCount ++; -} - -/** - * \brief Allocate and initialise a SpiderScript object - */ -tSpiderObject *SpiderScript_AllocateObject(tSpiderObjectDef *Class, int ExtraBytes) -{ - int size = sizeof(tSpiderObject) + Class->NAttributes * sizeof(tSpiderValue*) + ExtraBytes; - tSpiderObject *ret = malloc(size); - - ret->Type = Class; - ret->ReferenceCount = 1; - ret->OpaqueData = &ret->Attributes[ Class->NAttributes ]; - memset( ret->Attributes, 0, Class->NAttributes * sizeof(tSpiderValue*) ); - - return ret; -} - -/** - * \brief Create an integer object - */ -tSpiderValue *SpiderScript_CreateInteger(uint64_t Value) -{ - tSpiderValue *ret = malloc( sizeof(tSpiderValue) ); - ret->Type = SS_DATATYPE_INTEGER; - ret->ReferenceCount = 1; - ret->Integer = Value; - return ret; -} - -/** - * \brief Create an real number object - */ -tSpiderValue *SpiderScript_CreateReal(double Value) -{ - tSpiderValue *ret = malloc( sizeof(tSpiderValue) ); - ret->Type = SS_DATATYPE_REAL; - ret->ReferenceCount = 1; - ret->Real = Value; - return ret; -} - -/** - * \brief Create an string object - */ -tSpiderValue *SpiderScript_CreateString(int Length, const char *Data) -{ - tSpiderValue *ret = malloc( sizeof(tSpiderValue) + Length + 1 ); - ret->Type = SS_DATATYPE_STRING; - ret->ReferenceCount = 1; - ret->String.Length = Length; - if( Data ) - memcpy(ret->String.Data, Data, Length); - else - memset(ret->String.Data, 0, Length); - ret->String.Data[Length] = '\0'; - return ret; -} - -tSpiderValue *SpiderScript_CreateArray(int InnerType, int ItemCount) -{ - tSpiderValue *ret = malloc( sizeof(tSpiderValue) + ItemCount*sizeof(tSpiderValue*) ); - ret->Type = SS_MAKEARRAY(InnerType); - ret->ReferenceCount = 1; - ret->Array.Length = ItemCount; - memset(ret->Array.Items, 0, ItemCount*sizeof(tSpiderValue*)); - return ret; -} - -/** - * \brief Concatenate two strings - */ -tSpiderValue *SpiderScript_StringConcat(const tSpiderValue *Str1, const tSpiderValue *Str2) -{ - int newLen = 0; - tSpiderValue *ret; - - if( Str1 && Str1->Type != SS_DATATYPE_STRING) - return NULL; - if( Str2 && Str2->Type != SS_DATATYPE_STRING) - return NULL; - - if(Str1) newLen += Str1->String.Length; - if(Str2) newLen += Str2->String.Length; - ret = malloc( sizeof(tSpiderValue) + newLen + 1 ); - ret->Type = SS_DATATYPE_STRING; - ret->ReferenceCount = 1; - ret->String.Length = newLen; - if(Str1) - memcpy(ret->String.Data, Str1->String.Data, Str1->String.Length); - if(Str2) { - if(Str1) - memcpy(ret->String.Data+Str1->String.Length, Str2->String.Data, Str2->String.Length); - else - memcpy(ret->String.Data, Str2->String.Data, Str2->String.Length); - } - ret->String.Data[ newLen ] = '\0'; - return ret; -} - -/** - * \brief Cast one object to another - * \brief Type Destination type - * \brief Source Input data - */ -tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source) -{ - tSpiderValue *ret = ERRPTR; - int len = 0; - - if( !Source ) - { - switch(Type) - { - case SS_DATATYPE_INTEGER: return SpiderScript_CreateInteger(0); - case SS_DATATYPE_REAL: return SpiderScript_CreateReal(0); - case SS_DATATYPE_STRING: return SpiderScript_CreateString(4, "null"); - } - return NULL; - } - - // Check if anything needs to be done - if( Source->Type == Type ) { - SpiderScript_ReferenceValue(Source); - return Source; - } - - // Debug - #if 0 - { - printf("Casting %i ", Source->Type); - switch(Source->Type) - { - case SS_DATATYPE_INTEGER: printf("0x%lx", Source->Integer); break; - case SS_DATATYPE_STRING: printf("\"%s\"", Source->String.Data); break; - case SS_DATATYPE_REAL: printf("%f", Source->Real); break; - default: break; - } - printf(" to %i\n", Type); - } - #endif - - // Object casts - #if 0 - if( Source->Type == SS_DATATYPE_OBJECT ) - { - const char *name = NULL; - switch(Type) - { - case SS_DATATYPE_INTEGER: name = "cast Integer"; break; - case SS_DATATYPE_REAL: name = "cast Real"; break; - case SS_DATATYPE_STRING: name = "cast String"; break; - case SS_DATATYPE_ARRAY: name = "cast Array"; break; - default: - AST_RuntimeError(NULL, "Invalid cast to %i from Object", Type); - return ERRPTR; - } - if( fcnname ) - { - ret = Object_ExecuteMethod(Left->Object, fcnname, Right); - if( ret != ERRPTR ) - return ret; - // Fall through and try casting (which will usually fail) - } - } - #endif - - switch( (enum eSpiderScript_DataTypes)Type ) - { - case SS_DATATYPE_UNDEF: - case SS_DATATYPE_ARRAY: - case SS_DATATYPE_OPAQUE: - AST_RuntimeError(NULL, "Invalid cast to %i", Type); - return ERRPTR; - case SS_DATATYPE_OBJECT: - // TODO: - AST_RuntimeError(NULL, "Invalid cast to %i", Type); - return ERRPTR; - - case SS_DATATYPE_INTEGER: - ret = malloc(sizeof(tSpiderValue)); - ret->Type = SS_DATATYPE_INTEGER; - ret->ReferenceCount = 1; - switch(Source->Type) - { - case SS_DATATYPE_INTEGER: break; // Handled above - case SS_DATATYPE_STRING: ret->Integer = atoi(Source->String.Data); break; - case SS_DATATYPE_REAL: ret->Integer = Source->Real; break; - default: - AST_RuntimeError(NULL, "Invalid cast from %i to Integer", Source->Type); - free(ret); - ret = ERRPTR; - break; - } - break; - - case SS_DATATYPE_REAL: - ret = malloc(sizeof(tSpiderValue)); - ret->Type = SS_DATATYPE_REAL; - ret->ReferenceCount = 1; - switch(Source->Type) - { - case SS_DATATYPE_STRING: ret->Real = atof(Source->String.Data); break; - case SS_DATATYPE_INTEGER: ret->Real = Source->Integer; break; - default: - AST_RuntimeError(NULL, "Invalid cast from %i to Real", Source->Type); - free(ret); - ret = ERRPTR; - break; - } - break; - - case SS_DATATYPE_STRING: - switch(Source->Type) - { - case SS_DATATYPE_INTEGER: len = snprintf(NULL, 0, "%li", Source->Integer); break; - case SS_DATATYPE_REAL: len = snprintf(NULL, 0, "%g", Source->Real); break; - default: break; - } - ret = malloc(sizeof(tSpiderValue) + len + 1); - ret->Type = SS_DATATYPE_STRING; - ret->ReferenceCount = 1; - ret->String.Length = len; - switch(Source->Type) - { - case SS_DATATYPE_INTEGER: sprintf(ret->String.Data, "%li", Source->Integer); break; - case SS_DATATYPE_REAL: - sprintf(ret->String.Data, "%g", Source->Real); break; - default: - AST_RuntimeError(NULL, "Invalid cast from %i to String", Source->Type); - free(ret); - ret = ERRPTR; - break; - } - break; - - default: - AST_RuntimeError(NULL, "BUG - BUG REPORT: Unimplemented cast target %i", Type); - ret = ERRPTR; - break; - } - - return ret; -} - -/** - * \brief Condenses a value down to a boolean - */ -int SpiderScript_IsValueTrue(tSpiderValue *Value) -{ - if( Value == ERRPTR ) return 0; - if( Value == NULL ) return 0; - - switch( (enum eSpiderScript_DataTypes)Value->Type ) - { - case SS_DATATYPE_UNDEF: - return 0; - - case SS_DATATYPE_INTEGER: - return !!Value->Integer; - - case SS_DATATYPE_REAL: - return (-.5f < Value->Real && Value->Real < 0.5f); - - case SS_DATATYPE_STRING: - return Value->String.Length > 0; - - case SS_DATATYPE_OBJECT: - return Value->Object != NULL; - - case SS_DATATYPE_OPAQUE: - return Value->Opaque.Data != NULL; - - case SS_DATATYPE_ARRAY: - return Value->Array.Length > 0; - default: - AST_RuntimeError(NULL, "Unknown type %i in SpiderScript_IsValueTrue", Value->Type); - return 0; - } - return 0; -} - -/** - * \brief Free a value - * \note Just calls Object_Dereference - */ -void SpiderScript_FreeValue(tSpiderValue *Value) -{ - SpiderScript_DereferenceValue(Value); -} - -/** - * \brief Dump a value into a string - * \return Heap string - */ -char *SpiderScript_DumpValue(tSpiderValue *Value) -{ - char *ret; - if( Value == ERRPTR ) - return strdup("ERRPTR"); - if( Value == NULL ) - return strdup("null"); - - switch( (enum eSpiderScript_DataTypes)Value->Type ) - { - case SS_DATATYPE_UNDEF: return strdup("undefined"); - - case SS_DATATYPE_INTEGER: - ret = malloc( sizeof(Value->Integer)*2 + 3 ); - sprintf(ret, "0x%lx", Value->Integer); - return ret; - - case SS_DATATYPE_REAL: - ret = malloc( sprintf(NULL, "%f", Value->Real) + 1 ); - sprintf(ret, "%f", Value->Real); - return ret; - - case SS_DATATYPE_STRING: - ret = malloc( Value->String.Length + 3 ); - ret[0] = '"'; - strcpy(ret+1, Value->String.Data); - ret[Value->String.Length+1] = '"'; - ret[Value->String.Length+2] = '\0'; - return ret; - - case SS_DATATYPE_OBJECT: - ret = malloc( sprintf(NULL, "{%s *%p}", Value->Object->Type->Name, Value->Object) + 1 ); - sprintf(ret, "{%s *%p}", Value->Object->Type->Name, Value->Object); - return ret; - - case SS_DATATYPE_OPAQUE: - ret = malloc( sprintf(NULL, "*%p", Value->Opaque.Data) + 1 ); - sprintf(ret, "*%p", Value->Opaque.Data); - return ret; - - case SS_DATATYPE_ARRAY: - return strdup("Array"); - - default: - AST_RuntimeError(NULL, "Unknown type %i in Object_Dump", Value->Type); - return NULL; - } - -} - -// --- -tSpiderValue *SpiderScript_DoOp(tSpiderValue *Left, enum eSpiderValueOps Operation, int bCanCast, tSpiderValue *Right) -{ - switch(Left->Type) - { - case SS_DATATYPE_INTEGER: - return SpiderScript_int_DoOpInt(Left, Operation, bCanCast, Right); - default: - return NULL; - } - return NULL; -} - -tSpiderValue *SpiderScript_int_DoOpInt(tSpiderValue *Left, enum eSpiderValueOps Operation, int bCanCast, tSpiderValue *Right) -{ - tSpiderValue *oldright = Right; - tSpiderValue *ret = NULL; - int64_t rv = 0; - - // Casting - if(Right && Right->Type != SS_DATATYPE_INTEGER) { - if(!bCanCast) return ERRPTR; - Right = SpiderScript_CastValueTo(SS_DATATYPE_INTEGER, Right); - } - - // Do the operation - switch(Operation) - { - case SS_VALUEOP_NEGATE: - if(Right) ret = ERRPTR; - else rv = -Left->Integer; - break; - case SS_VALUEOP_ADD: - if(!Right) ret = ERRPTR; - else rv = Left->Integer + Right->Integer; - break; - case SS_VALUEOP_SUBTRACT: - if(!Right) ret = ERRPTR; - else rv = Left->Integer - Right->Integer; - break; - default: - ret = ERRPTR; - AST_RuntimeError(NULL, "BUG - BUG REPORT: Unimplemented integer operation %i", Operation); - break; - } - - // Delete temporary value - if( Right != oldright ) - SpiderScript_DereferenceValue(Right); - - // Return error if signaled - if(ret == ERRPTR) - return ERRPTR; - - // Reuse `Left` if possible, to reduce mallocs - if(Left->ReferenceCount == 1) { - SpiderScript_ReferenceValue(Left); - Left->Integer = rv; - return Left; - } - else { - return SpiderScript_CreateInteger(rv); - } -} -