// Define a variable
case NODETYPE_DEFVAR:
- WRITE_8(Buffer, Offset, Node->DefVar.DataType);
+ WRITE_32(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;
// 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;
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 *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);
struct {
int DataType;
- tAST_Node *LevelSizes;
- tAST_Node *LevelSizes_Last;
tAST_Node *InitialValue;
char Name[];
} DefVar;
extern tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node);
extern tSpiderValue *AST_ExecuteNode_BinOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Left, tSpiderValue *Right);
extern tSpiderValue *AST_ExecuteNode_UniOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Value);
+extern tSpiderValue *AST_ExecuteNode_Index(tSpiderScript *Script, tAST_Node *Node, tSpiderValue *Array, int Index, tSpiderValue *SaveValue);
#endif
ret->Operation = Operation;
ret->bUseInteger = 0;
ret->bUseString = (ExtraBytes > 0);
+ ret->CacheEnt = NULL;
return ret;
}
// Check for this level
for( ns = lastns->FirstChild; ns; ns = ns->Next )
{
- printf("%p %.*s == %s\n", lastns, len, name, ns->Name);
+// printf("%p %.*s == %s\n", lastns, len, name, ns->Name);
if( strncmp(name, ns->Name, len) == 0 && ns->Name[len] == 0 )
break ;
}
{
tSpiderValue *ret = ERRPTR;
tSpiderFunction *fcn = NULL;
+ tScript_Function *sfcn;
int i;
+ if( FunctionIdent && *FunctionIdent ) {
+ if( *(intptr_t*)FunctionIdent & 1 ) {
+ sfcn = (void*)( *(intptr_t*)FunctionIdent & ~1 );
+ goto _exec_sfcn;
+ }
+ else {
+ fcn = *FunctionIdent;
+ goto _exec_fcn;
+ }
+ }
+
// Scan list, Last item should always be NULL, so abuse that to check non-prefixed
for( i = 0; i == 0 || (DefaultNamespaces && DefaultNamespaces[i-1]); i ++ )
{
// TODO: Script namespacing
if( !fcn && strchr(Function, BC_NS_SEPARATOR) == NULL )
{
- tScript_Function *sfcn;
for( sfcn = Script->Functions; sfcn; sfcn = sfcn->Next )
{
if( strcmp(sfcn->Name, Function) == 0 )
break;
}
+ _exec_sfcn:
// Execute!
if(sfcn)
{
return ret;
}
}
-
+
+_exec_fcn:
if(fcn)
{
// Execute!
tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node);
tSpiderValue *AST_ExecuteNode_BinOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Left, tSpiderValue *Right);
tSpiderValue *AST_ExecuteNode_UniOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Value);
+tSpiderValue *AST_ExecuteNode_Index(tSpiderScript *Script, tAST_Node *Node, tSpiderValue *Array, int Index, tSpiderValue *SaveValue);
// - Variables
tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name, tSpiderValue *Value);
int Variable_SetValue(tAST_BlockState *Block, tAST_Node *VarNode, tSpiderValue *Value);
break;
}
- switch( op1->Type )
- {
- case SS_DATATYPE_ARRAY:
- 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);
- break;
-
- default:
- // TODO: Implement "operator []" on objects
- AST_RuntimeError(Node, "Indexing non-array");
- ret = ERRPTR;
- break;
- }
-
+ ret = AST_ExecuteNode_Index(Block->Script, Node, op1, op2->Integer, NULL);
+
SpiderScript_DereferenceValue(op1);
SpiderScript_DereferenceValue(op2);
break;
return ret;
}
+tSpiderValue *AST_ExecuteNode_Index(tSpiderScript *Script, tAST_Node *Node,
+ tSpiderValue *Array, int Index, tSpiderValue *SaveValue)
+{
+ // Quick sanity check
+ if( !Array )
+ {
+ AST_RuntimeError(Node, "Indexing NULL, not a good idea");
+ return ERRPTR;
+ }
+
+ // Array?
+ if( SS_GETARRAYDEPTH(Array->Type) )
+ {
+ if( Index < 0 || Index >= Array->Array.Length ) {
+ AST_RuntimeError(Node, "Array index out of bounds %i not in (0, %i]",
+ Index, Array->Array.Length);
+ return ERRPTR;
+ }
+
+ if( SaveValue )
+ {
+ if( SaveValue->Type != SS_DOWNARRAY(Array->Type) ) {
+ // TODO: Implicit casting
+ AST_RuntimeError(Node, "Type mismatch assiging to array element");
+ return ERRPTR;
+ }
+ SpiderScript_DereferenceValue( Array->Array.Items[Index] );
+ Array->Array.Items[Index] = SaveValue;
+ SpiderScript_ReferenceValue( Array->Array.Items[Index] );
+ return NULL;
+ }
+ else
+ {
+ SpiderScript_ReferenceValue( Array->Array.Items[Index] );
+ return Array->Array.Items[Index];
+ }
+ }
+ else
+ {
+ AST_RuntimeError(Node, "TODO - Implement indexing on non-arrays (type = %x)",
+ Array->Type);
+ return ERRPTR;
+ }
+}
+
#if USE_AST_EXEC
/**
* \brief Define a variable
tmp = malloc(sizeof(tSpiderValue));
tmp->ReferenceCount = 1;
} else {
+ // Stops a stack value from having free() called on it
tmp->ReferenceCount = 2;
}
break;
printf("Obj %p", Ent->Object);
break;
default:
- printf("*%p", Ent->Reference);
+ if( Ent->Reference )
+ printf("*%p (%i refs)", Ent->Reference, Ent->Reference->ReferenceCount);
+ else
+ printf("NULL");
break;
}
}
if(ret == &tmpsval) {
ret = malloc(sizeof(tSpiderValue));
memcpy(ret, &tmpsval, sizeof(tSpiderValue));
+ // Set to 2 in _GetSpiderValue, so stack doesn't have free() called
+ ret->ReferenceCount = 1;
}
return ret;
PUT_STACKVAL(val1);
// Deref return
SpiderScript_DereferenceValue(rv);
-
- return ret;
+
+ #if 0
+ if(!rv) {
+ printf("%s returned NULL\n", name);
+ }
+ if( rv && rv != ERRPTR && rv->ReferenceCount != 1 ) {
+ printf("Return value from %s reference count fail (%i)\n",
+ name, rv->ReferenceCount);
+ }
+ #endif
+
+ return 0;
}
int Bytecode_int_LocalBinOp_Integer(int Operation, tBC_StackEnt *Val1, tBC_StackEnt *Val2)
AST_RuntimeError(NULL, "Loading from invalid slot %i", slot);
return -1;
}
+ // Remove whatever was in there before
DEBUG_F("[Deref "); PRINT_STACKVAL(local_vars[slot]); DEBUG_F("] ");
Bytecode_int_DerefStackValue( &local_vars[slot] );
+ // Place new in
GET_STACKVAL(local_vars[slot]);
PRINT_STACKVAL(local_vars[slot]);
DEBUG_F("\n");
} break;
+ case BC_OP_INDEX:
+ case BC_OP_SETINDEX:
+ STATE_HDR();
+ GET_STACKVAL(val1); // Index
+ // TODO: Check that index is an integer
+ if( val1.Type != SS_DATATYPE_INTEGER ) {
+ nextop = NULL;
+ break;
+ }
+
+ // Get array as raw spider value
+ GET_STACKVAL(val2); // Array
+ pval1 = Bytecode_int_GetSpiderValue(&val2, &tmpVal1);
+ Bytecode_int_DerefStackValue(&val2);
+
+ if( op->Operation == BC_OP_SETINDEX ) {
+ GET_STACKVAL(val2);
+ pval2 = Bytecode_int_GetSpiderValue(&val2, NULL);
+ Bytecode_int_DerefStackValue(&val2);
+
+ ret_val = AST_ExecuteNode_Index(Script, NULL, pval1, val1.Integer, pval2);
+ if(ret_val == ERRPTR) { nextop = NULL; break; }
+ SpiderScript_DereferenceValue(pval2);
+ }
+ else {
+ ret_val = AST_ExecuteNode_Index(Script, NULL, pval1, val1.Integer, NULL);
+ if(ret_val == ERRPTR) { nextop = NULL; break; }
+
+ Bytecode_int_SetSpiderValue(&val1, ret_val);
+ SpiderScript_DereferenceValue(ret_val);
+ PUT_STACKVAL(val1);
+ }
+ // Dereference the stack
+ if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1);
+ break;
+ case BC_OP_ELEMENT:
+ case BC_OP_SETELEMENT:
+ STATE_HDR();
+ AST_RuntimeError(NULL, "TODO: Impliment ELEMENT/SETELEMENT");
+ nextop = NULL;
+ break;
+
// Constants:
case BC_OP_LOADINT:
STATE_HDR();
else {
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);
+
+ if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1);
+ Bytecode_int_DerefStackValue(&val1);
+// printf("CAST (%x->%x) - Original %i references remaining\n",
+// pval1->Type, OP_INDX(op),
+// pval1->ReferenceCount);
}
PUT_STACKVAL(val2);
break;
{
if( local_vars[i].Type != ET_NULL )
{
+ DEBUG_F("Var %i - ", i);
+ PRINT_STACKVAL(local_vars[i]);
Bytecode_int_DerefStackValue(&local_vars[i]);
+ DEBUG_F("\n");
}
+ else
+ DEBUG_F("Var %i - empty\n", i);
}
// - Restore stack
* Acess2 - SpiderScript
* - Script Exports (Lang. Namespace)
*/
+#define _GNU_SOURCE // HACK!
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
// === PROTOTYPES ===
tSpiderValue *Exports_sizeof(tSpiderScript *Script, int NArgs, tSpiderValue **Args);
+tSpiderValue *Exports_array(tSpiderScript *Script, int NArgs, tSpiderValue **Args);
tSpiderValue *Exports_Lang_Strings_Split(tSpiderScript *Script, int NArgs, tSpiderValue **Args);
tSpiderValue *Exports_Lang_Struct(tSpiderScript *Script, int NArgs, tSpiderValue **Args);
};
// -- Global Functions
+tSpiderFunction gExports_array = {
+ .Next = NULL,
+ .Name = "array",
+ .Handler = Exports_array,
+ .ReturnType = SS_DATATYPE_DYNAMIC,
+ .ArgTypes = {SS_DATATYPE_INTEGER, -1}
+};
tSpiderFunction gExports_sizeof = {
+ .Next = &gExports_array,
.Name = "sizeof",
.Handler = Exports_sizeof,
.ReturnType = SS_DATATYPE_INTEGER,
.ArgTypes = {SS_DATATYPE_UNDEF, -1}
};
-tSpiderFunction *gpExports_First;
+tSpiderFunction *gpExports_First = &gExports_sizeof;
// === CODE ===
tSpiderValue *Exports_sizeof(tSpiderScript *Script, int NArgs, tSpiderValue **Args)
}
}
+tSpiderValue *Exports_array(tSpiderScript *Script, int NArgs, tSpiderValue **Args)
+{
+ if(NArgs != 2) return ERRPTR;
+ if(!Args[0] || !Args[1]) return ERRPTR;
+
+ if(Args[0]->Type != SS_DATATYPE_INTEGER || Args[1]->Type != SS_DATATYPE_INTEGER)
+ return ERRPTR;
+
+ int type = Args[1]->Integer;
+ int size = Args[0]->Integer;
+
+ if( type != SS_DATATYPE_ARRAY )
+ {
+ if( !SS_GETARRAYDEPTH(type) ) {
+ // ERROR - This should never happen
+ return ERRPTR;
+ }
+ type = SS_DOWNARRAY(type);
+ }
+
+ return SpiderScript_CreateArray(type, size);
+}
+
tSpiderValue *Exports_Lang_Strings_Split(tSpiderScript *Script, int NArgs, tSpiderValue **Args)
{
- return NULL;
+ int len, ofs, slen;
+ void *haystack, *end;
+ int nSubStrs = 0;
+ tSpiderValue **strings = NULL;
+ tSpiderValue *ret;
+
+ // Error checking
+ if( NArgs != 2 )
+ return ERRPTR;
+ if( !Args[0] || !Args[1] )
+ return ERRPTR;
+ if( Args[0]->Type != SS_DATATYPE_STRING )
+ return ERRPTR;
+ if( Args[1]->Type != SS_DATATYPE_STRING )
+ return ERRPTR;
+
+ // Split the string
+ len = Args[0]->String.Length;
+ haystack = Args[0]->String.Data;
+ ofs = 0;
+ do {
+ end = memmem(haystack + ofs, len - ofs, Args[1]->String.Data, Args[1]->String.Length);
+ if( end )
+ slen = end - (haystack + ofs);
+ else
+ slen = len - ofs;
+
+ strings = realloc(strings, (nSubStrs+1)*sizeof(tSpiderValue*));
+ strings[nSubStrs] = SpiderScript_CreateString(slen, haystack + ofs);
+ nSubStrs ++;
+
+ ofs += slen + Args[1]->String.Length;
+ } while(end);
+
+ // Create output array
+ ret = SpiderScript_CreateArray(SS_DATATYPE_STRING, nSubStrs);
+ memcpy(ret->Array.Items, strings, nSubStrs*sizeof(tSpiderValue*));
+ free(strings);
+
+ return ret;
}
tSpiderValue *Exports_Lang_Struct(tSpiderScript *Script, int NArgs, tSpiderValue **Args)
// === 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_DoCodeBlock(tParser *Parser, tAST_Node *CodeNode);
+tAST_Node *Parse_DoBlockLine(tParser *Parser, tAST_Node *CodeNode);
+tAST_Node *Parse_VarDefList(tParser *Parser, tAST_Node *CodeNode, int Type);
tAST_Node *Parse_GetVarDef(tParser *Parser, int Type);
tAST_Node *Parse_DoExpr0(tParser *Parser); // Assignment
void SyntaxAssert(tParser *Parser, int Have, int Want);
void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...);
-#define SyntaxAssert(_parser, _have, _want) do { \
+#if 0
+#define SyntaxAssert(_parser, _have, _want) SyntaxAssertV(_parser, _have, _want, NULL)
+#define SyntaxAssertV(_parser, _have, _want, _rv) do { \
int have = (_have), want = (_want); \
if( (have) != (want) ) { \
SyntaxError(Parser, 1, "Unexpected %s(%i), expecting %s(%i)\n", \
csaTOKEN_NAMES[have], have, csaTOKEN_NAMES[want], want); \
- return NULL; \
+ return _rv; \
} \
}while(0)
+#endif
#define TODO(Parser, message...) do {\
fprintf(stderr, "TODO: "message);\
case TOKEN_GROUP_TYPES:
TOKEN_GET_DATATYPE(type, Parser->Token);
- switch(GetToken(Parser))
+ switch(LookAhead(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
+ // Define a variable (pass back to _DoBlockLine)
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);
- }
+ node = Parse_VarDefList(Parser, mainCode, type);
+ AST_AppendNode(mainCode, node);
+ SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
break;
default:
SyntaxError(Parser, 1, "Unexpected %s, expected TOK_IDENT or TOK_VARIABLE\n",
// Ordinary Statement
default:
PutBack(Parser);
- node = Parse_DoBlockLine(Parser);
+ node = Parse_DoBlockLine(Parser, mainCode);
if(!node) longjmp(Parser->JmpTarget, -1);
AST_AppendNode( mainCode, node );
break;
GetToken(Parser);
SyntaxAssert(Parser, Parser->Token, TOK_PAREN_CLOSE );
- code = Parse_DoCodeBlock(Parser);
+ code = Parse_DoCodeBlock(Parser, NULL);
rv = AST_AppendFunction( Script, name, Type, first_arg, code );
/**
* \brief Parse a block of code surrounded by { }
*/
-tAST_Node *Parse_DoCodeBlock(tParser *Parser)
+tAST_Node *Parse_DoCodeBlock(tParser *Parser, tAST_Node *CodeNode)
{
tAST_Node *ret;
// Check if we are being called for a one-liner
if( GetToken(Parser) != TOK_BRACE_OPEN ) {
PutBack(Parser);
- return Parse_DoBlockLine(Parser);
+ return Parse_DoBlockLine(Parser, CodeNode);
}
ret = AST_NewCodeBlock(Parser);
while( LookAhead(Parser) != TOK_BRACE_CLOSE )
{
- tAST_Node *node = Parse_DoBlockLine(Parser);
+ tAST_Node *node = Parse_DoBlockLine(Parser, ret);
if(!node) {
AST_FreeNode(ret);
return NULL;
/**
* \brief Parse a line in a block
*/
-tAST_Node *Parse_DoBlockLine(tParser *Parser)
+tAST_Node *Parse_DoBlockLine(tParser *Parser, tAST_Node *CodeNode)
{
tAST_Node *ret;
{
// New block
case TOK_BRACE_OPEN:
- return Parse_DoCodeBlock(Parser);
+ return Parse_DoCodeBlock(Parser, CodeNode);
// Empty statement
case TOK_SEMICOLON:
SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
cond = Parse_DoExpr0(Parser); // Get condition
SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
- true = Parse_DoCodeBlock(Parser);
+ true = Parse_DoCodeBlock(Parser, CodeNode);
if( LookAhead(Parser) == TOK_RWD_ELSE ) {
GetToken(Parser);
- false = Parse_DoCodeBlock(Parser);
+ false = Parse_DoCodeBlock(Parser, CodeNode);
}
else
false = AST_NewNop(Parser);
SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
- code = Parse_DoCodeBlock(Parser);
+ code = Parse_DoCodeBlock(Parser, CodeNode);
ret = AST_NewLoop(Parser, tag, init, 0, cond, inc, code);
if(tag) free(tag);
}
}
#endif
- code = Parse_DoCodeBlock(Parser);
+ code = Parse_DoCodeBlock(Parser, CodeNode);
SyntaxAssert( Parser, GetToken(Parser), TOK_RWD_WHILE );
SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
cond = Parse_DoExpr0(Parser);
SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
cond = Parse_DoExpr0(Parser);
SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
- code = Parse_DoCodeBlock(Parser);
+ code = Parse_DoCodeBlock(Parser, CodeNode);
ret = AST_NewLoop(Parser, tag, AST_NewNop(Parser), 0, cond, AST_NewNop(Parser), code);
}
return ret;
int type;
GetToken(Parser);
TOKEN_GET_DATATYPE(type, Parser->Token);
-
- SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
-
- ret = Parse_GetVarDef(Parser, type);
+ ret = Parse_VarDefList(Parser, CodeNode, type);
}
break;
return ret;
}
+tAST_Node *Parse_VarDefList(tParser *Parser, tAST_Node *CodeNode, int Type)
+{
+ tAST_Node *ret;
+
+ ret = NULL;
+ do {
+ if(ret) AST_AppendNode( CodeNode, ret );
+ SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
+
+ ret = Parse_GetVarDef(Parser, Type);
+ if(!ret) longjmp(Parser->JmpTarget, -1);
+ } while(GetToken(Parser) == TOK_COMMA);
+ PutBack(Parser); // Semicolon is checked by caller
+
+ return ret;
+}
+
/**
* \brief Get a variable definition
*/
ret = AST_NewDefineVar(Parser, Type, name);
// Handle arrays
level = 0;
- while( LookAhead(Parser) == TOK_SQUARE_OPEN )
+ if( LookAhead(Parser) == TOK_SQUARE_OPEN )
{
- tAST_Node *node;
GetToken(Parser);
- node = Parse_DoExpr0(Parser);
- if(!node) {
- AST_FreeNode(ret);
- return NULL;
+ if( LookAhead(Parser) != TOK_SQUARE_CLOSE )
+ {
+ ret->DefVar.InitialValue = AST_NewFunctionCall(Parser, "array");
+ AST_AppendFunctionCallArg(ret->DefVar.InitialValue, Parse_DoExpr0(Parser));
}
- AST_AppendNode(ret, node);
+ SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
+
+ level ++;
+ }
+ while( LookAhead(Parser) == TOK_SQUARE_OPEN )
+ {
+ GetToken(Parser);
SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
level ++;
}
// Initial value
if( LookAhead(Parser) == TOK_ASSIGN )
{
+ if( ret->DefVar.InitialValue )
+ {
+ SyntaxError(Parser, 1, "Cannot assign and set array size at the same time");
+ }
GetToken(Parser);
ret->DefVar.InitialValue = Parse_DoExpr0(Parser);
if(!ret->DefVar.InitialValue) {
return NULL;
}
}
+ else if( ret->DefVar.InitialValue )
+ {
+ AST_AppendFunctionCallArg(ret->DefVar.InitialValue, AST_NewInteger(Parser, ret->DefVar.DataType));
+ }
return ret;
}
}
}
+void SyntaxAssert(tParser *Parser, int Have, int Want)
+{
+ if( Have != Want )
+ {
+ SyntaxError(Parser, 1, "Unexpected %s(%i), expecting %s(%i)\n",
+ csaTOKEN_NAMES[Have], Have, csaTOKEN_NAMES[Want], Want);
+ }
+}
{
if(!Object || Object == ERRPTR) return ;
Object->ReferenceCount --;
-// if(Object->Type == SS_DATATYPE_OBJECT) {
-// }
if( Object->ReferenceCount == 0 )
{
- switch( (enum eSpiderScript_DataTypes) Object->Type )
+ int i;
+
+ if( Object->Type == SS_DATATYPE_ARRAY || SS_GETARRAYDEPTH(Object->Type) )
{
- case SS_DATATYPE_OBJECT:
- Object->Object->ReferenceCount --;
- if(Object->Object->ReferenceCount == 0) {
- Object->Object->Type->Destructor( Object->Object );
+ for( i = 0; i < Object->Array.Length; i ++ )
+ {
+ if( Object->Array.Items[i] ) {
+ SpiderScript_DereferenceValue(Object->Array.Items[i]);
+ }
+ Object->Array.Items[i] = NULL;
+ }
+ }
+ else
+ {
+ switch( (enum eSpiderScript_DataTypes) Object->Type )
+ {
+ case SS_DATATYPE_OBJECT:
+ Object->Object->ReferenceCount --;
+ if(Object->Object->ReferenceCount == 0) {
+ Object->Object->Type->Destructor( Object->Object );
+ }
+ Object->Object = NULL;
+ break;
+
+ case SS_DATATYPE_OPAQUE:
+ Object->Opaque.Destroy( Object->Opaque.Data );
+ break;
+ default:
+ break;
}
- Object->Object = NULL;
- break;
-
- case SS_DATATYPE_OPAQUE:
- Object->Opaque.Destroy( Object->Opaque.Data );
- break;
- default:
- break;
}
free(Object);
}
return ret;
}
+tSpiderValue *SpiderScript_CreateArray(int InnerType, int ItemCount)
+{
+ tSpiderValue *ret = malloc( sizeof(tSpiderValue) + ItemCount*sizeof(tSpiderValue*) );
+ ret->Type = SS_MAKEARRAY(InnerType);
+ ret->ReferenceCount = 1;
+ ret->Array.Length = ItemCount;
+ memset(ret->Array.Items, 0, ItemCount*sizeof(tSpiderValue*));
+ return ret;
+}
+
/**
* \brief Concatenate two strings
*/
extern tSpiderValue *SpiderScript_CreateInteger(uint64_t Value);
extern tSpiderValue *SpiderScript_CreateReal(double Value);
extern tSpiderValue *SpiderScript_CreateString(int Length, const char *Data);
+extern tSpiderValue *SpiderScript_CreateArray(int InnerType, int ItemCount);
extern tSpiderValue *SpiderScript_StringConcat(const tSpiderValue *Str1, const tSpiderValue *Str2);
extern tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source);
extern int SpiderScript_IsValueTrue(tSpiderValue *Value);