int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name);
int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode);
int BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode);
+void BC_Variable_Clear(tAST_BlockInfo *Block);
// - Errors
void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...);
void AST_RuntimeError(tAST_Node *Node, const char *Format, ...);
{
tBC_Function *ret;
tAST_BlockInfo bi = {0};
+ int i;
// TODO: Return BCFcn instead?
if(Fcn->BCFcn) return Fcn->BCFcn;
if(!ret) return NULL;
bi.Handle = ret;
+
+ // Parse arguments
+ for( i = 0; i < Fcn->ArgumentCount; i ++ )
+ {
+ BC_Variable_Define(&bi, Fcn->Arguments[i].Type, Fcn->Arguments[i].Name);
+ }
+
if( AST_ConvertNode(&bi, Fcn->ASTFcn, 0) )
{
AST_RuntimeError(Fcn->ASTFcn, "Error in converting function");
Bytecode_DeleteFunction(ret);
+ BC_Variable_Clear(&bi);
return NULL;
}
+ BC_Variable_Clear(&bi);
+
Bytecode_AppendConstInt(ret, 0); // TODO: NULL
Bytecode_AppendReturn(ret);
node;
node = node->NextSibling )
{
- ret = AST_ConvertNode(Block, node, 0);
+ ret = AST_ConvertNode(&blockInfo, node, 0);
if(ret) return ret;
if( blockInfo.StackDepth != 0 ) {
AST_RuntimeError(node, "Stack not reset at end of node");
+ blockInfo.StackDepth = 0;
}
}
+
+ BC_Variable_Clear(&blockInfo);
}
Bytecode_AppendLeaveContext(Block->Handle); // Leave this context
break;
for( i = 0; i < Block->NamespaceDepth; i ++ )
newnamelen += strlen(Block->CurNamespaceStack[i]) + 1;
newnamelen += strlen(Node->FunctionCall.Name) + 1;
+// newnamelen += 1;
+
manglename = alloca(newnamelen);
- manglename[0] = 0;
+ newnamelen = 0;
for( i = 0; i < Block->NamespaceDepth; i ++ ) {
- int pos;
- strcat(manglename, Block->CurNamespaceStack[i]);
- pos = strlen(manglename);
- manglename[pos] = BC_NS_SEPARATOR;
- manglename[pos+1] = '\0';
+ strcpy(manglename+newnamelen, Block->CurNamespaceStack[i]);
+ newnamelen += strlen(Block->CurNamespaceStack[i]) + 1;
+ manglename[ newnamelen - 1 ] = BC_NS_SEPARATOR;
}
- strcat(manglename, Node->FunctionCall.Name);
+ strcpy(manglename + newnamelen, Node->FunctionCall.Name);
+ newnamelen += strlen(Node->FunctionCall.Name) + 1;
+// manglename[ newnamelen ] = '\0'; // Zero length terminator
Block->NamespaceDepth = 0;
// Push arguments to the stack
// Loop
case NODETYPE_LOOP: {
- int loop_start, loop_end;
+ int loop_start, loop_end, code_end;
int saved_break, saved_continue;
const char *saved_tag;
if(ret) return ret;
loop_start = Bytecode_AllocateLabel(Block->Handle);
+ code_end = Bytecode_AllocateLabel(Block->Handle);
loop_end = Bytecode_AllocateLabel(Block->Handle);
saved_break = Block->BreakTarget;
saved_continue = Block->ContinueTarget;
saved_tag = Block->Tag;
Block->BreakTarget = loop_end;
- Block->ContinueTarget = loop_end;
+ Block->ContinueTarget = code_end;
Block->Tag = Node->For.Tag;
Bytecode_SetLabel(Block->Handle, loop_start);
// Code
ret = AST_ConvertNode(Block, Node->For.Code, 0);
if(ret) return ret;
-
+
+ Bytecode_SetLabel(Block->Handle, code_end);
+
// Increment
ret = AST_ConvertNode(Block, Node->For.Increment, 0);
if(ret) return ret;
case NODETYPE_CONTINUE: {
tAST_BlockInfo *bi = Block;
if( Node->Variable.Name[0] ) {
- while(bi && strcmp(bi->Tag, Node->Variable.Name) == 0) bi = bi->Parent;
+ while(bi && (!bi->Tag || strcmp(bi->Tag, Node->Variable.Name) != 0))
+ bi = bi->Parent;
+ }
+ else {
+ while(bi && !bi->Tag)
+ bi = bi->Parent;
}
if( !bi ) return 1;
// TODO: Check if BreakTarget/ContinueTarget are valid
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);
// > Type check
ret = _StackPop(Block, Node, SS_DATATYPE_UNDEF);
if(ret < 0) return -1;
- if(ret != SS_DATATYPE_ARRAY && (ret >> 16) == 0) {
+ if(ret != SS_DATATYPE_ARRAY && SS_GETARRAYDEPTH(ret) == 0) {
AST_RuntimeError(Node, "Type mismatch, Expected an array, got %i",
ret);
return -2;
// Update the array depth
if( i != SS_DATATYPE_ARRAY ) {
- i -= 0x10000; // Decrease the array level
+ i = SS_DOWNARRAY(i); // Decrease the array level
}
ret = _StackPush(Block, Node, i);
if(ret < 0) return -1;
// TODO: Scan namespace for constant name
AST_RuntimeError(Node, "TODO - Runtime Constants");
Block->NamespaceDepth = 0;
- ret = -1;
- break;
+ return -1;
// Constant Values
case NODETYPE_STRING:
if(ret < 0) return -1;
CHECK_IF_NEEDED(1);
break;
-
+ case NODETYPE_NULL:
+ Bytecode_AppendConstNull(Block->Handle);
+ ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF);
+ if(ret < 0) return -1;
+ CHECK_IF_NEEDED(1);
+ break;
+
// --- Operations ---
// Boolean Operations
case NODETYPE_LOGICALNOT: // Logical NOT (!)
int BC_SaveValue(tAST_BlockInfo *Block, tAST_Node *DestNode)
{
- int ret;
+ int ret, type;
switch(DestNode->Type)
{
// Variable, simple
case NODETYPE_VARIABLE:
ret = BC_Variable_SetValue( Block, DestNode );
+ if(ret) return ret;
break;
// Array index
case NODETYPE_INDEX:
if(ret) return ret;
ret = _StackPop(Block, DestNode->BinOp.Left, SS_DATATYPE_UNDEF);
if(ret < 0) return -1;
- if(ret != SS_DATATYPE_ARRAY && (ret >> 16) == 0) {
+ if(ret != SS_DATATYPE_ARRAY && SS_GETARRAYDEPTH(ret) == 0) {
AST_RuntimeError(DestNode, "Type mismatch, Expected an array, got %i",
ret);
return -2;
}
+ type = SS_DOWNARRAY(ret);
ret = AST_ConvertNode(Block, DestNode->BinOp.Right, 1); // Offset
if(ret) return ret;
if(ret < 0) return -1;
Bytecode_AppendSetIndex( Block->Handle );
+ _StackPop(Block, DestNode, type);
break;
// Object element
case NODETYPE_ELEMENT:
}
if(var) break;
}
-
+
if( !var )
{
// if( Block->Script->Variant->bDyamicTyped && CreateType != SS_DATATYPE_UNDEF ) {
return 0;
}
+void BC_Variable_Clear(tAST_BlockInfo *Block)
+{
+ tAST_Variable *var;
+ for( var = Block->FirstVar; var; )
+ {
+ tAST_Variable *tv = var->Next;
+ free( var );
+ var = tv;
+ }
+ Block->FirstVar = NULL;
+}
+
#if 0
void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...)
{