extern tSpiderValue *AST_ExecuteNode_BinOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Left, tSpiderValue *Right);
extern tSpiderValue *AST_ExecuteNode_UniOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Value);
extern tSpiderValue *AST_ExecuteNode_Index(tSpiderScript *Script, tAST_Node *Node, tSpiderValue *Array, int Index, tSpiderValue *SaveValue);
+extern tSpiderValue *AST_ExecuteNode_Element(tSpiderScript *Script, tAST_Node *Node, tSpiderValue *Object, const char *Element, tSpiderValue *SaveValue);
#endif
ret = AST_ConvertNode( Block, Node->Scope.Element, 1 );
if(ret) return ret;
+ // TODO: Support elements for non-objects
ret = _StackPop(Block, Node, SS_DATATYPE_OBJECT);
if(ret < 0) return -1;
Bytecode_AppendElement(Block->Handle, Node->Scope.Name);
+
+ // TODO: Somehow know this at compile time?
ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF);
if(ret < 0) return -1;
CHECK_IF_NEEDED(1);
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;
- }
+
+ ret = AST_ExecuteNode_Element(Block->Script, Node, tmpobj, Node->Scope.Name, ERRPTR);
break;
// Cast a value to another
break;
}
- ret = AST_ExecuteNode_Index(Block->Script, Node, op1, op2->Integer, NULL);
+ ret = AST_ExecuteNode_Index(Block->Script, Node, op1, op2->Integer, ERRPTR);
SpiderScript_DereferenceValue(op1);
SpiderScript_DereferenceValue(op2);
return ERRPTR;
}
- if( SaveValue )
+ if( SaveValue != ERRPTR )
{
- if( SaveValue->Type != SS_DOWNARRAY(Array->Type) ) {
+ if( SaveValue && SaveValue->Type != SS_DOWNARRAY(Array->Type) ) {
// TODO: Implicit casting
AST_RuntimeError(Node, "Type mismatch assiging to array element");
return ERRPTR;
}
}
+/**
+ * \brief Get/Set the value of an element/attribute of a class
+ * \param Script Executing script
+ * \param Node Current execution node (only used for AST_RuntimeError)
+ * \param Object Object value
+ * \param ElementName Name of the attribute to be accessed
+ * \param SaveValue Value to set the element to (if ERRPTR, element value is returned)
+ */
+tSpiderValue *AST_ExecuteNode_Element(tSpiderScript *Script, tAST_Node *Node,
+ tSpiderValue *Object, const char *ElementName, tSpiderValue *SaveValue)
+{
+ int i;
+ tSpiderValue *ret;
+
+ if( !Object ) {
+ AST_RuntimeError(Node, "Tried to access an element of NULL");
+ return ERRPTR;
+ }
+
+ switch( Object->Type )
+ {
+ case SS_DATATYPE_OBJECT: {
+ tSpiderObjectDef *class = Object->Object->Type;
+ for( i = 0; i < class->NAttributes; i ++ )
+ {
+ if( strcmp(ElementName, class->AttributeDefs[i].Name) == 0 )
+ {
+ if( SaveValue != ERRPTR ) {
+ Object->Object->Attributes[i] = SaveValue;
+ SpiderScript_ReferenceValue(SaveValue);
+ return NULL;
+ }
+ else {
+ ret = Object->Object->Attributes[i];
+ SpiderScript_ReferenceValue(ret);
+ return ret;
+ }
+ }
+ }
+ AST_RuntimeError(Node, "Unknown attribute '%s' of class '%s'",
+ ElementName, class->Name);
+ return ERRPTR; }
+ default:
+ AST_RuntimeError(Node, "Unable to get element of type %i", Object->Type);
+ return ERRPTR;
+ }
+}
+
#if USE_AST_EXEC
/**
* \brief Define a variable
DEBUG_F("\n");
} break;
+ // Array index (get or set)
case BC_OP_INDEX:
case BC_OP_SETINDEX:
STATE_HDR();
pval2 = Bytecode_int_GetSpiderValue(&val2, NULL);
Bytecode_int_DerefStackValue(&val2);
+ DEBUG_F("SETINDEX %i ", val1.Integer); PRINT_STACKVAL(val2); DEBUG_F("\n");
+
ret_val = AST_ExecuteNode_Index(Script, NULL, pval1, val1.Integer, pval2);
if(ret_val == ERRPTR) { nextop = NULL; break; }
SpiderScript_DereferenceValue(pval2);
}
else {
- ret_val = AST_ExecuteNode_Index(Script, NULL, pval1, val1.Integer, NULL);
+ DEBUG_F("INDEX %i ", val1.Integer);
+ ret_val = AST_ExecuteNode_Index(Script, NULL, pval1, val1.Integer, ERRPTR);
if(ret_val == ERRPTR) { nextop = NULL; break; }
Bytecode_int_SetSpiderValue(&val1, ret_val);
SpiderScript_DereferenceValue(ret_val);
PUT_STACKVAL(val1);
+
+ DEBUG_F("[Got "); PRINT_STACKVAL(val1); DEBUG_F("]\n");
+
}
- // Dereference the stack
+ // Dereference the array (or object, ...)
if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1);
break;
+
+ // Object element (get or set)
case BC_OP_ELEMENT:
case BC_OP_SETELEMENT:
STATE_HDR();
- AST_RuntimeError(NULL, "TODO: Impliment ELEMENT/SETELEMENT");
- nextop = NULL;
+
+ GET_STACKVAL(val1);
+ // - Integers/Reals can't have elements :)
+ if( val1.Type != ET_REFERENCE ) {
+ nextop = NULL;
+ break;
+ }
+
+ pval1 = Bytecode_int_GetSpiderValue(&val1, NULL);
+ Bytecode_int_DerefStackValue(&val1);
+
+ if( op->Operation == BC_OP_SETELEMENT ) {
+ GET_STACKVAL(val2);
+ pval2 = Bytecode_int_GetSpiderValue(&val2, &tmpVal2);
+ Bytecode_int_DerefStackValue(&val2);
+
+ DEBUG_F("SETELEMENT %s ", OP_STRING(op)); PRINT_STACKVAL(val2); DEBUG_F("\n");
+
+ ret_val = AST_ExecuteNode_Element(Script, NULL, pval1, OP_STRING(op), pval2);
+ if(ret_val == ERRPTR) { nextop = NULL; break; }
+
+ if(pval2 != &tmpVal2) SpiderScript_DereferenceValue(pval2);
+ }
+ else {
+ DEBUG_F("ELEMENT %s ", OP_STRING(op));
+
+ ret_val = AST_ExecuteNode_Element(Script, NULL, pval1, OP_STRING(op), ERRPTR);
+ if(ret_val == ERRPTR) { nextop = NULL; break; }
+
+ Bytecode_int_SetSpiderValue(&val2, ret_val);
+ SpiderScript_DereferenceValue(ret_val);
+ PUT_STACKVAL(val2);
+
+ DEBUG_F("[Got "); PRINT_STACKVAL(val2); DEBUG_F("]\n");
+ }
+
+ SpiderScript_DereferenceValue(pval1);
break;
// Constants:
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;
* by this function.
*/
void (*Destructor)(tSpiderObject *This);
+
+
+ /**
+ * \brief Get/Set an attribute's value
+ */
+ tSpiderValue *(*GetSetAttribute)(tSpiderObject *This, int AttibuteID, tSpiderValue *NewValue);
- tSpiderFunction *Methods; //!< Method Definitions (linked list)
+ /**
+ * \brief Method Definitions (linked list)
+ */
+ tSpiderFunction *Methods;
- int NAttributes; //!< Number of attributes
+ /**
+ * \brief Number of attributes
+ */
+ int NAttributes;
//! Attribute definitions
struct {
const char *Name; //!< Attribute Name
- int bReadOnly; //!< Allow writes to the attribute?
+ int Type; //!< Datatype
+ char bReadOnly; //!< Allow writes to the attribute?
+ char bMethod; //!< IO Goes via GetSetAttribute function
} AttributeDefs[];
};