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
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
AST_RuntimeError(Node, "LVALUE of assignment is not a variable");
return -1;
}
- ret = AST_ConvertNode(Block, Node->Assign.Value, 1);
- if(ret) return ret;
// 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
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);
// Post increment/decrement
case NODETYPE_POSTINC:
case NODETYPE_POSTDEC:
- Bytecode_AppendConstInt(Block->Handle, 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 -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;
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_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( Node->Type == NODETYPE_METHODCALL )
{
// TODO: Sanity check stack top
- ret = AST_ConvertNode(Block, Node->FunctionCall.Object, 1);
- if(ret) return ret;
Bytecode_AppendMethodCall(Block->Handle, Node->FunctionCall.Name, nargs);
}
else
Bytecode_AppendFunctionCall(Block->Handle, manglename, nargs);
}
}
+ CHECK_IF_NEEDED(0); // Don't warn
+ // TODO: Implement warn_unused_ret
} break;
// Conditional
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
if(ret) return ret;
Bytecode_AppendElement(Block->Handle, Node->Scope.Name);
+ CHECK_IF_NEEDED(1);
break;
// Cast a value to another
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
if(ret) return ret;
Bytecode_AppendIndex(Block->Handle);
+ CHECK_IF_NEEDED(1);
break;
// TODO: Implement runtime constants
// 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 ---
ret = AST_ConvertNode(Block, Node->UniOp.Value, 1);
if(ret) return ret;
Bytecode_AppendUniOp(Block->Handle, op);
+ CHECK_IF_NEEDED(1);
break;
// Logic
if(ret) return ret;
Bytecode_AppendBinOp(Block->Handle, op);
+ CHECK_IF_NEEDED(1);
break;
- //default:
- // ret = NULL;
- // AST_RuntimeError(Node, "BUG - SpiderScript AST_ConvertNode Unimplemented %i", Node->Type);
- // break;
+ default:
+ ret = -1;
+ AST_RuntimeError(Node, "BUG - SpiderScript AST_ConvertNode Unimplemented %i", Node->Type);
+ break;
}
#if TRACE_NODE_RETURNS