X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FLibraries%2Flibspiderscript.so_src%2Fast_to_bytecode.c;h=7c1398e8a4d59a3cc79c2413d4d3d2f6561caf99;hb=2acaad7b0d455a6c7cb177e1a7ecc5f07f40c7bb;hp=7afd0c03240841dc2bff821a552cad782639edba;hpb=2c8989ea0849b0e207e6c357626d41c991dc423f;p=tpg%2Facess2.git diff --git a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c index 7afd0c03..7c1398e8 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c @@ -7,12 +7,14 @@ #include #include #include +#include "common.h" #include "ast.h" #include "bytecode_gen.h" #include "bytecode_ops.h" #define TRACE_VAR_LOOKUPS 0 #define TRACE_NODE_RETURNS 0 +#define MAX_NAMESPACE_DEPTH 10 // === IMPORTS === extern tSpiderFunction *gpExports_First; @@ -26,11 +28,13 @@ typedef struct sAST_BlockInfo int BreakTarget; int ContinueTarget; + + const char *CurNamespaceStack[MAX_NAMESPACE_DEPTH]; } tAST_BlockInfo; // === PROTOTYPES === // Node Traversal - int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node); + int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue); // Variables int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name); int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode); @@ -43,36 +47,40 @@ void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); // int giNextBlockIdent = 1; // === CODE === +int SpiderScript_BytecodeScript(tSpiderScript *Script) +{ + tScript_Function *fcn; + for(fcn = Script->Functions; fcn; fcn = fcn->Next) + { + if( Bytecode_ConvertFunction(fcn) == 0 ) + return -1; + } + return 0; +} + /** * \brief Convert a function into bytecode */ -tBC_Function *Bytecode_ConvertFunction(tAST_Function *ASTFcn) +tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn) { tBC_Function *ret; tAST_BlockInfo bi = {0}; - - { - tAST_Node *arg; - int i; - char *arg_names[ASTFcn->ArgumentCount]; - int arg_types[ASTFcn->ArgumentCount]; - - for(arg = ASTFcn->Arguments, i = 0; arg; arg = arg->NextSibling, i ++) - { - arg_names[i] = arg->DefVar.Name; - arg_types[i] = arg->DefVar.DataType; - } - ret = Bytecode_CreateFunction(ASTFcn->Name, ASTFcn->ArgumentCount, arg_names, arg_types); - if(!ret) return NULL; - } + // TODO: Return BCFcn instead? + if(Fcn->BCFcn) return Fcn->BCFcn; + + ret = Bytecode_CreateFunction(Fcn); + if(!ret) return NULL; bi.Handle = ret; - if( AST_ConvertNode(&bi, ASTFcn->Code) ) + if( AST_ConvertNode(&bi, Fcn->ASTFcn, 0) ) { Bytecode_DeleteFunction(ret); return NULL; } + + Fcn->BCFcn = ret; + return ret; } @@ -81,36 +89,37 @@ tBC_Function *Bytecode_ConvertFunction(tAST_Function *ASTFcn) * \param Block Execution context * \param Node Node to execute */ -int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) +int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) { tAST_Node *node; int ret = 0; int i, op = 0; + int bAddedValue = 1; switch(Node->Type) { // No Operation case NODETYPE_NOP: + bAddedValue = 0; break; // Code block case NODETYPE_BLOCK: Bytecode_AppendEnterContext(Block->Handle); // Create a new block { - tAST_BlockInfo blockInfo; + tAST_BlockInfo blockInfo = {0}; blockInfo.Parent = Block; blockInfo.Handle = Block->Handle; - blockInfo.ContinueTarget = 0; - blockInfo.BreakTarget = 0; // Loop over all nodes, or until the return value is set for(node = Node->Block.FirstChild; node; node = node->NextSibling ) { - AST_ConvertNode(Block, node); + AST_ConvertNode(Block, node, 0); } } Bytecode_AppendLeaveContext(Block->Handle); // Leave this context + bAddedValue = 0; break; // Assignment @@ -120,8 +129,6 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) AST_RuntimeError(Node, "LVALUE of assignment is not a variable"); return -1; } - ret = AST_ConvertNode(Block, Node->Assign.Value); - if(ret) return ret; // Perform assignment operation if( Node->Assign.Operation != NODETYPE_NOP ) @@ -129,11 +136,41 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) ret = BC_Variable_GetValue(Block, Node->Assign.Dest); if(ret) return ret; - Bytecode_AppendBinOp(Block->Handle, Node->Assign.Operation); + ret = AST_ConvertNode(Block, Node->Assign.Value, 1); + if(ret) return ret; + switch(Node->Assign.Operation) + { + // General Binary Operations + case NODETYPE_ADD: op = BC_OP_ADD; break; + case NODETYPE_SUBTRACT: op = BC_OP_SUBTRACT; break; + case NODETYPE_MULTIPLY: op = BC_OP_MULTIPLY; break; + case NODETYPE_DIVIDE: op = BC_OP_DIVIDE; break; + case NODETYPE_MODULO: op = BC_OP_MODULO; break; + case NODETYPE_BWAND: op = BC_OP_BITAND; break; + case NODETYPE_BWOR: op = BC_OP_BITOR; break; + case NODETYPE_BWXOR: op = BC_OP_BITXOR; break; + case NODETYPE_BITSHIFTLEFT: op = BC_OP_BITSHIFTLEFT; break; + case NODETYPE_BITSHIFTRIGHT: op = BC_OP_BITSHIFTRIGHT; break; + case NODETYPE_BITROTATELEFT: op = BC_OP_BITROTATELEFT; break; + + default: + AST_RuntimeError(Node, "Unknown operation in ASSIGN %i", Node->Assign.Operation); + break; + } + 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); // Set the variable value ret = BC_Variable_SetValue( Block, Node->Assign.Dest ); + bAddedValue = 0; break; // Post increment/decrement @@ -151,9 +188,9 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) if(ret) return ret; if( Node->Type == NODETYPE_POSTDEC ) - Bytecode_AppendBinOp(Block->Handle, NODETYPE_SUBTRACT); + Bytecode_AppendBinOp(Block->Handle, BC_OP_SUBTRACT); else - Bytecode_AppendBinOp(Block->Handle, NODETYPE_ADD); + Bytecode_AppendBinOp(Block->Handle, BC_OP_ADD); if(ret) return ret; ret = BC_Variable_SetValue(Block, Node->UniOp.Value); @@ -163,57 +200,85 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) // Function Call case NODETYPE_METHODCALL: case NODETYPE_FUNCTIONCALL: - case NODETYPE_CREATEOBJECT: - i = 0; + case NODETYPE_CREATEOBJECT: { + int nargs = 0; for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) { - ret = AST_ConvertNode(Block, node); + ret = AST_ConvertNode(Block, node, 1); if(ret) return ret; - i ++; + nargs ++; } // Call the function - if( Node->Type == NODETYPE_CREATEOBJECT ) - { - // TODO: Sanity check stack top - Bytecode_AppendCreateObj(Block->Handle, Node->FunctionCall.Name, i); - } - else if( Node->Type == NODETYPE_METHODCALL ) + if( Node->Type == NODETYPE_METHODCALL ) { // TODO: Sanity check stack top - ret = AST_ConvertNode(Block, Node->FunctionCall.Object); + ret = AST_ConvertNode(Block, Node->FunctionCall.Object, 1); if(ret) return ret; - Bytecode_AppendMethodCall(Block->Handle, Node->FunctionCall.Name, i); + Bytecode_AppendMethodCall(Block->Handle, Node->FunctionCall.Name, nargs); } else { - Bytecode_AppendFunctionCall(Block->Handle, Node->FunctionCall.Name, i); + int newnamelen = 0; + char *manglename; + for( i = 0; i < MAX_NAMESPACE_DEPTH && Block->CurNamespaceStack[i]; i ++ ) + newnamelen = strlen(Block->CurNamespaceStack[i]) + 1; + newnamelen += strlen(Node->FunctionCall.Name) + 1; + manglename = alloca(newnamelen); + manglename[0] = 0; + for( i = 0; i < MAX_NAMESPACE_DEPTH && Block->CurNamespaceStack[i]; i ++ ) { + int pos; + strcat(manglename, Block->CurNamespaceStack[i]); + pos = strlen(manglename); + manglename[pos] = BC_NS_SEPARATOR; + manglename[pos+1] = '\0'; + } + strcat(manglename, Node->FunctionCall.Name); + + if( Node->Type == NODETYPE_CREATEOBJECT ) + { + // TODO: Sanity check stack top + Bytecode_AppendCreateObj(Block->Handle, manglename, nargs); + } + else + { + Bytecode_AppendFunctionCall(Block->Handle, manglename, nargs); + } } - break; + } break; // Conditional case NODETYPE_IF: { - int if_true, if_end; - ret = AST_ConvertNode(Block, Node->If.Condition); + int if_end; + ret = AST_ConvertNode(Block, Node->If.Condition, 1); if(ret) return ret; - if_true = Bytecode_AllocateLabel(Block->Handle); if_end = Bytecode_AllocateLabel(Block->Handle); - - Bytecode_AppendCondJump(Block->Handle, if_true); - // False - ret = AST_ConvertNode(Block, Node->If.False); - if(ret) return ret; - Bytecode_AppendJump(Block->Handle, if_end); + if( Node->If.False->Type != NODETYPE_NOP ) + { + int if_true = Bytecode_AllocateLabel(Block->Handle); + + Bytecode_AppendCondJump(Block->Handle, if_true); + + // False + ret = AST_ConvertNode(Block, Node->If.False, 0); + if(ret) return ret; + Bytecode_AppendJump(Block->Handle, if_end); + Bytecode_SetLabel(Block->Handle, if_true); + } + else + { + Bytecode_AppendCondJumpNot(Block->Handle, if_end); + } // True - Bytecode_SetLabel(Block->Handle, if_true); - ret = AST_ConvertNode(Block, Node->If.True); + ret = AST_ConvertNode(Block, Node->If.True, 0); if(ret) return ret; // End Bytecode_SetLabel(Block->Handle, if_end); + bAddedValue = 0; } break; // Loop @@ -223,7 +288,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) const char *saved_tag; // Initialise - ret = AST_ConvertNode(Block, Node->For.Init); + ret = AST_ConvertNode(Block, Node->For.Init, 0); if(ret) return ret; loop_start = Bytecode_AllocateLabel(Block->Handle); @@ -241,40 +306,46 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) // Check initial condition if( !Node->For.bCheckAfter ) { - ret = AST_ConvertNode(Block, Node->For.Condition); + ret = AST_ConvertNode(Block, Node->For.Condition, 1); if(ret) return ret; - Bytecode_AppendUniOp(Block->Handle, NODETYPE_LOGICALNOT); + Bytecode_AppendUniOp(Block->Handle, BC_OP_LOGICNOT); Bytecode_AppendCondJump(Block->Handle, loop_end); } // Code - ret = AST_ConvertNode(Block, Node->For.Code); + ret = AST_ConvertNode(Block, Node->For.Code, 0); if(ret) return ret; // Increment - ret = AST_ConvertNode(Block, Node->For.Increment); + ret = AST_ConvertNode(Block, Node->For.Increment, 0); if(ret) return ret; // Tail check if( Node->For.bCheckAfter ) { - ret = AST_ConvertNode(Block, Node->For.Condition); + ret = AST_ConvertNode(Block, Node->For.Condition, 1); if(ret) return ret; Bytecode_AppendCondJump(Block->Handle, loop_start); } + else + { + Bytecode_AppendJump(Block->Handle, loop_start); + } Bytecode_SetLabel(Block->Handle, loop_end); Block->BreakTarget = saved_break; Block->ContinueTarget = saved_continue; Block->Tag = saved_tag; + bAddedValue = 0; } break; // Return case NODETYPE_RETURN: - ret = AST_ConvertNode(Block, Node->UniOp.Value); + ret = AST_ConvertNode(Block, Node->UniOp.Value, 1); if(ret) return ret; Bytecode_AppendReturn(Block->Handle); + bAddedValue = 0; break; case NODETYPE_BREAK: @@ -289,6 +360,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) Bytecode_AppendJump(Block->Handle, bi->BreakTarget); else Bytecode_AppendJump(Block->Handle, bi->ContinueTarget); + bAddedValue = 0; } break; // Define a variable @@ -298,16 +370,23 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) if( Node->DefVar.InitialValue ) { - ret = AST_ConvertNode(Block, Node->DefVar.InitialValue); + ret = AST_ConvertNode(Block, Node->DefVar.InitialValue, 1); if(ret) return ret; Bytecode_AppendSaveVar(Block->Handle, Node->DefVar.Name); } + bAddedValue = 0; break; // Scope case NODETYPE_SCOPE: - Bytecode_AppendSubNamespace(Block->Handle, Node->Scope.Name); - ret = AST_ConvertNode(Block, Node->Scope.Element); + for( i = 0; i < MAX_NAMESPACE_DEPTH && Block->CurNamespaceStack[i]; i ++ ); + if( i == MAX_NAMESPACE_DEPTH ) { + AST_RuntimeError(Node, "Exceeded max explicit namespace depth (%i)", i); + return 2; + } + Block->CurNamespaceStack[i] = Node->Scope.Name; + ret = AST_ConvertNode(Block, Node->Scope.Element, 2); + Block->CurNamespaceStack[i] = NULL; break; // Variable @@ -317,7 +396,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) // Element of an Object case NODETYPE_ELEMENT: - ret = AST_ConvertNode( Block, Node->Scope.Element ); + ret = AST_ConvertNode( Block, Node->Scope.Element, 1 ); if(ret) return ret; Bytecode_AppendElement(Block->Handle, Node->Scope.Name); @@ -325,16 +404,16 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) // Cast a value to another case NODETYPE_CAST: - ret = AST_ConvertNode(Block, Node->Cast.Value); + ret = AST_ConvertNode(Block, Node->Cast.Value, 1); if(ret) return ret; Bytecode_AppendCast(Block->Handle, Node->Cast.DataType); break; // Index into an array case NODETYPE_INDEX: - ret = AST_ConvertNode(Block, Node->BinOp.Left); // Array + ret = AST_ConvertNode(Block, Node->BinOp.Left, 1); // Array if(ret) return ret; - ret = AST_ConvertNode(Block, Node->BinOp.Right); // Offset + ret = AST_ConvertNode(Block, Node->BinOp.Right, 1); // Offset if(ret) return ret; Bytecode_AppendIndex(Block->Handle); @@ -355,7 +434,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) Bytecode_AppendConstInt(Block->Handle, Node->Constant.Integer); break; case NODETYPE_REAL: - Bytecode_AppendConstInt(Block->Handle, Node->Constant.Real); + Bytecode_AppendConstReal(Block->Handle, Node->Constant.Real); break; // --- Operations --- @@ -366,17 +445,15 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) if(!op) op = BC_OP_BITNOT; case NODETYPE_NEGATE: // Negation (-) if(!op) op = BC_OP_NEG; - ret = AST_ConvertNode(Block, Node->UniOp.Value); + ret = AST_ConvertNode(Block, Node->UniOp.Value, 1); if(ret) return ret; Bytecode_AppendUniOp(Block->Handle, op); break; - case NODETYPE_LOGICALAND: // Logical AND (&&) - if(!op) op = BC_OP_LOGICAND; - case NODETYPE_LOGICALOR: // Logical OR (||) - if(!op) op = BC_OP_LOGICOR; - case NODETYPE_LOGICALXOR: // Logical XOR (^^) - if(!op) op = BC_OP_LOGICXOR; + // Logic + case NODETYPE_LOGICALAND: if(!op) op = BC_OP_LOGICAND; + case NODETYPE_LOGICALOR: if(!op) op = BC_OP_LOGICOR; + case NODETYPE_LOGICALXOR: if(!op) op = BC_OP_LOGICXOR; // Comparisons case NODETYPE_EQUALS: if(!op) op = BC_OP_EQUALS; case NODETYPE_LESSTHAN: if(!op) op = BC_OP_LESSTHAN; @@ -395,18 +472,18 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) case NODETYPE_BITSHIFTLEFT: if(!op) op = BC_OP_BITSHIFTLEFT; case NODETYPE_BITSHIFTRIGHT: if(!op) op = BC_OP_BITSHIFTRIGHT; case NODETYPE_BITROTATELEFT: if(!op) op = BC_OP_BITROTATELEFT; - ret = AST_ConvertNode(Block, Node->BinOp.Left); + ret = AST_ConvertNode(Block, Node->BinOp.Left, 1); if(ret) return ret; - ret = AST_ConvertNode(Block, Node->BinOp.Right); + ret = AST_ConvertNode(Block, Node->BinOp.Right, 1); if(ret) return ret; - + Bytecode_AppendBinOp(Block->Handle, op); 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 @@ -418,6 +495,9 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node) } #endif + if( !bKeepValue && bAddedValue ) + Bytecode_AppendDelete(Block->Handle); + return ret; }