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->ReferenceCount == 0 )
37 switch( (enum eSpiderScript_DataTypes) Object->Type )
39 case SS_DATATYPE_OBJECT:
40 Object->Object->Type->Destructor( Object->Object );
42 case SS_DATATYPE_OPAQUE:
43 Object->Opaque.Destroy( Object->Opaque.Data );
53 * \brief Reference a value
55 void SpiderScript_ReferenceValue(tSpiderValue *Object)
57 if(!Object || Object == ERRPTR) return ;
58 Object->ReferenceCount ++;
62 * \brief Allocate and initialise a SpiderScript object
64 tSpiderObject *SpiderScript_AllocateObject(tSpiderObjectDef *Class, int ExtraBytes)
66 int size = sizeof(tSpiderObject) + Class->NAttributes * sizeof(tSpiderValue*) + ExtraBytes;
67 tSpiderObject *ret = malloc(size);
70 ret->ReferenceCount = 1;
71 ret->OpaqueData = &ret->Attributes[ Class->NAttributes ];
72 memset( ret->Attributes, 0, Class->NAttributes * sizeof(tSpiderValue*) );
78 * \brief Create an integer object
80 tSpiderValue *SpiderScript_CreateInteger(uint64_t Value)
82 tSpiderValue *ret = malloc( sizeof(tSpiderValue) );
83 ret->Type = SS_DATATYPE_INTEGER;
84 ret->ReferenceCount = 1;
90 * \brief Create an real number object
92 tSpiderValue *SpiderScript_CreateReal(double Value)
94 tSpiderValue *ret = malloc( sizeof(tSpiderValue) );
95 ret->Type = SS_DATATYPE_REAL;
96 ret->ReferenceCount = 1;
102 * \brief Create an string object
104 tSpiderValue *SpiderScript_CreateString(int Length, const char *Data)
106 tSpiderValue *ret = malloc( sizeof(tSpiderValue) + Length + 1 );
107 ret->Type = SS_DATATYPE_STRING;
108 ret->ReferenceCount = 1;
109 ret->String.Length = Length;
111 memcpy(ret->String.Data, Data, Length);
113 memset(ret->String.Data, 0, Length);
114 ret->String.Data[Length] = '\0';
119 * \brief Concatenate two strings
121 tSpiderValue *SpiderScript_StringConcat(const tSpiderValue *Str1, const tSpiderValue *Str2)
126 if( Str1 && Str1->Type != SS_DATATYPE_STRING)
128 if( Str2 && Str2->Type != SS_DATATYPE_STRING)
131 if(Str1) newLen += Str1->String.Length;
132 if(Str2) newLen += Str2->String.Length;
133 ret = malloc( sizeof(tSpiderValue) + newLen + 1 );
134 ret->Type = SS_DATATYPE_STRING;
135 ret->ReferenceCount = 1;
136 ret->String.Length = newLen;
138 memcpy(ret->String.Data, Str1->String.Data, Str1->String.Length);
141 memcpy(ret->String.Data+Str1->String.Length, Str2->String.Data, Str2->String.Length);
143 memcpy(ret->String.Data, Str2->String.Data, Str2->String.Length);
145 ret->String.Data[ newLen ] = '\0';
150 * \brief Cast one object to another
151 * \brief Type Destination type
152 * \brief Source Input data
154 tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source)
156 tSpiderValue *ret = ERRPTR;
163 case SS_DATATYPE_INTEGER: return SpiderScript_CreateInteger(0);
164 case SS_DATATYPE_REAL: return SpiderScript_CreateReal(0);
165 case SS_DATATYPE_STRING: return SpiderScript_CreateString(4, "null");
170 // Check if anything needs to be done
171 if( Source->Type == Type ) {
172 SpiderScript_DereferenceValue(Source);
179 printf("Casting %i ", Source->Type);
182 case SS_DATATYPE_INTEGER: printf("0x%lx", Source->Integer); break;
183 case SS_DATATYPE_STRING: printf("\"%s\"", Source->String.Data); break;
184 case SS_DATATYPE_REAL: printf("%f", Source->Real); break;
187 printf(" to %i\n", Type);
193 if( Source->Type == SS_DATATYPE_OBJECT )
195 const char *name = NULL;
198 case SS_DATATYPE_INTEGER: name = "cast Integer"; break;
199 case SS_DATATYPE_REAL: name = "cast Real"; break;
200 case SS_DATATYPE_STRING: name = "cast String"; break;
201 case SS_DATATYPE_ARRAY: name = "cast Array"; break;
203 AST_RuntimeError(NULL, "Invalid cast to %i from Object", Type);
208 ret = Object_ExecuteMethod(Left->Object, fcnname, Right);
211 // Fall through and try casting (which will usually fail)
216 switch( (enum eSpiderScript_DataTypes)Type )
218 case SS_DATATYPE_UNDEF:
219 case SS_DATATYPE_ARRAY:
220 case SS_DATATYPE_OPAQUE:
221 AST_RuntimeError(NULL, "Invalid cast to %i", Type);
223 case SS_DATATYPE_OBJECT:
225 AST_RuntimeError(NULL, "Invalid cast to %i", Type);
228 case SS_DATATYPE_INTEGER:
229 ret = malloc(sizeof(tSpiderValue));
230 ret->Type = SS_DATATYPE_INTEGER;
231 ret->ReferenceCount = 1;
234 case SS_DATATYPE_INTEGER: break; // Handled above
235 case SS_DATATYPE_STRING: ret->Integer = atoi(Source->String.Data); break;
236 case SS_DATATYPE_REAL: ret->Integer = Source->Real; break;
238 AST_RuntimeError(NULL, "Invalid cast from %i to Integer", Source->Type);
245 case SS_DATATYPE_REAL:
246 ret = malloc(sizeof(tSpiderValue));
247 ret->Type = SS_DATATYPE_REAL;
248 ret->ReferenceCount = 1;
251 case SS_DATATYPE_STRING: ret->Real = atof(Source->String.Data); break;
252 case SS_DATATYPE_INTEGER: ret->Real = Source->Integer; break;
254 AST_RuntimeError(NULL, "Invalid cast from %i to Real", Source->Type);
261 case SS_DATATYPE_STRING:
264 case SS_DATATYPE_INTEGER: len = snprintf(NULL, 0, "%li", Source->Integer); break;
265 case SS_DATATYPE_REAL: len = snprintf(NULL, 0, "%g", Source->Real); break;
268 ret = malloc(sizeof(tSpiderValue) + len + 1);
269 ret->Type = SS_DATATYPE_STRING;
270 ret->ReferenceCount = 1;
271 ret->String.Length = len;
274 case SS_DATATYPE_INTEGER: sprintf(ret->String.Data, "%li", Source->Integer); break;
275 case SS_DATATYPE_REAL:
276 sprintf(ret->String.Data, "%g", Source->Real); break;
278 AST_RuntimeError(NULL, "Invalid cast from %i to String", Source->Type);
286 AST_RuntimeError(NULL, "BUG - BUG REPORT: Unimplemented cast target %i", Type);
295 * \brief Condenses a value down to a boolean
297 int SpiderScript_IsValueTrue(tSpiderValue *Value)
299 if( Value == ERRPTR ) return 0;
300 if( Value == NULL ) return 0;
302 switch( (enum eSpiderScript_DataTypes)Value->Type )
304 case SS_DATATYPE_UNDEF:
307 case SS_DATATYPE_INTEGER:
308 return !!Value->Integer;
310 case SS_DATATYPE_REAL:
311 return (-.5f < Value->Real && Value->Real < 0.5f);
313 case SS_DATATYPE_STRING:
314 return Value->String.Length > 0;
316 case SS_DATATYPE_OBJECT:
317 return Value->Object != NULL;
319 case SS_DATATYPE_OPAQUE:
320 return Value->Opaque.Data != NULL;
322 case SS_DATATYPE_ARRAY:
323 return Value->Array.Length > 0;
325 AST_RuntimeError(NULL, "Unknown type %i in SpiderScript_IsValueTrue", Value->Type);
332 * \brief Free a value
333 * \note Just calls Object_Dereference
335 void SpiderScript_FreeValue(tSpiderValue *Value)
337 SpiderScript_DereferenceValue(Value);
341 * \brief Dump a value into a string
342 * \return Heap string
344 char *SpiderScript_DumpValue(tSpiderValue *Value)
347 if( Value == ERRPTR )
348 return strdup("ERRPTR");
350 return strdup("null");
352 switch( (enum eSpiderScript_DataTypes)Value->Type )
354 case SS_DATATYPE_UNDEF: return strdup("undefined");
356 case SS_DATATYPE_INTEGER:
357 ret = malloc( sizeof(Value->Integer)*2 + 3 );
358 sprintf(ret, "0x%lx", Value->Integer);
361 case SS_DATATYPE_REAL:
362 ret = malloc( sprintf(NULL, "%f", Value->Real) + 1 );
363 sprintf(ret, "%f", Value->Real);
366 case SS_DATATYPE_STRING:
367 ret = malloc( Value->String.Length + 3 );
369 strcpy(ret+1, Value->String.Data);
370 ret[Value->String.Length+1] = '"';
371 ret[Value->String.Length+2] = '\0';
374 case SS_DATATYPE_OBJECT:
375 ret = malloc( sprintf(NULL, "{%s *%p}", Value->Object->Type->Name, Value->Object) + 1 );
376 sprintf(ret, "{%s *%p}", Value->Object->Type->Name, Value->Object);
379 case SS_DATATYPE_OPAQUE:
380 ret = malloc( sprintf(NULL, "*%p", Value->Opaque.Data) + 1 );
381 sprintf(ret, "*%p", Value->Opaque.Data);
384 case SS_DATATYPE_ARRAY:
385 return strdup("Array");
388 AST_RuntimeError(NULL, "Unknown type %i in Object_Dump", Value->Type);