diff --git a/assets/scripts/scene.toy b/assets/scripts/scene.toy index 9974a3b..df334e7 100644 --- a/assets/scripts/scene.toy +++ b/assets/scripts/scene.toy @@ -1,4 +1,5 @@ //the overarching scene +import engine; import node; //debugging tools @@ -42,6 +43,13 @@ fn onDraw(node: opaque) { stepCounter = 0; } +fn onMouseButtonDown(node: opaque, x: int, y: int, button: string) { + //reload the scene on click + if (button == "left") { + loadRootNode("scripts:/scene.toy"); + } +} + //global accessors fn getTileWidth(node: opaque): int { return 64; } fn getTileHeight(node: opaque): int { return 64; } diff --git a/box/box_engine.c b/box/box_engine.c index 6e833ea..9573626 100644 --- a/box/box_engine.c +++ b/box/box_engine.c @@ -35,6 +35,7 @@ static void fatalError(char* message) { void Box_initEngine() { //clear engine.rootNode = NULL; + engine.nextRootNodeFilename = TOY_TO_NULL_LITERAL; engine.running = false; engine.window = NULL; engine.renderer = NULL; @@ -69,23 +70,22 @@ void Box_initEngine() { const unsigned char* tb = Toy_compileString((const char*)source, &size); free((void*)source); + //TODO: inner-interpreter Toy_runInterpreter(&engine.interpreter, tb, size); - - //init the node-tree - Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onInit", NULL); - } void Box_freeEngine() { //clear existing root node if (engine.rootNode != NULL) { Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onFree", NULL); - Box_freeEngineNode(engine.rootNode); - engine.rootNode = NULL; } + if (!TOY_IS_NULL(engine.nextRootNodeFilename)) { + Toy_freeLiteral(engine.nextRootNodeFilename); + } + Toy_freeInterpreter(&engine.interpreter); //free events @@ -101,6 +101,64 @@ void Box_freeEngine() { engine.window = NULL; } +static void execLoadRootNode() { + //if a new root node is NOT needed, skip out + if (TOY_IS_NULL(engine.nextRootNodeFilename)) { + return; + } + + //free the existing root node + if (engine.rootNode != NULL) { + Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onFree", NULL); + Box_freeEngineNode(engine.rootNode); + engine.rootNode = NULL; + } + + //compile the new root node + size_t size = 0; + const unsigned char* source = Toy_readFile(Toy_toCString(TOY_AS_STRING(engine.nextRootNodeFilename)), &size); + const unsigned char* tb = Toy_compileString((const char*)source, &size); + free((void*)source); + + //allocate the new root node + engine.rootNode = TOY_ALLOCATE(Box_EngineNode, 1); + + //BUGFIX: make an inner-interpreter + Toy_Interpreter inner; + + //init the inner interpreter manually + Toy_initLiteralArray(&inner.literalCache); + inner.scope = Toy_pushScope(engine.interpreter.scope); + inner.bytecode = tb; + inner.length = size; + inner.count = 0; + inner.codeStart = -1; + inner.depth = engine.interpreter.depth + 1; + inner.panic = false; + Toy_initLiteralArray(&inner.stack); + inner.hooks = engine.interpreter.hooks; + Toy_setInterpreterPrint(&inner, engine.interpreter.printOutput); + Toy_setInterpreterAssert(&inner, engine.interpreter.assertOutput); + Toy_setInterpreterError(&inner, engine.interpreter.errorOutput); + + Box_initEngineNode(engine.rootNode, &inner, tb, size); + + //immediately call onLoad() after running the script - for loading other nodes + Box_callEngineNode(engine.rootNode, &inner, "onLoad", NULL); + + //manual cleanup + inner.scope = Toy_popScope(inner.scope); + Toy_freeLiteralArray(&inner.stack); + Toy_freeLiteralArray(&inner.literalCache); + + //cleanup + Toy_freeLiteral(engine.nextRootNodeFilename); + engine.nextRootNodeFilename = TOY_TO_NULL_LITERAL; + + //init the new node-tree + Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onInit", NULL); +} + static void execEvents() { Toy_LiteralArray args; //save some allocation by reusing this Toy_initLiteralArray(&args); @@ -336,7 +394,7 @@ static void execEvents() { Toy_freeLiteralArray(&args); } -void execStep() { +static void execStep() { if (engine.rootNode != NULL) { //steps Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onStep", NULL); @@ -355,6 +413,8 @@ void Box_execEngine() { clock_t delta = (double) CLOCKS_PER_SEC / 60.0; while (engine.running) { + execLoadRootNode(); + execEvents(); //calc the time passed diff --git a/box/box_engine.h b/box/box_engine.h index 06cec62..055a876 100644 --- a/box/box_engine.h +++ b/box/box_engine.h @@ -13,6 +13,7 @@ typedef struct Box_private_engine { //engine stuff Box_EngineNode* rootNode; + Toy_Literal nextRootNodeFilename; clock_t simTime; clock_t realTime; bool running; diff --git a/box/box_engine_node.c b/box/box_engine_node.c index c181be6..53f3f11 100644 --- a/box/box_engine_node.c +++ b/box/box_engine_node.c @@ -8,6 +8,7 @@ void Box_initEngineNode(Box_EngineNode* node, Toy_Interpreter* interpreter, cons // node->freeMemory = freeMemory; node->functions = TOY_ALLOCATE(Toy_LiteralDictionary, 1); node->parent = NULL; + node->scope = NULL; node->tag = OPAQUE_TAG_ENGINE_NODE; node->children = NULL; node->capacity = 0; @@ -64,7 +65,7 @@ void Box_freeEngineNode(Box_EngineNode* node) { return; //NO-OP } - //free and tombstone this node + //free this node's children for (int i = 0; i < node->count; i++) { Box_freeEngineNode(node->children[i]); } @@ -77,6 +78,10 @@ void Box_freeEngineNode(Box_EngineNode* node) { TOY_FREE(Toy_LiteralDictionary, node->functions); } + if (node->scope != NULL) { + Toy_popScope(node->scope); + } + if (node->texture != NULL) { Box_freeTextureEngineNode(node); } @@ -99,7 +104,6 @@ void Box_freeChildEngineNode(Box_EngineNode* node, int index) { //free the node if (childNode != NULL) { - Box_callRecursiveEngineNode(childNode, &engine.interpreter, "onFree", NULL); Box_freeEngineNode(childNode); node->childCount--; } diff --git a/box/box_engine_node.h b/box/box_engine_node.h index 5be8d87..11d3a0e 100644 --- a/box/box_engine_node.h +++ b/box/box_engine_node.h @@ -22,6 +22,9 @@ typedef struct Box_private_engineNode { //point to the parent Box_EngineNode* parent; + //BUGFIX: hold the node's scope so it can be popped + Toy_Scope* scope; + //my opaque type tag int tag; diff --git a/box/lib_engine.c b/box/lib_engine.c index 8aab366..b2903af 100644 --- a/box/lib_engine.c +++ b/box/lib_engine.c @@ -130,56 +130,9 @@ static int nativeLoadRootNode(Toy_Interpreter* interpreter, Toy_LiteralArray* ar return -1; } - //clear existing root node - if (engine.rootNode != NULL) { - Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onFree", NULL); + //set the signal that a new node is needed + engine.nextRootNodeFilename = Toy_copyLiteral(filePathLiteral); - Box_freeEngineNode(engine.rootNode); - TOY_FREE(Box_EngineNode, engine.rootNode); - - engine.rootNode = NULL; - } - - //load the new root node - size_t size = 0; - const unsigned char* source = Toy_readFile(Toy_toCString(TOY_AS_STRING(filePathLiteral)), &size); - const unsigned char* tb = Toy_compileString((const char*)source, &size); - free((void*)source); - - Box_EngineNode* rootNode = TOY_ALLOCATE(Box_EngineNode, 1); - - //BUGFIX: make an inner-interpreter - Toy_Interpreter inner; - - //init the inner interpreter manually - Toy_initLiteralArray(&inner.literalCache); - inner.scope = Toy_pushScope(interpreter->scope); - inner.bytecode = tb; - inner.length = size; - inner.count = 0; - inner.codeStart = -1; - inner.depth = interpreter->depth + 1; - inner.panic = false; - Toy_initLiteralArray(&inner.stack); - inner.hooks = interpreter->hooks; - Toy_setInterpreterPrint(&inner, interpreter->printOutput); - Toy_setInterpreterAssert(&inner, interpreter->assertOutput); - Toy_setInterpreterError(&inner, interpreter->errorOutput); - - Box_initEngineNode(rootNode, &inner, tb, size); - - //immediately call onLoad() after running the script - for loading other nodes - Box_callEngineNode(rootNode, &engine.interpreter, "onLoad", NULL); - - //NOW it's non-null - engine.rootNode = rootNode; - - //cleanup - Toy_popScope(inner.scope); - inner.scope = NULL; - - Toy_freeLiteralArray(&inner.stack); - Toy_freeLiteralArray(&inner.literalCache); Toy_freeLiteral(filePathLiteral); return 0; diff --git a/box/lib_node.c b/box/lib_node.c index 2c8f1ab..6712b31 100644 --- a/box/lib_node.c +++ b/box/lib_node.c @@ -71,13 +71,15 @@ static int nativeLoadNode(Toy_Interpreter* interpreter, Toy_LiteralArray* argume Box_initEngineNode(node, &inner, tb, size); //immediately call onLoad() after running the script - for loading other nodes - Box_callEngineNode(node, &engine.interpreter, "onLoad", NULL); + Box_callEngineNode(node, &inner, "onLoad", NULL); // return the node Toy_Literal nodeLiteral = TOY_TO_OPAQUE_LITERAL(node, node->tag); Toy_pushLiteralArray(&interpreter->stack, nodeLiteral); //cleanup (NOT the scope - that needs to hang around) + node->scope = inner.scope; + Toy_freeLiteralArray(&inner.stack); Toy_freeLiteralArray(&inner.literalCache); Toy_freeLiteral(filePathLiteral); @@ -246,6 +248,8 @@ static int nativeFreeChildNode(Toy_Interpreter* interpreter, Toy_LiteralArray* a return -1; } + //TODO: differentiate between onFree() and freeing memory + Box_callRecursiveEngineNode(node, interpreter, "onFree", NULL); Box_freeChildEngineNode(node, idx); //cleanup