From: John Hodge Date: Sun, 22 Apr 2012 09:36:55 +0000 (+0800) Subject: Merge branch 'master' of cadel.mutabah.net:acess2 X-Git-Tag: rel0.15~714 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=533ed3e53b3b16da86c4e792eb52e0570e2cd21f;hp=dca6decf0b2d98f521488f071ba3af1a4a6b8647;p=tpg%2Facess2.git Merge branch 'master' of cadel.mutabah.net:acess2 --- diff --git a/KernelLand/Kernel/arch/armv7/proc.S b/KernelLand/Kernel/arch/armv7/proc.S index 8711dee6..19790583 100644 --- a/KernelLand/Kernel/arch/armv7/proc.S +++ b/KernelLand/Kernel/arch/armv7/proc.S @@ -49,9 +49,8 @@ SwitchTask: # mov r1, #1 mcrne p15, 0, r1, c8, c7, 0 @ TLBIALL - Invalid user space - @ Restore SP + @ Restore state mov sp, r0 - bx r2 .return: @@ -102,3 +101,5 @@ csProc_CloneInt_NewTaskMessage: .asciz "New task PC=%p, R4=%p, sp=%p" csProc_CloneInt_OldTaskMessage: .asciz "Parent task PC=%p, R4=%p, SP=%p" + +@ vim: ft=armv7 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 28382cad..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/Makefile +++ /dev/null @@ -1,13 +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 exec_ast.o exports.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 12f9f775..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/ast.c +++ /dev/null @@ -1,744 +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_8(Buffer, Offset, Node->DefVar.DataType); - // TODO: Duplicate compress the strings - WRITE_STR(Buffer, Offset, Node->DefVar.Name); - - WRITE_NODELIST(Buffer, Offset, Node->DefVar.LevelSizes); - 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_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; - - //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: - for( node = Node->DefVar.LevelSizes; node; ) - { - tAST_Node *savedNext = node->NextSibling; - AST_FreeNode(node); - node = savedNext; - } - 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_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_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; - case NODETYPE_DEFVAR: - if(Parent->DefVar.LevelSizes == NULL) { - Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child; - } - else { - Parent->DefVar.LevelSizes_Last->NextSibling = Child; - Parent->DefVar.LevelSizes_Last = 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 ) { - 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 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.LevelSizes = NULL; - ret->DefVar.LevelSizes_Last = NULL; - 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 8ee56d77..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/ast.h +++ /dev/null @@ -1,235 +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 - - NODETYPE_VARIABLE, //!< Variable - NODETYPE_CONSTANT, //!< Runtime Constant - NODETYPE_STRING, //!< String Constant - NODETYPE_INTEGER, //!< Integer Constant - NODETYPE_REAL, //!< Real Constant - - 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) - - 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 - - NODETYPE_IF, //!< Conditional - NODETYPE_LOOP, //!< Looping Construct - - NODETYPE_INDEX, //!< Index into an array - - 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_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 *LevelSizes; - tAST_Node *LevelSizes_Last; - 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_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); - -#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 58cc5f82..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c +++ /dev/null @@ -1,679 +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_NODE_RETURNS 0 -#define MAX_NAMESPACE_DEPTH 10 - -// === IMPORTS === -extern tSpiderFunction *gpExports_First; - -// === TYPES === -typedef struct sAST_BlockInfo -{ - struct sAST_BlockInfo *Parent; - void *Handle; - const char *Tag; - - int BreakTarget; - int ContinueTarget; - - const char *CurNamespaceStack[MAX_NAMESPACE_DEPTH]; -} tAST_BlockInfo; - -// === PROTOTYPES === -// Node Traversal - int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue); -// 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); -// - 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 === -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}; - - // TODO: Return BCFcn instead? - if(Fcn->BCFcn) return Fcn->BCFcn; - - ret = Bytecode_CreateFunction(Fcn); - if(!ret) return NULL; - - bi.Handle = ret; - if( AST_ConvertNode(&bi, Fcn->ASTFcn, 0) ) - { - Bytecode_DeleteFunction(ret); - return NULL; - } - - 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);\ -} } 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 ) - { - AST_ConvertNode(Block, node, 0); - } - } - Bytecode_AppendLeaveContext(Block->Handle); // Leave this context - 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 -1; - } - - // Perform assignment operation - if( Node->Assign.Operation != NODETYPE_NOP ) - { - - ret = BC_Variable_GetValue(Block, Node->Assign.Dest); - if(ret) return ret; - ret = AST_ConvertNode(Block, Node->Assign.Value, 1); - if(ret) return ret; - 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); - Bytecode_AppendBinOp(Block->Handle, op); - } - else - { - ret = AST_ConvertNode(Block, Node->Assign.Value, 1); - if(ret) return ret; - } - - if( bKeepValue ) - Bytecode_AppendDuplicate(Block->Handle); - // Set the variable value - ret = BC_Variable_SetValue( Block, Node->Assign.Dest ); - break; - - // Post increment/decrement - case NODETYPE_POSTINC: - case NODETYPE_POSTDEC: - // TODO: Support assigning to object attributes - if( Node->UniOp.Value->Type != NODETYPE_VARIABLE ) { - AST_RuntimeError(Node, "LVALUE of assignment is not a variable"); - return -1; - } - - // 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 = BC_Variable_GetValue(Block, Node->UniOp.Value); - if(ret) return ret; - - if( Node->Type == NODETYPE_POSTDEC ) - Bytecode_AppendBinOp(Block->Handle, BC_OP_SUBTRACT); - else - Bytecode_AppendBinOp(Block->Handle, BC_OP_ADD); - if(ret) return ret; - - - ret = BC_Variable_SetValue(Block, Node->UniOp.Value); - if(ret) return ret; - // Doesn't push unless needed - break; - - // Function Call - case NODETYPE_METHODCALL: - case NODETYPE_FUNCTIONCALL: - case NODETYPE_CREATEOBJECT: { - int nargs = 0; - - // Put the object earlier on the stack to the arguments (for exec) - if( Node->Type == NODETYPE_METHODCALL ) { - ret = AST_ConvertNode(Block, Node->FunctionCall.Object, 1); - if(ret) return ret; - } - - for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) - { - ret = AST_ConvertNode(Block, node, 1); - if(ret) return ret; - nargs ++; - } - - // Call the function - if( Node->Type == NODETYPE_METHODCALL ) - { - // TODO: Sanity check stack top - Bytecode_AppendMethodCall(Block->Handle, Node->FunctionCall.Name, nargs); - } - else - { - int newnamelen = 0; - char *manglename; - for( i = 0; i < MAX_NAMESPACE_DEPTH && Block->CurNamespaceStack[i]; i ++ ) - newnamelen = strlen(Block->CurNamespaceStack[i]) + 1; - newnamelen += strlen(Node->FunctionCall.Name) + 1; - manglename = alloca(newnamelen); - manglename[0] = 0; - for( i = 0; i < MAX_NAMESPACE_DEPTH && Block->CurNamespaceStack[i]; i ++ ) { - int pos; - strcat(manglename, Block->CurNamespaceStack[i]); - pos = strlen(manglename); - manglename[pos] = BC_NS_SEPARATOR; - manglename[pos+1] = '\0'; - } - strcat(manglename, Node->FunctionCall.Name); - - if( Node->Type == NODETYPE_CREATEOBJECT ) - { - // TODO: Sanity check stack top - Bytecode_AppendCreateObj(Block->Handle, manglename, nargs); - } - else - { - Bytecode_AppendFunctionCall(Block->Handle, manglename, nargs); - } - } - 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; - - 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; - 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); - loop_end = Bytecode_AllocateLabel(Block->Handle); - - saved_break = Block->BreakTarget; - saved_continue = Block->ContinueTarget; - saved_tag = Block->Tag; - Block->BreakTarget = loop_end; - Block->ContinueTarget = loop_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); - Bytecode_AppendCondJump(Block->Handle, loop_end); - } - - // Code - ret = AST_ConvertNode(Block, Node->For.Code, 0); - if(ret) return ret; - - // Increment - ret = AST_ConvertNode(Block, Node->For.Increment, 0); - if(ret) return ret; - - // Tail check - if( Node->For.bCheckAfter ) - { - ret = AST_ConvertNode(Block, Node->For.Condition, 1); - if(ret) 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); - break; - - case NODETYPE_BREAK: - case NODETYPE_CONTINUE: { - tAST_BlockInfo *bi = Block; - if( Node->Variable.Name[0] ) { - while(bi && strcmp(bi->Tag, Node->Variable.Name) == 0) 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; - Bytecode_AppendSaveVar(Block->Handle, Node->DefVar.Name); - } - break; - - // Scope - case NODETYPE_SCOPE: - for( i = 0; i < MAX_NAMESPACE_DEPTH && Block->CurNamespaceStack[i]; i ++ ); - if( i == MAX_NAMESPACE_DEPTH ) { - AST_RuntimeError(Node, "Exceeded max explicit namespace depth (%i)", i); - return 2; - } - Block->CurNamespaceStack[i] = Node->Scope.Name; - ret = AST_ConvertNode(Block, Node->Scope.Element, 2); - Block->CurNamespaceStack[i] = NULL; - CHECK_IF_NEEDED(0); // No warning? - // TODO: Will this collide with _CALLFUNCTION etc? - break; - - // Variable - case NODETYPE_VARIABLE: - ret = BC_Variable_GetValue( Block, Node ); - CHECK_IF_NEEDED(1); - break; - - // Element of an Object - case NODETYPE_ELEMENT: - ret = AST_ConvertNode( Block, Node->Scope.Element, 1 ); - if(ret) return ret; - - Bytecode_AppendElement(Block->Handle, Node->Scope.Name); - 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; - Bytecode_AppendCast(Block->Handle, Node->Cast.DataType); - CHECK_IF_NEEDED(1); - break; - - // Index into an array - case NODETYPE_INDEX: - ret = AST_ConvertNode(Block, Node->BinOp.Left, 1); // Array - if(ret) return ret; - ret = AST_ConvertNode(Block, Node->BinOp.Right, 1); // Offset - if(ret) return ret; - - Bytecode_AppendIndex(Block->Handle); - CHECK_IF_NEEDED(1); - break; - - // TODO: Implement runtime constants - case NODETYPE_CONSTANT: - // TODO: Scan namespace for constant name - AST_RuntimeError(Node, "TODO - Runtime Constants"); - ret = -1; - break; - - // Constant Values - case NODETYPE_STRING: - Bytecode_AppendConstString(Block->Handle, Node->Constant.String.Data, Node->Constant.String.Length); - CHECK_IF_NEEDED(1); - break; - case NODETYPE_INTEGER: - Bytecode_AppendConstInt(Block->Handle, Node->Constant.Integer); - CHECK_IF_NEEDED(1); - break; - case NODETYPE_REAL: - Bytecode_AppendConstReal(Block->Handle, Node->Constant.Real); - 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; - Bytecode_AppendUniOp(Block->Handle, op); - 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_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 = AST_ConvertNode(Block, Node->BinOp.Right, 1); - if(ret) return ret; - - Bytecode_AppendBinOp(Block->Handle, op); - CHECK_IF_NEEDED(1); - break; - - default: - ret = -1; - AST_RuntimeError(Node, "BUG - SpiderScript AST_ConvertNode Unimplemented %i", Node->Type); - break; - } - - #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; -} - -/** - * \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) -{ - #if 0 - 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; - strcpy(var->Name, Name); - - if(prev) prev->Next = var; - else Block->FirstVar = var; - - return var; - #else - Bytecode_AppendDefineVar(Block->Handle, Name, Type); - return 0; - #endif -} - -tAST_Variable *BC_Variable_Lookup(tAST_BlockInfo *Block, tAST_Node *VarNode, int CreateType) -{ - #if 0 - 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_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", "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; - #else - return (void*)1; - #endif -} - -/** - * \brief Set the value of a variable - * \return Boolean Failure - */ -int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode) -{ - tAST_Variable *var; - - var = BC_Variable_Lookup(Block, VarNode, SS_DATATYPE_UNDEF); - if(!var) return -1; - - // TODO: Check types - - 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; - - Bytecode_AppendLoadVar(Block->Handle, VarNode->Variable.Name); - return 0; -} - -#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 diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode.h b/Usermode/Libraries/libspiderscript.so_src/bytecode.h deleted file mode 100644 index bc3c91cd..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode.h +++ /dev/null @@ -1,50 +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 - 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 b089b9ae..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c +++ /dev/null @@ -1,444 +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); - - 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_qword(uint64_t value) - { - _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_dword(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_dword( 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_dword(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); - - 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); -} - -// --- Indexing / Scoping -void Bytecode_AppendElement(tBC_Function *Handle, const char *Name) - DEF_BC_STR(BC_OP_ELEMENT, Name) -void Bytecode_AppendIndex(tBC_Function *Handle) - DEF_BC_NONE(BC_OP_INDEX) - -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 0d901ebd..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h +++ /dev/null @@ -1,79 +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); -// > Scoping -extern void Bytecode_AppendElement(tBC_Function *Handle, const char *Name); // Obj->SubObj -extern void Bytecode_AppendIndex(tBC_Function *Handle); // Index into an array -// > 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 5affbef0..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c +++ /dev/null @@ -1,133 +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); - 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); - 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 59c58bea..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h +++ /dev/null @@ -1,67 +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_DUPSTACK, // = 13 - BC_OP_DELSTACK, // - BC_OP_CAST, // - - BC_OP_ELEMENT, // = 16 - BC_OP_INDEX, - - BC_OP_ENTERCONTEXT, // = 18 - BC_OP_LEAVECONTEXT, - BC_OP_DEFINEVAR, - - // Operations - BC_OP_LOGICNOT, // 21 - BC_OP_LOGICAND, - BC_OP_LOGICOR, - BC_OP_LOGICXOR, - - BC_OP_BITNOT, // 25 - BC_OP_BITAND, - BC_OP_BITOR, - BC_OP_BITXOR, - - BC_OP_BITSHIFTLEFT, // 29 - BC_OP_BITSHIFTRIGHT, - BC_OP_BITROTATELEFT, - - BC_OP_NEG, // 32 - BC_OP_ADD, - BC_OP_SUBTRACT, - BC_OP_MULTIPLY, - BC_OP_DIVIDE, - BC_OP_MODULO, - - BC_OP_EQUALS, // 38 - 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 b073cbf0..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/exec.c +++ /dev/null @@ -1,342 +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 - -// === IMPORTS === -extern tSpiderFunction *gpExports_First; -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 === -/** - * \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, - tSpiderNamespace *Namespace, const char *Function, - int NArguments, tSpiderValue **Arguments) -{ - int bFound = 0; // Used to keep nesting levels down - tSpiderValue *ret = ERRPTR; - - // First: Find the function in the script - { - tScript_Function *fcn; - for( fcn = Script->Functions; fcn; fcn = fcn->Next ) - { - if( strcmp(fcn->Name, Function) == 0 ) - break; - } - // Execute! - if(fcn) - { - if( fcn->BCFcn ) - ret = Bytecode_ExecuteFunction(Script, fcn, NArguments, Arguments); - else - ret = AST_ExecuteFunction(Script, fcn, NArguments, Arguments); - bFound = 1; - } - } - - // Didn't find it in script? - if(!bFound) - { - tSpiderFunction *fcn; - fcn = NULL; // Just to allow the below code to be neat - - // Second: Scan current namespace - if( !fcn && Namespace ) - { - for( fcn = Namespace->Functions; fcn; fcn = fcn->Next ) - { - if( strcmp( fcn->Name, Function ) == 0 ) - break; - } - } - - // Third: 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; - } - } - - // Execute! - if(fcn) - { - // TODO: Type Checking - ret = fcn->Handler( Script, NArguments, Arguments ); - bFound = 1; - } - } - - // Not found? - if(!bFound) - { - fprintf(stderr, "Undefined reference to function '%s' (ns='%s')\n", - Function, Namespace->Name); - return ERRPTR; - } - - return ret; -} - -/** - * \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, - tSpiderNamespace *Namespace, const char *ClassName, - int NArguments, tSpiderValue **Arguments) -{ - int bFound = 0; // Used to keep nesting levels down - tSpiderValue *ret = ERRPTR; - tSpiderObjectDef *class; - - // 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 - - // Didn't find it in script? - if(!bFound) - { - class = NULL; // Just to allow the below code to be neat - - //if( !Namespace ) - // Namespace = &Script->Variant->RootNamespace; - - // Second: Scan current namespace - if( !class && Namespace ) - { - for( class = Namespace->Classes; class; class = class->Next ) - { - if( strcmp( class->Name, ClassName ) == 0 ) - break; - } - } - - #if 0 - // Third: Search the variant's global exports - if( !class ) - { - for( class = Script->Variant->Classes; class; class = fcn->Next ) - { - if( strcmp( class->Name, Function ) == 0 ) - break; - } - } - #endif - - #if 0 - // Fourth: Search language exports - if( !class ) - { - for( class = gpExports_First; class; class = fcn->Next ) - { - if( strcmp( class->Name, ClassName ) == 0 ) - break; - } - } - #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; - bFound = 1; - } - } - - // Not found? - if(!bFound) - { - fprintf(stderr, "Undefined reference to class '%s'\n", ClassName); - return ERRPTR; - } - - return ret; -} - -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 7a94dc42..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c +++ /dev/null @@ -1,1062 +0,0 @@ -/* - * SpiderScript Library - * - * AST Execution - */ -#include -#include -#include -#include -#include "common.h" -#include "ast.h" - -#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); -// - 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 === -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`) - { - tSpiderNamespace *ns = Block->CurNamespace; - tSpiderValue *params[Node->FunctionCall.NumArgs]; - i = 0; - 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 ++; - } - - if( !ns ) ns = Block->BaseNamespace; - - // Call the function - if( Node->Type == NODETYPE_CREATEOBJECT ) - { - ret = SpiderScript_CreateObject(Block->Script, - ns, - Node->FunctionCall.Name, - 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, - ns, Node->FunctionCall.Name, - Node->FunctionCall.NumArgs, params - ); - } - - - // 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; - - 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; - if( !tmpobj || tmpobj->Type != SS_DATATYPE_OBJECT ) - { - AST_RuntimeError(Node->Scope.Element, "Unable to dereference a non-object"); - ret = ERRPTR; - break ; - } - - for( i = 0; i < tmpobj->Object->Type->NAttributes; i ++ ) - { - if( strcmp(Node->Scope.Name, tmpobj->Object->Type->AttributeDefs[i].Name) == 0 ) - { - ret = tmpobj->Object->Attributes[i]; - SpiderScript_ReferenceValue(ret); - break; - } - } - if( i == tmpobj->Object->Type->NAttributes ) - { - AST_RuntimeError(Node->Scope.Element, "Unknown attribute '%s' of class '%s'", - Node->Scope.Name, tmpobj->Object->Type->Name); - ret = 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( !op1 || op1->Type != SS_DATATYPE_ARRAY ) - { - // TODO: Implement "operator []" on objects - AST_RuntimeError(Node, "Indexing non-array"); - ret = ERRPTR; - break; - } - - if( (!op2 || op2->Type != SS_DATATYPE_INTEGER) && !Block->Script->Variant->bImplicitCasts ) { - AST_RuntimeError(Node, "Array index is not an integer"); - ret = ERRPTR; - break; - } - - if( !op2 || op2->Type != SS_DATATYPE_INTEGER ) - { - tmpobj = SpiderScript_CastValueTo(SS_DATATYPE_INTEGER, op2); - SpiderScript_DereferenceValue(op2); - op2 = tmpobj; - } - - if( op2->Integer >= op1->Array.Length ) { - AST_RuntimeError(Node, "Array index out of bounds %i >= %i", - op2->Integer, op1->Array.Length); - ret = ERRPTR; - break; - } - - ret = op1->Array.Items[ op2->Integer ]; - SpiderScript_ReferenceValue(ret); - - 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; - - // --- 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_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; -} - -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_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_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; -} - -/** - * \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); -} - 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 4673bd28..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c +++ /dev/null @@ -1,806 +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 { - 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: - printf("*%p", Ent->Reference); - 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)); - } - - 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; -} - -#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); - 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(); - // NOTE: Evil, all jumps are off by -1, so fix that - 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; - } - DEBUG_F("[Deref "); PRINT_STACKVAL(local_vars[slot]); DEBUG_F("] "); - Bytecode_int_DerefStackValue( &local_vars[slot] ); - GET_STACKVAL(local_vars[slot]); - PRINT_STACKVAL(local_vars[slot]); - DEBUG_F("\n"); - } 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_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; - } - switch(val2.Type * 100 + val1.Type ) - { - case SS_DATATYPE_INTEGER*100 + SS_DATATYPE_REAL: - val2.Integer = val1.Real; - PUT_STACKVAL(val2); - break; - case SS_DATATYPE_REAL*100 + SS_DATATYPE_INTEGER: - val2.Real = val1.Integer; - PUT_STACKVAL(val2); - break; - default: { - pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1); - pval2 = SpiderScript_CastValueTo(val2.Type, pval1); - if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1); - Bytecode_int_SetSpiderValue(&val2, pval2); - SpiderScript_DereferenceValue(pval2); - PUT_STACKVAL(val2); - } break; - } - 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; - - STATE_HDR(); - DEBUG_F("UNIOP %i\n", ast_op); - - 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_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 - - #define PERFORM_NUM_OP(_type, _field) if(val1.Type == _type && val1.Type == val2.Type) { \ - switch(op->Operation) { \ - case BC_OP_ADD: val1._field = val1._field + val2._field; break; \ - case BC_OP_SUBTRACT: val1._field = val1._field - val2._field; break; \ - case BC_OP_MULTIPLY: val1._field = val1._field * val2._field; break; \ - case BC_OP_DIVIDE: val1._field = val1._field / val2._field; break; \ - case BC_OP_EQUALS: val1._field = val1._field == val2._field; break; \ - case BC_OP_LESSTHAN: val1._field = val1._field < val2._field; break; \ - case BC_OP_LESSTHANOREQUAL: val1._field = val1._field <= val2._field; break; \ - case BC_OP_GREATERTHAN: val1._field = val1._field > val2._field; break; \ - case BC_OP_GREATERTHANOREQUAL: val1._field = val1._field >= val2._field; break; \ - \ - case BC_OP_BITAND: val1._field = (int64_t)val1._field & (int64_t)val2._field; break; \ - case BC_OP_BITOR: val1._field = (int64_t)val1._field | (int64_t)val2._field; break; \ - case BC_OP_BITXOR: val1._field = (int64_t)val1._field ^ (int64_t)val2._field; break; \ - case BC_OP_MODULO: val1._field = (int64_t)val1._field % (int64_t)val2._field; break; \ - default: AST_RuntimeError(NULL, "Invalid operation on datatype %i", _type); nextop = NULL; break;\ - }\ - PUT_STACKVAL(val1);\ - break;\ - } - - PERFORM_NUM_OP(SS_DATATYPE_INTEGER, Integer); - PERFORM_NUM_OP(SS_DATATYPE_REAL, Real); - - pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1); - pval2 = Bytecode_int_GetSpiderValue(&val2, &tmpVal2); - Bytecode_int_DerefStackValue(&val1); - Bytecode_int_DerefStackValue(&val2); - - 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: { - tScript_Function *fcn = NULL; - const char *name = OP_STRING(op); - int arg_count = OP_INDX(op); - - STATE_HDR(); - DEBUG_F("CALL FUNCTION %s %i args\n", name, arg_count); - - if( op->Operation == BC_OP_CALLFUNCTION ) - { - // 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 - { - tSpiderNamespace *ns = NULL; - tSpiderValue *args[arg_count]; - tSpiderValue *rv; - // Read arguments - for( i = arg_count; i --; ) - { - GET_STACKVAL(val1); - args[i] = Bytecode_int_GetSpiderValue(&val1, NULL); - Bytecode_int_DerefStackValue(&val1); - } - - // Resolve namespace into pointer - if( op->Operation != BC_OP_CALLMETHOD ) { - if( name[0] == BC_NS_SEPARATOR ) { - name ++; - ns = Bytecode_int_ResolveNamespace(&Script->Variant->RootNamespace, name, &name); - } - else { - // TODO: Support multiple default namespaces - ns = Bytecode_int_ResolveNamespace(default_namespace, name, &name); - } - } - - // Call the function etc. - if( op->Operation == BC_OP_CALLFUNCTION ) - { - rv = SpiderScript_ExecuteFunction(Script, ns, name, arg_count, args); - } - else if( op->Operation == BC_OP_CREATEOBJ ) - { - rv = SpiderScript_CreateObject(Script, ns, name, 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->Type == SS_DATATYPE_OBJECT) - obj = val1.Reference->Object; - else { - // Error - AST_RuntimeError(NULL, "OP_CALLMETHOD on non object"); - nextop = NULL; - break; - } - 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"); - nextop = NULL; - break; - } - // 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); - } - } 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 ) - { - Bytecode_int_DerefStackValue(&local_vars[i]); - } - } - - // - Restore stack -// printf("TODO: Roll back stack\n"); - if( Stack->Entries[Stack->EntryCount - 1].Type == ET_FUNCTION_START ) - Stack->EntryCount --; - else - { - GET_STACKVAL(val1); - while( Stack->EntryCount && Stack->Entries[ --Stack->EntryCount ].Type != ET_FUNCTION_START ) - { - Bytecode_int_DerefStackValue( &Stack->Entries[Stack->EntryCount] ); - } - PUT_STACKVAL(val1); - } - - - 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 4c73eb9f..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/exports.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Acess2 - SpiderScript - * - Script Exports (Lang. Namespace) - */ -#include -#include -#include -#include - -// === PROTOTYPES === -tSpiderValue *Exports_Lang_Struct(tSpiderScript *Script, int NArgs, tSpiderValue **Args); - -// === GLOBALS === -tSpiderFunction gExports_Lang_Struct = {NULL,"Lang.Struct", Exports_Lang_Struct, {SS_DATATYPE_STRING,-1}}; -tSpiderFunction *gpExports_First = &gExports_Lang_Struct; - -// === CODE === -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 2d16bcfb..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/lex.c +++ /dev/null @@ -1,468 +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 '!': - 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 bd292805..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/main.c +++ /dev/null @@ -1,145 +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; - printf("Total Size: "); - fflush(stdout); - size = AST_WriteScript(NULL, Script); - printf("0x%x bytes\n", (unsigned)size); - - 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 e6d96942..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/parse.c +++ /dev/null @@ -1,1082 +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 *Parse_DoBlockLine(tParser *Parser); -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, ...); - -#define SyntaxAssert(_parser, _have, _want) 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 NULL; \ - } \ -}while(0) - -#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; - - 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(GetToken(Parser)) - { - // Define a function (pass on to the other function definition code) - case TOK_IDENT: - PutBack(Parser); - if( Parse_FunctionDefinition(Script, Parser, type) == NULL ) - longjmp(Parser->JmpTarget, -1); - break ; - // Define a variable - case TOK_VARIABLE: - node = Parse_GetVarDef(Parser, type); - if(!node) longjmp(Parser->JmpTarget, -1); - - AST_AppendNode( mainCode, node ); - // Can't use SyntaxAssert because that returns - if(GetToken(Parser) != TOK_SEMICOLON) { - SyntaxError(Parser, 1, "Unexpected %s, expected TOK_SEMICOLON", - csaTOKEN_NAMES[Parser->Token]); - longjmp(Parser->JmpTarget, -1); - } - 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); - 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); - - 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 *ret; - - // Check if we are being called for a one-liner - if( GetToken(Parser) != TOK_BRACE_OPEN ) { - PutBack(Parser); - return Parse_DoBlockLine(Parser); - } - - ret = AST_NewCodeBlock(Parser); - - while( LookAhead(Parser) != TOK_BRACE_CLOSE ) - { - tAST_Node *node = Parse_DoBlockLine(Parser); - 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 *ret; - - //printf("Parse_DoBlockLine: Line %i\n", Parser->CurLine); - - switch(LookAhead(Parser)) - { - // New block - case TOK_BRACE_OPEN: - return Parse_DoCodeBlock(Parser); - - // 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); - if( LookAhead(Parser) == TOK_RWD_ELSE ) { - GetToken(Parser); - false = Parse_DoCodeBlock(Parser); - } - 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); - 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); - 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); - 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); - - SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE); - - ret = Parse_GetVarDef(Parser, type); - } - break; - - // Default - default: - //printf("exp0\n"); - ret = Parse_DoExpr0(Parser); - break; - } - - SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON ); - return ret; -} - -/** - * \brief Get a variable definition - */ -tAST_Node *Parse_GetVarDef(tParser *Parser, int Type) -{ - char name[Parser->TokenLen]; - tAST_Node *ret; - - 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 - while( LookAhead(Parser) == TOK_SQUARE_OPEN ) - { - tAST_Node *node; - GetToken(Parser); - node = Parse_DoExpr0(Parser); - if(!node) { - AST_FreeNode(ret); - return NULL; - } - AST_AppendNode(ret, node); - SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE); - } - - if( LookAhead(Parser) == TOK_ASSIGN ) - { - GetToken(Parser); - ret->DefVar.InitialValue = Parse_DoExpr0(Parser); - if(!ret->DefVar.InitialValue) { - AST_FreeNode(ret); - return NULL; - } - } - - 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_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_NewNop(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; - } -} - diff --git a/Usermode/Libraries/libspiderscript.so_src/tokens.h b/Usermode/Libraries/libspiderscript.so_src/tokens.h deleted file mode 100644 index 44176b0b..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/tokens.h +++ /dev/null @@ -1,200 +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; -} 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_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_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 f72e2903..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/values.c +++ /dev/null @@ -1,461 +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, int Operation, int bCanCast, tSpiderValue *Right); -tSpiderValue *SpiderScript_int_DoOpInt(tSpiderValue *Left, int Operation, int bCanCast, tSpiderValue *Right); -tSpiderValue *SpiderScript_int_DoOpReal(tSpiderValue *Left, int Operation, int bCanCast, tSpiderValue *Right); -tSpiderValue *SpiderScript_int_DoOpString(tSpiderValue *Left, int Operation, int bCanCast, tSpiderValue *Right); - - -// === CODE === -/** - * \brief Dereference a created object - */ -void SpiderScript_DereferenceValue(tSpiderValue *Object) -{ - if(!Object || Object == ERRPTR) return ; - Object->ReferenceCount --; - if(Object->Type == SS_DATATYPE_OBJECT) { - } - if( Object->ReferenceCount == 0 ) - { - 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; -} - -/** - * \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, int Operation, int bCanCast, tSpiderValue *Right) -{ - switch(Left->Type) - { - case SS_DATATYPE_INTEGER: - return SpiderScript_int_DoOpInt(Left, Operation, bCanCast, Right); - } - return NULL; -} - -tSpiderValue *SpiderScript_int_DoOpInt(tSpiderValue *Left, int Operation, int bCanCast, tSpiderValue *Right) -{ - tSpiderValue *oldright = Right; - tSpiderValue *ret = NULL; - int64_t rv; - - // Casting - if(Right && Right->Type != SS_DATATYPE_INTEGER) { - if(!bCanCast) return ERRPTR; - Right = SpiderScript_CastValueTo(Right, SS_DATATYPE_INTEGER); - } - - // 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; - } - - // 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); - } -} - diff --git a/Usermode/include/spiderscript.h b/Usermode/include/spiderscript.h deleted file mode 100644 index e1dc5078..00000000 --- a/Usermode/include/spiderscript.h +++ /dev/null @@ -1,321 +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 - */ - 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 -}; - -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); - - tSpiderFunction *Methods; //!< Method Definitions (linked list) - - int NAttributes; //!< Number of attributes - - //! Attribute definitions - struct { - const char *Name; //!< Attribute Name - int bReadOnly; //!< Allow writes to the attribute? - } 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 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, - tSpiderNamespace *Namespace, const char *Function, - int NArguments, tSpiderValue **Arguments - ); -/** - * \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, - tSpiderNamespace *Namespace, const char *ClassName, - 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_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