3 * by John Hodge (thePowersGang)
6 * - Manage tSpiderValue objects
11 #include "spiderscript.h"
14 extern void AST_RuntimeError(void *Node, const char *Format, ...);
17 void SpiderScript_DereferenceValue(tSpiderValue *Object);
18 void SpiderScript_ReferenceValue(tSpiderValue *Object);
19 tSpiderValue *SpiderScript_CreateInteger(uint64_t Value);
20 tSpiderValue *SpiderScript_CreateReal(double Value);
21 tSpiderValue *SpiderScript_CreateString(int Length, const char *Data);
22 tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source);
23 int SpiderScript_IsValueTrue(tSpiderValue *Value);
24 void SpiderScript_FreeValue(tSpiderValue *Value);
25 char *SpiderScript_DumpValue(tSpiderValue *Value);
29 * \brief Dereference a created object
31 void SpiderScript_DereferenceValue(tSpiderValue *Object)
33 if(!Object || Object == ERRPTR) return ;
34 Object->ReferenceCount --;
35 if(Object->Type == SS_DATATYPE_OBJECT) {
37 if( Object->ReferenceCount == 0 )
39 switch( (enum eSpiderScript_DataTypes) Object->Type )
41 case SS_DATATYPE_OBJECT:
42 Object->Object->ReferenceCount --;
43 if(Object->Object->ReferenceCount == 0) {
44 Object->Object->Type->Destructor( Object->Object );
46 Object->Object = NULL;
49 case SS_DATATYPE_OPAQUE:
50 Object->Opaque.Destroy( Object->Opaque.Data );
60 * \brief Reference a value
62 void SpiderScript_ReferenceValue(tSpiderValue *Object)
64 if(!Object || Object == ERRPTR) return ;
65 Object->ReferenceCount ++;
69 * \brief Allocate and initialise a SpiderScript object
71 tSpiderObject *SpiderScript_AllocateObject(tSpiderObjectDef *Class, int ExtraBytes)
73 int size = sizeof(tSpiderObject) + Class->NAttributes * sizeof(tSpiderValue*) + ExtraBytes;
74 tSpiderObject *ret = malloc(size);
77 ret->ReferenceCount = 1;
78 ret->OpaqueData = &ret->Attributes[ Class->NAttributes ];
79 memset( ret->Attributes, 0, Class->NAttributes * sizeof(tSpiderValue*) );
85 * \brief Create an integer object
87 tSpiderValue *SpiderScript_CreateInteger(uint64_t Value)
89 tSpiderValue *ret = malloc( sizeof(tSpiderValue) );
90 ret->Type = SS_DATATYPE_INTEGER;
91 ret->ReferenceCount = 1;
97 * \brief Create an real number object
99 tSpiderValue *SpiderScript_CreateReal(double Value)
101 tSpiderValue *ret = malloc( sizeof(tSpiderValue) );
102 ret->Type = SS_DATATYPE_REAL;
103 ret->ReferenceCount = 1;
109 * \brief Create an string object
111 tSpiderValue *SpiderScript_CreateString(int Length, const char *Data)
113 tSpiderValue *ret = malloc( sizeof(tSpiderValue) + Length + 1 );
114 ret->Type = SS_DATATYPE_STRING;
115 ret->ReferenceCount = 1;
116 ret->String.Length = Length;
118 memcpy(ret->String.Data, Data, Length);
120 memset(ret->String.Data, 0, Length);
121 ret->String.Data[Length] = '\0';
126 * \brief Concatenate two strings
128 tSpiderValue *SpiderScript_StringConcat(const tSpiderValue *Str1, const tSpiderValue *Str2)
133 if( Str1 && Str1->Type != SS_DATATYPE_STRING)
135 if( Str2 && Str2->Type != SS_DATATYPE_STRING)
138 if(Str1) newLen += Str1->String.Length;
139 if(Str2) newLen += Str2->String.Length;
140 ret = malloc( sizeof(tSpiderValue) + newLen + 1 );
141 ret->Type = SS_DATATYPE_STRING;
142 ret->ReferenceCount = 1;
143 ret->String.Length = newLen;
145 memcpy(ret->String.Data, Str1->String.Data, Str1->String.Length);
148 memcpy(ret->String.Data+Str1->String.Length, Str2->String.Data, Str2->String.Length);
150 memcpy(ret->String.Data, Str2->String.Data, Str2->String.Length);
152 ret->String.Data[ newLen ] = '\0';
157 * \brief Cast one object to another
158 * \brief Type Destination type
159 * \brief Source Input data
161 tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source)
163 tSpiderValue *ret = ERRPTR;
170 case SS_DATATYPE_INTEGER: return SpiderScript_CreateInteger(0);
171 case SS_DATATYPE_REAL: return SpiderScript_CreateReal(0);
172 case SS_DATATYPE_STRING: return SpiderScript_CreateString(4, "null");
177 // Check if anything needs to be done
178 if( Source->Type == Type ) {
179 SpiderScript_ReferenceValue(Source);
186 printf("Casting %i ", Source->Type);
189 case SS_DATATYPE_INTEGER: printf("0x%lx", Source->Integer); break;
190 case SS_DATATYPE_STRING: printf("\"%s\"", Source->String.Data); break;
191 case SS_DATATYPE_REAL: printf("%f", Source->Real); break;
194 printf(" to %i\n", Type);
200 if( Source->Type == SS_DATATYPE_OBJECT )
202 const char *name = NULL;
205 case SS_DATATYPE_INTEGER: name = "cast Integer"; break;
206 case SS_DATATYPE_REAL: name = "cast Real"; break;
207 case SS_DATATYPE_STRING: name = "cast String"; break;
208 case SS_DATATYPE_ARRAY: name = "cast Array"; break;
210 AST_RuntimeError(NULL, "Invalid cast to %i from Object", Type);
215 ret = Object_ExecuteMethod(Left->Object, fcnname, Right);
218 // Fall through and try casting (which will usually fail)
223 switch( (enum eSpiderScript_DataTypes)Type )
225 case SS_DATATYPE_UNDEF:
226 case SS_DATATYPE_ARRAY:
227 case SS_DATATYPE_OPAQUE:
228 AST_RuntimeError(NULL, "Invalid cast to %i", Type);
230 case SS_DATATYPE_OBJECT:
232 AST_RuntimeError(NULL, "Invalid cast to %i", Type);
235 case SS_DATATYPE_INTEGER:
236 ret = malloc(sizeof(tSpiderValue));
237 ret->Type = SS_DATATYPE_INTEGER;
238 ret->ReferenceCount = 1;
241 case SS_DATATYPE_INTEGER: break; // Handled above
242 case SS_DATATYPE_STRING: ret->Integer = atoi(Source->String.Data); break;
243 case SS_DATATYPE_REAL: ret->Integer = Source->Real; break;
245 AST_RuntimeError(NULL, "Invalid cast from %i to Integer", Source->Type);
252 case SS_DATATYPE_REAL:
253 ret = malloc(sizeof(tSpiderValue));
254 ret->Type = SS_DATATYPE_REAL;
255 ret->ReferenceCount = 1;
258 case SS_DATATYPE_STRING: ret->Real = atof(Source->String.Data); break;
259 case SS_DATATYPE_INTEGER: ret->Real = Source->Integer; break;
261 AST_RuntimeError(NULL, "Invalid cast from %i to Real", Source->Type);
268 case SS_DATATYPE_STRING:
271 case SS_DATATYPE_INTEGER: len = snprintf(NULL, 0, "%li", Source->Integer); break;
272 case SS_DATATYPE_REAL: len = snprintf(NULL, 0, "%g", Source->Real); break;
275 ret = malloc(sizeof(tSpiderValue) + len + 1);
276 ret->Type = SS_DATATYPE_STRING;
277 ret->ReferenceCount = 1;
278 ret->String.Length = len;
281 case SS_DATATYPE_INTEGER: sprintf(ret->String.Data, "%li", Source->Integer); break;
282 case SS_DATATYPE_REAL:
283 sprintf(ret->String.Data, "%g", Source->Real); break;
285 AST_RuntimeError(NULL, "Invalid cast from %i to String", Source->Type);
293 AST_RuntimeError(NULL, "BUG - BUG REPORT: Unimplemented cast target %i", Type);
302 * \brief Condenses a value down to a boolean
304 int SpiderScript_IsValueTrue(tSpiderValue *Value)
306 if( Value == ERRPTR ) return 0;
307 if( Value == NULL ) return 0;
309 switch( (enum eSpiderScript_DataTypes)Value->Type )
311 case SS_DATATYPE_UNDEF:
314 case SS_DATATYPE_INTEGER:
315 return !!Value->Integer;
317 case SS_DATATYPE_REAL:
318 return (-.5f < Value->Real && Value->Real < 0.5f);
320 case SS_DATATYPE_STRING:
321 return Value->String.Length > 0;
323 case SS_DATATYPE_OBJECT:
324 return Value->Object != NULL;
326 case SS_DATATYPE_OPAQUE:
327 return Value->Opaque.Data != NULL;
329 case SS_DATATYPE_ARRAY:
330 return Value->Array.Length > 0;
332 AST_RuntimeError(NULL, "Unknown type %i in SpiderScript_IsValueTrue", Value->Type);
339 * \brief Free a value
340 * \note Just calls Object_Dereference
342 void SpiderScript_FreeValue(tSpiderValue *Value)
344 SpiderScript_DereferenceValue(Value);
348 * \brief Dump a value into a string
349 * \return Heap string
351 char *SpiderScript_DumpValue(tSpiderValue *Value)
354 if( Value == ERRPTR )
355 return strdup("ERRPTR");
357 return strdup("null");
359 switch( (enum eSpiderScript_DataTypes)Value->Type )
361 case SS_DATATYPE_UNDEF: return strdup("undefined");
363 case SS_DATATYPE_INTEGER:
364 ret = malloc( sizeof(Value->Integer)*2 + 3 );
365 sprintf(ret, "0x%lx", Value->Integer);
368 case SS_DATATYPE_REAL:
369 ret = malloc( sprintf(NULL, "%f", Value->Real) + 1 );
370 sprintf(ret, "%f", Value->Real);
373 case SS_DATATYPE_STRING:
374 ret = malloc( Value->String.Length + 3 );
376 strcpy(ret+1, Value->String.Data);
377 ret[Value->String.Length+1] = '"';
378 ret[Value->String.Length+2] = '\0';
381 case SS_DATATYPE_OBJECT:
382 ret = malloc( sprintf(NULL, "{%s *%p}", Value->Object->Type->Name, Value->Object) + 1 );
383 sprintf(ret, "{%s *%p}", Value->Object->Type->Name, Value->Object);
386 case SS_DATATYPE_OPAQUE:
387 ret = malloc( sprintf(NULL, "*%p", Value->Opaque.Data) + 1 );
388 sprintf(ret, "*%p", Value->Opaque.Data);
391 case SS_DATATYPE_ARRAY:
392 return strdup("Array");
395 AST_RuntimeError(NULL, "Unknown type %i in Object_Dump", Value->Type);