diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index a6da6ec..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "Toy"] - path = Toy - url = https://github.com/Ratstail91/Toy diff --git a/Airport.sln b/Airport.sln deleted file mode 100644 index c1eb04c..0000000 --- a/Airport.sln +++ /dev/null @@ -1,58 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.4.33213.308 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Box", "Box.vcxproj", "{348A36D9-181E-46AD-BEEB-8A3FFAA50E79}" - ProjectSection(ProjectDependencies) = postProject - {26360002-CC2A-469A-9B28-BA0C1AF41657} = {26360002-CC2A-469A-9B28-BA0C1AF41657} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Toy", "Toy\Toy.vcxproj", "{26360002-CC2A-469A-9B28-BA0C1AF41657}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Airport", "Airport.vcxproj", "{97F823E5-3AB8-47EF-B142-C15DD7CADF76}" - ProjectSection(ProjectDependencies) = postProject - {26360002-CC2A-469A-9B28-BA0C1AF41657} = {26360002-CC2A-469A-9B28-BA0C1AF41657} - {348A36D9-181E-46AD-BEEB-8A3FFAA50E79} = {348A36D9-181E-46AD-BEEB-8A3FFAA50E79} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {348A36D9-181E-46AD-BEEB-8A3FFAA50E79}.Debug|x64.ActiveCfg = Debug|x64 - {348A36D9-181E-46AD-BEEB-8A3FFAA50E79}.Debug|x64.Build.0 = Debug|x64 - {348A36D9-181E-46AD-BEEB-8A3FFAA50E79}.Debug|x86.ActiveCfg = Debug|Win32 - {348A36D9-181E-46AD-BEEB-8A3FFAA50E79}.Debug|x86.Build.0 = Debug|Win32 - {348A36D9-181E-46AD-BEEB-8A3FFAA50E79}.Release|x64.ActiveCfg = Release|x64 - {348A36D9-181E-46AD-BEEB-8A3FFAA50E79}.Release|x64.Build.0 = Release|x64 - {348A36D9-181E-46AD-BEEB-8A3FFAA50E79}.Release|x86.ActiveCfg = Release|Win32 - {348A36D9-181E-46AD-BEEB-8A3FFAA50E79}.Release|x86.Build.0 = Release|Win32 - {26360002-CC2A-469A-9B28-BA0C1AF41657}.Debug|x64.ActiveCfg = Debug|x64 - {26360002-CC2A-469A-9B28-BA0C1AF41657}.Debug|x64.Build.0 = Debug|x64 - {26360002-CC2A-469A-9B28-BA0C1AF41657}.Debug|x86.ActiveCfg = Debug|Win32 - {26360002-CC2A-469A-9B28-BA0C1AF41657}.Debug|x86.Build.0 = Debug|Win32 - {26360002-CC2A-469A-9B28-BA0C1AF41657}.Release|x64.ActiveCfg = Release|x64 - {26360002-CC2A-469A-9B28-BA0C1AF41657}.Release|x64.Build.0 = Release|x64 - {26360002-CC2A-469A-9B28-BA0C1AF41657}.Release|x86.ActiveCfg = Release|Win32 - {26360002-CC2A-469A-9B28-BA0C1AF41657}.Release|x86.Build.0 = Release|Win32 - {97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Debug|x64.ActiveCfg = Debug|x64 - {97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Debug|x64.Build.0 = Debug|x64 - {97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Debug|x86.ActiveCfg = Debug|Win32 - {97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Debug|x86.Build.0 = Debug|Win32 - {97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Release|x64.ActiveCfg = Release|x64 - {97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Release|x64.Build.0 = Release|x64 - {97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Release|x86.ActiveCfg = Release|Win32 - {97F823E5-3AB8-47EF-B142-C15DD7CADF76}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {11A7E1C9-DA78-4754-9B70-3B328B0B5471} - EndGlobalSection -EndGlobal diff --git a/Airport.vcxproj b/Airport.vcxproj deleted file mode 100644 index 14a001b..0000000 --- a/Airport.vcxproj +++ /dev/null @@ -1,161 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - 17.0 - {97F823E5-3AB8-47EF-B142-C15DD7CADF76} - Win32Proj - 10.0 - - - - Application - true - v143 - - - Application - false - v143 - - - Application - true - v143 - - - Application - false - v143 - - - - - - - - - - - - - - - - - - - - - true - - - true - - - false - $(SolutionDir)out\$(Configuration)\ - $(Platform)\$(ProjectName)\$(Configuration)\ - - - $(SolutionDir)out\$(Configuration)\ - $(Platform)\$(ProjectName)\$(Configuration)\ - - - - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level3 - ProgramDatabase - Disabled - - - MachineX86 - true - Console - - - - - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - Level3 - ProgramDatabase - - - MachineX86 - true - Console - true - true - - - - - SDL2main.lib;SDL2.lib;SDL2_image.lib;Toy.lib;Box.lib;%(AdditionalDependencies) - $(SDL2Dir)\lib\x64;$(SDL2ImageDir)\lib\x64;$(SDL2TTFDir)\lib\x64;$(SolutionDir)out\$(Configuration);%(AdditionalLibraryDirectories) - - - $(SDL2Dir)\include;$(SDL2ImageDir)\include;$(SDL2TTFDir)\include;%(SolutionDir)Toy\source;$(SolutionDir)box;%(AdditionalIncludeDirectories) - stdc17 - TOY_DISABLE_REPL - - - - - - - - - stdc17 - TOY_DISABLE_REPL - $(SDL2Dir)\include;$(SDL2ImageDir)\include;$(SDL2TTFDir)\include;%(SolutionDir)Toy\source;$(SolutionDir)box;%(AdditionalIncludeDirectories) - - - $(SDL2Dir)\lib\x64;$(SDL2ImageDir)\lib\x64;$(SDL2TTFDir)\lib\x64;$(SolutionDir)out\$(Configuration);%(AdditionalLibraryDirectories) - SDL2main.lib;SDL2.lib;SDL2_image.lib;Toy.lib;Box.lib;%(AdditionalDependencies) - - - - - - - - - - \ No newline at end of file diff --git a/Box.vcxproj b/Box.vcxproj deleted file mode 100644 index 9037151..0000000 --- a/Box.vcxproj +++ /dev/null @@ -1,170 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 17.0 - {348A36D9-181E-46AD-BEEB-8A3FFAA50E79} - Win32Proj - 10.0 - - - - DynamicLibrary - true - v143 - - - DynamicLibrary - false - v143 - - - DynamicLibrary - true - v143 - - - DynamicLibrary - false - v143 - - - - - - - - - - - - - - - - - - - - - true - - - true - - - $(SolutionDir)out\$(Configuration)\ - $(Platform)\$(ProjectName)\$(Configuration)\ - - - $(SolutionDir)out\$(Configuration)\ - $(Platform)\$(ProjectName)\$(Configuration)\ - - - - WIN32;_DEBUG;_WINDOWS;_USRDLL;BOX_EXPORTS;BOX_EXPORT;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - Level3 - ProgramDatabase - Disabled - - - MachineX86 - true - Windows - - - - - WIN32;NDEBUG;_WINDOWS;_USRDLL;BOX_EXPORTS;BOX_EXPORT;%(PreprocessorDefinitions) - MultiThreadedDLL - Level3 - ProgramDatabase - - - MachineX86 - true - Windows - true - true - - - - - stdc17 - TOY_DISABLE_REPL;BOX_EXPORT;%(PreprocessorDefinitions) - $(SDL2Dir)\include;$(SDL2ImageDir)\include;$(SDL2TTFDir)\include;%(SolutionDir)Toy\source;%(AdditionalIncludeDirectories) - - - $(SDL2Dir)\lib\x64;$(SDL2ImageDir)\lib\x64;$(SDL2TTFDir)\lib\x64;$(SolutionDir)out\$(Configuration)\;%(AdditionalLibraryDirectories) - SDL2.lib;SDL2_image.lib;SDL2_ttf.lib;Toy.lib;%(AdditionalDependencies) - - - xcopy "$(SolutionDir)Toy\repl\lib*.*" "$(SolutionDir)box" /Y /I /E -xcopy "$(SolutionDir)Toy\repl\repl_tools.*" "$(SolutionDir)box" /Y /I /E - - - - - stdc17 - TOY_DISABLE_REPL;BOX_EXPORT;%(PreprocessorDefinitions) - $(SDL2Dir)\include;$(SDL2ImageDir)\include;$(SDL2TTFDir)\include;%(SolutionDir)Toy\source;%(AdditionalIncludeDirectories) - - - $(SDL2Dir)\lib\x64;$(SDL2ImageDir)\lib\x64;$(SDL2TTFDir)\lib\x64;$(SolutionDir)out\$(Configuration)\;%(AdditionalLibraryDirectories) - SDL2.lib;SDL2_image.lib;SDL2_ttf.lib;Toy.lib;%(AdditionalDependencies) - - - xcopy "$(SolutionDir)Toy\repl\lib*.*" "$(SolutionDir)box" /Y /I /E -xcopy "$(SolutionDir)Toy\repl\repl_tools.*" "$(SolutionDir)box" /Y /I /E - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/README.md b/README.md index 84adf7d..433aa9a 100644 --- a/README.md +++ b/README.md @@ -2,27 +2,21 @@ The best way to build a game engine, is to build a game first. -This project has now been adapted into a roguelike for the 7 day roguelike jam. +This game utilizes the [Box Game Engine](https://github.com/Ratstail91/Box) the [Toy Programming Language](https://toylang.com). -This game/engine utilizes the [Toy programming langauge](https://toylang.com). - -## Cloning +# Cloning Either clone recursively, or run `git submodule update --init` after cloning. -## Building +# Building -We're now using Visual Studio - define the following environment variables to point to the root of each SDL2 lib: +WIP -* `SDL2Dir` -* `SDL2ImageDir` -* `SDL2TTFDir` - -## Running +# Running Make sure the program can see the `assets` folder (symbolic links can help), and all of the required DLLs are present. -## Dependencies +# Dependencies * SDL2 * SDL2_image @@ -32,6 +26,6 @@ Make sure the program can see the `assets` folder (symbolic links can help), and * Art - Evan Hartshorn * Coding - Kayne Ruse -* Font - Ancient God (Koczman Bálint) +* Font - Ancient God (Koczman B�lint) * Font - AlphaBeta (Brian Kent) diff --git a/Toy b/Toy deleted file mode 160000 index 0e41b00..0000000 --- a/Toy +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0e41b00ef4634bfe3a068a2b274fa7d89420502a diff --git a/box/box_common.c b/box/box_common.c deleted file mode 100644 index 3371c20..0000000 --- a/box/box_common.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "box_common.h" - -STATIC_ASSERT(sizeof(char) == 1); -STATIC_ASSERT(sizeof(short) == 2); -STATIC_ASSERT(sizeof(int) == 4); -STATIC_ASSERT(sizeof(float) == 4); -STATIC_ASSERT(sizeof(unsigned char) == 1); -STATIC_ASSERT(sizeof(unsigned short) == 2); -STATIC_ASSERT(sizeof(unsigned int) == 4); - diff --git a/box/box_common.h b/box/box_common.h deleted file mode 100644 index 5e10b94..0000000 --- a/box/box_common.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include -#include -#include - -#define BOX_VERSION_MAJOR 0 -#define BOX_VERSION_MINOR 1 -#define BOX_VERSION_PATCH 0 -#define BOX_VERSION_BUILD __DATE__ " " __TIME__ - -//platform/compiler-specific instructions -#if defined(__linux__) || defined(__MINGW32__) || defined(__GNUC__) - -#include -#include -#include - -#include -#define BOX_API extern - -#elif defined(_MSC_VER) - -#include -#include -#include - -#include -#include - -#ifndef BOX_EXPORT -#define BOX_API __declspec(dllimport) -#else -#define BOX_API __declspec(dllexport) -#endif - -//TODO: figure out the sleep issue -#define sleep Sleep - -#else - -#define BOX_API extern - -#endif - -#include - -//test variable sizes based on platform -#define STATIC_ASSERT(test_for_true) static_assert((test_for_true), "(" #test_for_true ") failed") - -//debugging -#include "dbg_profiler.h" diff --git a/box/box_engine.c b/box/box_engine.c deleted file mode 100644 index 492bde7..0000000 --- a/box/box_engine.c +++ /dev/null @@ -1,482 +0,0 @@ -#include "box_engine.h" - -#include "lib_about.h" -#include "lib_standard.h" -#include "lib_random.h" -#include "lib_runner.h" -#include "lib_engine.h" -#include "lib_node.h" -#include "lib_input.h" - -#include "repl_tools.h" - -#include "toy_memory.h" -#include "toy_lexer.h" -#include "toy_parser.h" -#include "toy_compiler.h" -#include "toy_interpreter.h" -#include "toy_literal_array.h" -#include "toy_literal_dictionary.h" - -#include "toy_console_colors.h" - -#include -#include -#include - -//define the extern engine object -Box_Engine engine; - -//errors here should be fatal -static void fatalError(char* message) { - fprintf(stderr, TOY_CC_ERROR "%s" TOY_CC_RESET, message); - exit(-1); -} - -//exposed functions -void Box_initEngine() { - //clear - engine.rootNode = NULL; - engine.nextRootNodeFilename = TOY_TO_NULL_LITERAL; - engine.running = false; - engine.window = NULL; - engine.renderer = NULL; - - //init SDL - if (SDL_Init(SDL_INIT_VIDEO) != 0) { - fatalError("Failed to initialize SDL2"); - } - - //init SDL_image - int imageFlags = IMG_INIT_PNG | IMG_INIT_JPG; - if (IMG_Init(imageFlags) != imageFlags) { - fatalError("Failed to initialize SDL2_image"); - } - - //init SDL_ttf - if (TTF_Init() == -1) { - fatalError("Failed to initialize SDL2_ttf"); - } - - //init events - Toy_initLiteralDictionary(&engine.symKeyDownEvents); - Toy_initLiteralDictionary(&engine.symKeyUpEvents); - - //init Toy - Toy_initInterpreter(&engine.interpreter); - Toy_injectNativeHook(&engine.interpreter, "about", Toy_hookAbout); - Toy_injectNativeHook(&engine.interpreter, "standard", Toy_hookStandard); - Toy_injectNativeHook(&engine.interpreter, "random", Toy_hookRandom); - Toy_injectNativeHook(&engine.interpreter, "runner", Toy_hookRunner); - Toy_injectNativeHook(&engine.interpreter, "engine", Box_hookEngine); - Toy_injectNativeHook(&engine.interpreter, "node", Box_hookNode); - Toy_injectNativeHook(&engine.interpreter, "input", Box_hookInput); - - //run the init - size_t size = 0; - const unsigned char* source = Toy_readFile("./assets/scripts/init.toy", &size); - - if (!source) { - fatalError("Couldn't read /assets/scripts/init.toy"); - } - - const unsigned char* tb = Toy_compileString((const char*)source, &size); - free((void*)source); - - //A quirk of the setup is that anything defined in `init.toy` becomes a global object - Toy_runInterpreter(&engine.interpreter, tb, size); -} - -void Box_freeEngine() { - //clear existing root node - if (engine.rootNode != NULL) { - Box_callRecursiveNode(engine.rootNode, &engine.interpreter, "onFree", NULL); - Box_freeNode(engine.rootNode); - engine.rootNode = NULL; - } - - if (!TOY_IS_NULL(engine.nextRootNodeFilename)) { - Toy_freeLiteral(engine.nextRootNodeFilename); - } - - Toy_freeInterpreter(&engine.interpreter); - - //free events - Toy_freeLiteralDictionary(&engine.symKeyDownEvents); - Toy_freeLiteralDictionary(&engine.symKeyUpEvents); - - //free SDL - SDL_DestroyRenderer(engine.renderer); - SDL_DestroyWindow(engine.window); - SDL_Quit(); - - engine.renderer = NULL; - engine.window = NULL; -} - -static inline 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_callRecursiveNode(engine.rootNode, &engine.interpreter, "onFree", NULL); - Box_freeNode(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_Node, 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_initNode(engine.rootNode, &inner, tb, size); - - //immediately call onLoad() after running the script - for loading other nodes - Box_callNode(engine.rootNode, &inner, "onLoad", NULL); - - //cache the scope for later freeing - engine.rootNode->scope = inner.scope; - - //manual cleanup - 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_callRecursiveNode(engine.rootNode, &engine.interpreter, "onInit", NULL); -} - -static inline void execEvents() { - Toy_LiteralArray args; //save some allocation by reusing this - Toy_initLiteralArray(&args); - - //poll all events - SDL_Event event; - - while (SDL_PollEvent(&event)) { - switch(event.type) { - //quit - case SDL_QUIT: { - engine.running = false; - } - break; - - //window events are handled internally - case SDL_WINDOWEVENT: { - switch(event.window.event) { - case SDL_WINDOWEVENT_RESIZED: - //TODO: toy onWindowResized, setLogicalWindowSize, getLogicalWindowSize - //engine.screenWidth = event.window.data1; - //engine.screenHeight = event.window.data2; - //SDL_RenderSetLogicalSize(engine.renderer, engine.screenWidth, engine.screenHeight); - break; - } - } - break; - - //input - case SDL_KEYDOWN: { - //bugfix: ignore repeat messages - if (event.key.repeat) { - break; - } - - //determine the given keycode - Toy_Literal keycodeLiteral = TOY_TO_INTEGER_LITERAL( (int)(event.key.keysym.sym) ); - if (!Toy_existsLiteralDictionary(&engine.symKeyDownEvents, keycodeLiteral)) { - Toy_freeLiteral(keycodeLiteral); - break; - } - - //get the event name - Toy_Literal eventLiteral = Toy_getLiteralDictionary(&engine.symKeyDownEvents, keycodeLiteral); - - //call the function - Toy_pushLiteralArray(&args, eventLiteral); - Box_callRecursiveNode(engine.rootNode, &engine.interpreter, "onKeyDown", &args); - Toy_freeLiteral(Toy_popLiteralArray(&args)); - - //push to the event list - Toy_freeLiteral(eventLiteral); - Toy_freeLiteral(keycodeLiteral); - } - break; - - case SDL_KEYUP: { - //bugfix: ignore repeat messages - if (event.key.repeat) { - break; - } - - //determine the given keycode - Toy_Literal keycodeLiteral = TOY_TO_INTEGER_LITERAL( (int)(event.key.keysym.sym) ); - if (!Toy_existsLiteralDictionary(&engine.symKeyUpEvents, keycodeLiteral)) { - Toy_freeLiteral(keycodeLiteral); - break; - } - - //get the event name - Toy_Literal eventLiteral = Toy_getLiteralDictionary(&engine.symKeyUpEvents, keycodeLiteral); - - //call the function - Toy_pushLiteralArray(&args, eventLiteral); - Box_callRecursiveNode(engine.rootNode, &engine.interpreter, "onKeyUp", &args); - Toy_freeLiteral(Toy_popLiteralArray(&args)); - - //push to the event list - Toy_freeLiteral(eventLiteral); - Toy_freeLiteral(keycodeLiteral); - } - break; - - //mouse motion - case SDL_MOUSEMOTION: { - Toy_Literal mouseX = TOY_TO_INTEGER_LITERAL( (int)(event.motion.x) ); - Toy_Literal mouseY = TOY_TO_INTEGER_LITERAL( (int)(event.motion.y) ); - Toy_Literal mouseXRel = TOY_TO_INTEGER_LITERAL( (int)(event.motion.xrel) ); - Toy_Literal mouseYRel = TOY_TO_INTEGER_LITERAL( (int)(event.motion.yrel) ); - - Toy_pushLiteralArray(&args, mouseX); - Toy_pushLiteralArray(&args, mouseY); - Toy_pushLiteralArray(&args, mouseXRel); - Toy_pushLiteralArray(&args, mouseYRel); - - Box_callRecursiveNode(engine.rootNode, &engine.interpreter, "onMouseMotion", &args); - - Toy_freeLiteral(mouseX); - Toy_freeLiteral(mouseY); - Toy_freeLiteral(mouseXRel); - Toy_freeLiteral(mouseYRel); - - //hack: manual free - for(int i = 0; i < args.count; i++) { - Toy_freeLiteral(args.literals[i]); - } - args.count = 0; - } - break; - - //mouse button down - case SDL_MOUSEBUTTONDOWN: { - Toy_Literal mouseX = TOY_TO_INTEGER_LITERAL( (int)(event.button.x) ); - Toy_Literal mouseY = TOY_TO_INTEGER_LITERAL( (int)(event.button.y) ); - Toy_Literal mouseButton; - - switch (event.button.button) { - case SDL_BUTTON_LEFT: - mouseButton = TOY_TO_STRING_LITERAL(Toy_createRefString("left")); - break; - - case SDL_BUTTON_MIDDLE: - mouseButton = TOY_TO_STRING_LITERAL(Toy_createRefString("middle")); - break; - - case SDL_BUTTON_RIGHT: - mouseButton = TOY_TO_STRING_LITERAL(Toy_createRefString("right")); - break; - - case SDL_BUTTON_X1: - mouseButton = TOY_TO_STRING_LITERAL(Toy_createRefString("x1")); - break; - - case SDL_BUTTON_X2: - mouseButton = TOY_TO_STRING_LITERAL(Toy_createRefString("x2")); - break; - - default: - mouseButton = TOY_TO_STRING_LITERAL(Toy_createRefString("unknown")); - break; - } - - Toy_pushLiteralArray(&args, mouseX); - Toy_pushLiteralArray(&args, mouseY); - Toy_pushLiteralArray(&args, mouseButton); - - Box_callRecursiveNode(engine.rootNode, &engine.interpreter, "onMouseButtonDown", &args); - - Toy_freeLiteral(mouseX); - Toy_freeLiteral(mouseY); - Toy_freeLiteral(mouseButton); - - //hack: manual free - for(int i = 0; i < args.count; i++) { - Toy_freeLiteral(args.literals[i]); - } - args.count = 0; - } - break; - - //mouse button up - case SDL_MOUSEBUTTONUP: { - Toy_Literal mouseX = TOY_TO_INTEGER_LITERAL( (int)(event.button.x) ); - Toy_Literal mouseY = TOY_TO_INTEGER_LITERAL( (int)(event.button.y) ); - Toy_Literal mouseButton; - - switch (event.button.button) { - case SDL_BUTTON_LEFT: - mouseButton = TOY_TO_STRING_LITERAL(Toy_createRefString("left")); - break; - - case SDL_BUTTON_MIDDLE: - mouseButton = TOY_TO_STRING_LITERAL(Toy_createRefString("middle")); - break; - - case SDL_BUTTON_RIGHT: - mouseButton = TOY_TO_STRING_LITERAL(Toy_createRefString("right")); - break; - - case SDL_BUTTON_X1: - mouseButton = TOY_TO_STRING_LITERAL(Toy_createRefString("x1")); - break; - - case SDL_BUTTON_X2: - mouseButton = TOY_TO_STRING_LITERAL(Toy_createRefString("x2")); - break; - - default: - mouseButton = TOY_TO_STRING_LITERAL(Toy_createRefString("unknown")); - break; - } - - Toy_pushLiteralArray(&args, mouseX); - Toy_pushLiteralArray(&args, mouseY); - Toy_pushLiteralArray(&args, mouseButton); - - Box_callRecursiveNode(engine.rootNode, &engine.interpreter, "onMouseButtonUp", &args); - - Toy_freeLiteral(mouseX); - Toy_freeLiteral(mouseY); - Toy_freeLiteral(mouseButton); - - //hack: manual free - for(int i = 0; i < args.count; i++) { - Toy_freeLiteral(args.literals[i]); - } - args.count = 0; - } - break; - - //mouse wheel - case SDL_MOUSEWHEEL: { - Toy_Literal mouseX = TOY_TO_INTEGER_LITERAL( (int)(event.wheel.x) ); - Toy_Literal mouseY = TOY_TO_INTEGER_LITERAL( (int)(event.wheel.y) ); - Toy_pushLiteralArray(&args, mouseX); - Toy_pushLiteralArray(&args, mouseY); - - Box_callRecursiveNode(engine.rootNode, &engine.interpreter, "onMouseWheel", &args); - - Toy_freeLiteral(mouseX); - Toy_freeLiteral(mouseY); - - //hack: manual free - for(int i = 0; i < args.count; i++) { - Toy_freeLiteral(args.literals[i]); - } - args.count = 0; - } - break; - } - } - - Toy_freeLiteralArray(&args); -} - -static inline void execStep() { - if (engine.rootNode != NULL) { - //steps - Box_callRecursiveNode(engine.rootNode, &engine.interpreter, "onStep", NULL); - } -} - -//the heart of the engine -void Box_execEngine() { - if (!engine.running) { - fatalError("Can't execute the engine (did you forget to initialize the screen?)"); - } - - //set up time - engine.realTime = clock(); - engine.simTime = engine.realTime; - clock_t delta = (double) CLOCKS_PER_SEC / 30.0; - - Dbg_Timer dbgTimer; - Dbg_FPSCounter fps; - - Dbg_initTimer(&dbgTimer); - Dbg_initFPSCounter(&fps); - - while (engine.running) { - Dbg_tickFPSCounter(&fps); - - Dbg_clearConsole(); - Dbg_printTimerLog(&dbgTimer); - Dbg_printFPSCounter(&fps); - - Dbg_startTimer(&dbgTimer, "execLoadRootNode()"); - execLoadRootNode(); - Dbg_stopTimer(&dbgTimer); - - Dbg_startTimer(&dbgTimer, "execEvents()"); - execEvents(); - Dbg_stopTimer(&dbgTimer); - - //calc the time passed - engine.realTime = clock(); - - Dbg_startTimer(&dbgTimer, "execStep() (variable)"); - //while not enough time has passed - while(engine.simTime < engine.realTime) { - //simulate the world - execStep(); - - //calc the time simulation - engine.simTime += delta; - } - Dbg_stopTimer(&dbgTimer); - - //render the world - Dbg_startTimer(&dbgTimer, "clear screen"); - SDL_SetRenderDrawColor(engine.renderer, 128, 128, 128, 255); //NOTE: This line can be disabled later - SDL_RenderClear(engine.renderer); //NOTE: This line can be disabled later - Dbg_stopTimer(&dbgTimer); - - Dbg_startTimer(&dbgTimer, "onDraw() calls"); - Box_callRecursiveNode(engine.rootNode, &engine.interpreter, "onDraw", NULL); - Dbg_stopTimer(&dbgTimer); - - Dbg_startTimer(&dbgTimer, "render screen"); - SDL_RenderPresent(engine.renderer); - Dbg_stopTimer(&dbgTimer); - } - - Dbg_freeTimer(&dbgTimer); - Dbg_freeFPSCounter(&fps); -} diff --git a/box/box_engine.h b/box/box_engine.h deleted file mode 100644 index 18e5b2e..0000000 --- a/box/box_engine.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "box_common.h" -#include "box_node.h" - -#include "toy_interpreter.h" -#include "toy_literal_array.h" -#include "toy_literal_dictionary.h" - -#include - -//the base engine object, which represents the state of the game -typedef struct Box_private_engine { - //engine stuff - Box_Node* rootNode; - Toy_Literal nextRootNodeFilename; - clock_t simTime; - clock_t realTime; - bool running; - - //Toy stuff - Toy_Interpreter interpreter; - - //SDL stuff - SDL_Window* window; - SDL_Renderer* renderer; - int screenWidth; - int screenHeight; - - //input syms mapped to events - Toy_LiteralDictionary symKeyDownEvents; //keysym -> event names - Toy_LiteralDictionary symKeyUpEvents; //keysym -> event names -} Box_Engine; - -//extern singleton - used by various libraries -extern Box_Engine engine; - -//APIs for running the engine in main() -BOX_API void Box_initEngine(); -BOX_API void Box_execEngine(); -BOX_API void Box_freeEngine(); - diff --git a/box/box_node.c b/box/box_node.c deleted file mode 100644 index 7b543c2..0000000 --- a/box/box_node.c +++ /dev/null @@ -1,395 +0,0 @@ -#include "box_node.h" -#include "box_engine.h" - -#include "toy_memory.h" - -void Box_initNode(Box_Node* node, Toy_Interpreter* interpreter, const unsigned char* tb, size_t size) { - //init - // node->freeMemory = freeMemory; - node->functions = TOY_ALLOCATE(Toy_LiteralDictionary, 1); - node->parent = NULL; - node->scope = NULL; - node->tag = OPAQUE_TAG_NODE; - node->children = NULL; - node->capacity = 0; - node->count = 0; - node->childCount = 0; - node->texture = NULL; - node->rect = ((SDL_Rect) { 0, 0, 0, 0 }); - node->frames = 0; - - Toy_initLiteralDictionary(node->functions); - - //run bytecode - Toy_runInterpreter(interpreter, tb, size); - - //grab all top-level functions from the dirty interpreter - Toy_LiteralDictionary* variablesPtr = &interpreter->scope->variables; - - for (int i = 0; i < variablesPtr->capacity; i++) { - //skip empties and tombstones - if (TOY_IS_NULL(variablesPtr->entries[i].key)) { - continue; - } - - //if this variable is a function (this outmodes import and export) - Toy_private_dictionary_entry* entry = &variablesPtr->entries[i]; - if (TOY_IS_FUNCTION(entry->value)) { - //save a copy - Toy_setLiteralDictionary(node->functions, entry->key, entry->value); - } - } -} - -void Box_pushNode(Box_Node* node, Box_Node* child) { - //push to the array - if (node->count + 1 > node->capacity) { - int oldCapacity = node->capacity; - - node->capacity = TOY_GROW_CAPACITY(oldCapacity); - node->children = TOY_GROW_ARRAY(Box_Node*, node->children, oldCapacity, node->capacity); - } - - //assign - node->children[node->count++] = child; - - //reverse-assign - child->parent = node; - - //count - node->childCount++; -} - -void Box_freeNode(Box_Node* node) { - if (node == NULL) { - return; //NO-OP - } - - //free this node's children - for (int i = 0; i < node->count; i++) { - Box_freeNode(node->children[i]); - } - - //free the pointer array to the children - TOY_FREE_ARRAY(Box_Node*, node->children, node->capacity); - - if (node->functions != NULL) { - Toy_freeLiteralDictionary(node->functions); - TOY_FREE(Toy_LiteralDictionary, node->functions); - } - - if (node->scope != NULL) { - Toy_popScope(node->scope); - } - - if (node->texture != NULL) { - Box_freeTextureNode(node); - } - - //free this node's memory - TOY_FREE(Box_Node, node); -} - -Box_Node* Box_getChildNode(Box_Node* node, int index) { - if (index < 0 || index > node->count) { - return NULL; - } - - return node->children[index]; -} - -void Box_freeChildNode(Box_Node* node, int index) { - //get the child node - Box_Node* childNode = node->children[index]; - - //free the node - if (childNode != NULL) { - Box_freeNode(childNode); - node->childCount--; - } - - node->children[index] = NULL; -} - -static void swapUtil(Box_Node** lhs, Box_Node** rhs) { - Box_Node* tmp = *lhs; - *lhs = *rhs; - *rhs = tmp; -} - -//copied from lib_standard.c -static void recursiveLiteralQuicksortUtil(Toy_Interpreter* interpreter, Box_Node** ptr, int count, Toy_Literal fnCompare) { - //base case - if (count <= 1) { - return; - } - - int runner = 0; - - //iterate through the array - for (int checker = 0; checker < count - 1; checker++) { - //if node is null, it is always "sorted" to the end - while (ptr[checker] == NULL && count > 0) { - swapUtil(&ptr[checker], &ptr[count - 1]); - count--; - } - - //base case - if (count < 2) { - return; - } - - Toy_LiteralArray arguments; - Toy_LiteralArray returns; - - Toy_initLiteralArray(&arguments); - Toy_initLiteralArray(&returns); - - Toy_pushLiteralArray(&arguments, TOY_TO_OPAQUE_LITERAL(ptr[checker], OPAQUE_TAG_NODE)); - Toy_pushLiteralArray(&arguments, TOY_TO_OPAQUE_LITERAL(ptr[count - 1], OPAQUE_TAG_NODE)); - - Toy_callLiteralFn(interpreter, fnCompare, &arguments, &returns); - - Toy_Literal lessThan = Toy_popLiteralArray(&returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - - if (TOY_IS_TRUTHY(lessThan)) { - swapUtil(&ptr[runner++], &ptr[checker]); - } - - Toy_freeLiteral(lessThan); - } - - //"shift everything up" so the pivot is in the middle - swapUtil(&ptr[runner], &ptr[count - 1]); - - //recurse on each end - recursiveLiteralQuicksortUtil(interpreter, &ptr[0], runner, fnCompare); - recursiveLiteralQuicksortUtil(interpreter, &ptr[runner + 1], count - runner - 1, fnCompare); -} - -BOX_API void Box_sortChildrenNode(Box_Node* node, Toy_Interpreter* interpreter, Toy_Literal fnCompare) { - //check that this node's children aren't already sorted - bool sorted = true; - for (int checker = 0; checker < node->count - 1 && sorted; checker++) { - //NULL (tombstone) is always considered unsorted - if (node->children[checker] == NULL || node->children[checker + 1] == NULL) { - sorted = false; - break; - } - - Toy_LiteralArray arguments; - Toy_LiteralArray returns; - - Toy_initLiteralArray(&arguments); - Toy_initLiteralArray(&returns); - - Toy_pushLiteralArray(&arguments, TOY_TO_OPAQUE_LITERAL(node->children[checker], OPAQUE_TAG_NODE)); - Toy_pushLiteralArray(&arguments, TOY_TO_OPAQUE_LITERAL(node->children[checker + 1], OPAQUE_TAG_NODE)); - - Toy_callLiteralFn(interpreter, fnCompare, &arguments, &returns); - - Toy_Literal lessThan = Toy_popLiteralArray(&returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - - if (!TOY_IS_TRUTHY(lessThan)) { - sorted = false; - } - - Toy_freeLiteral(lessThan); - } - - //sort the children - if (!sorted) { - recursiveLiteralQuicksortUtil(interpreter, node->children, node->count, fnCompare); - } - - //re-count the newly-sorted children - for (int i = node->count - 1; node->children[i] == NULL; i--) { - node->count--; - } -} - -Toy_Literal Box_callNodeLiteral(Box_Node* node, Toy_Interpreter* interpreter, Toy_Literal key, Toy_LiteralArray* args) { - Toy_Literal ret = TOY_TO_NULL_LITERAL; - - //if this fn exists - if (Toy_existsLiteralDictionary(node->functions, key)) { - Toy_Literal fn = Toy_getLiteralDictionary(node->functions, key); - Toy_Literal n = TOY_TO_OPAQUE_LITERAL(node, node->tag); - - Toy_LiteralArray arguments; - Toy_LiteralArray returns; - Toy_initLiteralArray(&arguments); - Toy_initLiteralArray(&returns); - - //feed the arguments in - Toy_pushLiteralArray(&arguments, n); - - if (args) { - for (int i = 0; i < args->count; i++) { - Toy_pushLiteralArray(&arguments, args->literals[i]); - } - } - - Toy_callLiteralFn(interpreter, fn, &arguments, &returns); - - ret = Toy_popLiteralArray(&returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - - Toy_freeLiteral(n); - Toy_freeLiteral(fn); - } - - return ret; -} - -Toy_Literal Box_callNode(Box_Node* node, Toy_Interpreter* interpreter, const char* fnName, Toy_LiteralArray* args) { - //call "fnName" on this node, and all children, if it exists - Toy_Literal key = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString(fnName)); - - Toy_Literal ret = Box_callNodeLiteral(node, interpreter, key, args); - - Toy_freeLiteral(key); - - return ret; -} - -void Box_callRecursiveNodeLiteral(Box_Node* node, Toy_Interpreter* interpreter, Toy_Literal key, Toy_LiteralArray* args) { - //if this fn exists - if (Toy_existsLiteralDictionary(node->functions, key)) { - Toy_Literal fn = Toy_getLiteralDictionary(node->functions, key); - Toy_Literal n = TOY_TO_OPAQUE_LITERAL(node, node->tag); - - Toy_LiteralArray arguments; - Toy_LiteralArray returns; - Toy_initLiteralArray(&arguments); - Toy_initLiteralArray(&returns); - - //feed the arguments in - Toy_pushLiteralArray(&arguments, n); - - if (args) { - for (int i = 0; i < args->count; i++) { - Toy_pushLiteralArray(&arguments, args->literals[i]); - } - } - - Toy_callLiteralFn(interpreter, fn, &arguments, &returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - - Toy_freeLiteral(n); - Toy_freeLiteral(fn); - } - - //recurse to the (non-tombstone) children - for (int i = 0; i < node->count; i++) { - if (node->children[i] != NULL) { - Box_callRecursiveNodeLiteral(node->children[i], interpreter, key, args); - } - } -} - -void Box_callRecursiveNode(Box_Node* node, Toy_Interpreter* interpreter, const char* fnName, Toy_LiteralArray* args) { - //call "fnName" on this node, and all children, if it exists - Toy_Literal key = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString(fnName)); - - Box_callRecursiveNodeLiteral(node, interpreter, key, args); - - Toy_freeLiteral(key); -} - -int Box_getChildCountNode(Box_Node* node) { - return node->childCount; -} - -int Box_loadTextureNode(Box_Node* node, const char* fname) { - SDL_Surface* surface = IMG_Load(fname); - - if (surface == NULL) { - return -1; - } - - node->texture = SDL_CreateTextureFromSurface(engine.renderer, surface); - - if (node->texture == NULL) { - return -2; - } - - SDL_FreeSurface(surface); - - int w, h; - SDL_QueryTexture(node->texture, NULL, NULL, &w, &h); - SDL_Rect r = { 0, 0, w, h }; - Box_setRectNode(node, r); - Box_setFramesNode(node, 1); //default - - return 0; -} - -void Box_freeTextureNode(Box_Node* node) { - if (node->texture != NULL) { - SDL_DestroyTexture(node->texture); - node->texture = NULL; - } -} - -void Box_setRectNode(Box_Node* node, SDL_Rect rect) { - node->rect = rect; -} - -SDL_Rect Box_getRectNode(Box_Node* node) { - return node->rect; -} - -void Box_setFramesNode(Box_Node* node, int frames) { - node->frames = frames; - node->currentFrame = 0; //just in case -} - -int Box_getFramesNode(Box_Node* node) { - return node->frames; -} - -void Box_setCurrentFrameNode(Box_Node* node, int currentFrame) { - node->currentFrame = currentFrame; -} - -int Box_getCurrentFrameNode(Box_Node* node) { - return node->currentFrame; -} - -void Box_incrementCurrentFrame(Box_Node* node) { - node->currentFrame++; - if (node->currentFrame >= node->frames) { - node->currentFrame = 0; - } -} - -void Box_setTextNode(Box_Node* node, TTF_Font* font, const char* text, SDL_Color color) { - SDL_Surface* surface = TTF_RenderText_Solid(font, text, color); - - node->texture = SDL_CreateTextureFromSurface(engine.renderer, surface); - - node->rect = (SDL_Rect){ .x = 0, .y = 0, .w = surface->w, .h = surface->h }; - node->frames = 1; - node->currentFrame = 0; - - SDL_FreeSurface(surface); -} - - -void Box_drawNode(Box_Node* node, SDL_Rect dest) { - if (!node->texture) return; - SDL_Rect src = node->rect; - src.x += src.w * node->currentFrame; - SDL_RenderCopy(engine.renderer, node->texture, &src, &dest); -} diff --git a/box/box_node.h b/box/box_node.h deleted file mode 100644 index b223e75..0000000 --- a/box/box_node.h +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include "box_common.h" - -#include "toy_literal_dictionary.h" -#include "toy_interpreter.h" - -#define OPAQUE_TAG_NODE 1001 - -//forward declare -typedef struct Box_private_node Box_Node; - -//the node object, which forms a tree -typedef struct Box_private_node { - //toy functions, stored in a dict for flexibility - Toy_LiteralDictionary* functions; - - //point to the parent - Box_Node* parent; - - //BUGFIX: hold the node's scope so it can be popped - Toy_Scope* scope; - - //my opaque type tag - int tag; - - //use Toy's memory model - Box_Node** children; - int capacity; - int count; //includes tombstones - int childCount; - - //rendering-specific features - SDL_Texture* texture; - SDL_Rect rect; //rendered rect - int frames; //horizontal-strip based animations - int currentFrame; -} Box_Node; - -BOX_API void Box_initNode(Box_Node* node, Toy_Interpreter* interpreter, const unsigned char* tb, size_t size); //run bytecode, then grab all top-level function literals -BOX_API void Box_pushNode(Box_Node* node, Box_Node* child); //push to the array (prune tombstones when expanding/copying) -BOX_API void Box_freeNode(Box_Node* node); //free this node and all children - -BOX_API Box_Node* Box_getChildNode(Box_Node* node, int index); -BOX_API void Box_freeChildNode(Box_Node* node, int index); - -BOX_API void Box_sortChildrenNode(Box_Node* node, Toy_Interpreter* interpreter, Toy_Literal fnCompare); - -BOX_API Toy_Literal Box_callNodeLiteral(Box_Node* node, Toy_Interpreter* interpreter, Toy_Literal key, Toy_LiteralArray* args); -BOX_API Toy_Literal Box_callNode(Box_Node* node, Toy_Interpreter* interpreter, const char* fnName, Toy_LiteralArray* args); //call "fnName" on this node, and only this node, if it exists - -//for calling various lifecycle functions -BOX_API void Box_callRecursiveNodeLiteral(Box_Node* node, Toy_Interpreter* interpreter, Toy_Literal key, Toy_LiteralArray* args); -BOX_API void Box_callRecursiveNode(Box_Node* node, Toy_Interpreter* interpreter, const char* fnName, Toy_LiteralArray* args); //call "fnName" on this node, and all children, if it exists - -BOX_API int Box_getChildCountNode(Box_Node* node); - -BOX_API int Box_loadTextureNode(Box_Node* node, const char* fname); -BOX_API void Box_freeTextureNode(Box_Node* node); - -BOX_API void Box_setRectNode(Box_Node* node, SDL_Rect rect); -BOX_API SDL_Rect Box_getRectNode(Box_Node* node); - -BOX_API void Box_setFramesNode(Box_Node* node, int frames); -BOX_API int Box_getFramesNode(Box_Node* node); -BOX_API void Box_setCurrentFrameNode(Box_Node* node, int currentFrame); -BOX_API int Box_getCurrentFrameNode(Box_Node* node); -BOX_API void Box_incrementCurrentFrame(Box_Node* node); - -BOX_API void Box_setTextNode(Box_Node* node, TTF_Font* font, const char* text, SDL_Color color); - -BOX_API void Box_drawNode(Box_Node* node, SDL_Rect dest); diff --git a/box/dbg_profiler.c b/box/dbg_profiler.c deleted file mode 100644 index 340d939..0000000 --- a/box/dbg_profiler.c +++ /dev/null @@ -1,114 +0,0 @@ -#include "dbg_profiler.h" - -#include "toy_memory.h" - -#include - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include - -//https://stackoverflow.com/questions/2347770/how-do-you-clear-the-console-screen-in-c -void Dbg_clearConsole() -{ - HANDLE hStdOut; - CONSOLE_SCREEN_BUFFER_INFO csbi; - DWORD count; - DWORD cellCount; - COORD homeCoords = { 0, 0 }; - - hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); - if (hStdOut == INVALID_HANDLE_VALUE) return; - - /* Get the number of cells in the current buffer */ - if (!GetConsoleScreenBufferInfo(hStdOut, &csbi)) return; - cellCount = csbi.dwSize.X * csbi.dwSize.Y; - - /* Fill the entire buffer with spaces */ - if (!FillConsoleOutputCharacter( - hStdOut, - (TCHAR)' ', - cellCount, - homeCoords, - &count - )) return; - - /* Fill the entire buffer with the current colors and attributes */ - if (!FillConsoleOutputAttribute( - hStdOut, - csbi.wAttributes, - cellCount, - homeCoords, - &count - )) return; - - /* Move the cursor home */ - SetConsoleCursorPosition(hStdOut, homeCoords); -} - -#else // !_WIN32 -#include -#include - -void Dbg_clearConsole() -{ - if (!cur_term) - { - int result; - setupterm(NULL, STDOUT_FILENO, &result); - if (result <= 0) return; - } - - putp(tigetstr("clear")); -} -#endif - -void Dbg_initTimer(Dbg_Timer* timer) { - timer->name = NULL; - timer->start = 0; - memset(timer->log, 0, 2048); - timer->logPos = 0; -} - -void Dbg_startTimer(Dbg_Timer* timer, const char* name) { - timer->name = name; - timer->start = clock(); -} - -void Dbg_stopTimer(Dbg_Timer* timer) { - double duration = (clock() - timer->start) / (double) CLOCKS_PER_SEC * 1000; - timer->logPos += sprintf(&(timer->log[timer->logPos]), "%.3fms %s\n", duration, timer->name); -} - -void Dbg_printTimerLog(Dbg_Timer* timer) { - printf("%.*s", timer->logPos, timer->log); - timer->logPos = 0; -} - -void Dbg_freeTimer(Dbg_Timer* timer) { - // -} - -void Dbg_initFPSCounter(Dbg_FPSCounter* counter) { - counter->count = 0; - counter->start = clock(); - memset(counter->log, 0, 256); -} - -void Dbg_tickFPSCounter(Dbg_FPSCounter* counter) { - counter->count++; - - if (clock() - counter->start > CLOCKS_PER_SEC) { - sprintf(counter->log, "%d FPS", counter->count); - counter->start = clock(); - counter->count = 0; - } -} - -void Dbg_printFPSCounter(Dbg_FPSCounter* counter) { - printf("%s\n", counter->log); -} - -void Dbg_freeFPSCounter(Dbg_FPSCounter* counter) { - // -} \ No newline at end of file diff --git a/box/dbg_profiler.h b/box/dbg_profiler.h deleted file mode 100644 index 7cd9309..0000000 --- a/box/dbg_profiler.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -void Dbg_clearConsole(); - -typedef struct Dbg_Timer { - const char* name; - clock_t start; - char log[2048]; - int logPos; -} Dbg_Timer; - -void Dbg_initTimer(Dbg_Timer*); -void Dbg_startTimer(Dbg_Timer*, const char* name); -void Dbg_stopTimer(Dbg_Timer*); -void Dbg_printTimerLog(Dbg_Timer*); -void Dbg_freeTimer(Dbg_Timer*); - -typedef struct Dbg_FPSCounter { - int count; - clock_t start; - char log[256]; -} Dbg_FPSCounter; - -void Dbg_initFPSCounter(Dbg_FPSCounter*); -void Dbg_tickFPSCounter(Dbg_FPSCounter*); -void Dbg_printFPSCounter(Dbg_FPSCounter*); -void Dbg_freeFPSCounter(Dbg_FPSCounter*); diff --git a/box/lib_about.c b/box/lib_about.c deleted file mode 100644 index fe5b0c8..0000000 --- a/box/lib_about.c +++ /dev/null @@ -1,162 +0,0 @@ -#include "lib_about.h" - -#include "toy_memory.h" - -int Toy_hookAbout(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) { - //the about keys - Toy_Literal majorKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("major")); - Toy_Literal minorKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("minor")); - Toy_Literal patchKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("patch")); - Toy_Literal buildKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("build")); - Toy_Literal authorKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("author")); - - //the about identifiers - Toy_Literal majorIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("major")); - Toy_Literal minorIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("minor")); - Toy_Literal patchIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("patch")); - Toy_Literal buildIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("build")); - Toy_Literal authorIdentifierLiteral = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString("author")); - - //the about values - Toy_Literal majorLiteral = TOY_TO_INTEGER_LITERAL(TOY_VERSION_MAJOR); - Toy_Literal minorLiteral = TOY_TO_INTEGER_LITERAL(TOY_VERSION_MINOR); - Toy_Literal patchLiteral = TOY_TO_INTEGER_LITERAL(TOY_VERSION_PATCH); - Toy_Literal buildLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(TOY_VERSION_BUILD)); - Toy_Literal authorLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("Kayne Ruse, KR Game Studios")); - - //store as an aliased dictionary - if (!TOY_IS_NULL(alias)) { - //make sure the name isn't taken - if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) { - interpreter->errorOutput("Can't override an existing variable\n"); - Toy_freeLiteral(alias); - - Toy_freeLiteral(majorKeyLiteral); - Toy_freeLiteral(minorKeyLiteral); - Toy_freeLiteral(patchKeyLiteral); - Toy_freeLiteral(buildKeyLiteral); - Toy_freeLiteral(authorKeyLiteral); - - Toy_freeLiteral(majorIdentifierLiteral); - Toy_freeLiteral(minorIdentifierLiteral); - Toy_freeLiteral(patchIdentifierLiteral); - Toy_freeLiteral(buildIdentifierLiteral); - Toy_freeLiteral(authorIdentifierLiteral); - - Toy_freeLiteral(majorLiteral); - Toy_freeLiteral(minorLiteral); - Toy_freeLiteral(patchLiteral); - Toy_freeLiteral(buildLiteral); - Toy_freeLiteral(authorLiteral); - - return -1; - } - - //create the dictionary to load up with values - Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1); - Toy_initLiteralDictionary(dictionary); - - //set each key/value pair - Toy_setLiteralDictionary(dictionary, majorKeyLiteral, majorLiteral); - Toy_setLiteralDictionary(dictionary, minorKeyLiteral, minorLiteral); - Toy_setLiteralDictionary(dictionary, patchKeyLiteral, patchLiteral); - Toy_setLiteralDictionary(dictionary, buildKeyLiteral, buildLiteral); - Toy_setLiteralDictionary(dictionary, authorKeyLiteral, authorLiteral); - - //build the type - Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true); - Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true); - Toy_Literal anyType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_ANY, true); - TOY_TYPE_PUSH_SUBTYPE(&type, strType); - TOY_TYPE_PUSH_SUBTYPE(&type, anyType); - - //set scope - Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary); - Toy_declareScopeVariable(interpreter->scope, alias, type); - Toy_setScopeVariable(interpreter->scope, alias, dict, false); - - //cleanup - Toy_freeLiteral(dict); - Toy_freeLiteral(type); - } - - //store globally - else { - //make sure the names aren't taken - if (Toy_isDelcaredScopeVariable(interpreter->scope, majorKeyLiteral) || - Toy_isDelcaredScopeVariable(interpreter->scope, minorKeyLiteral) || - Toy_isDelcaredScopeVariable(interpreter->scope, patchKeyLiteral) || - Toy_isDelcaredScopeVariable(interpreter->scope, buildKeyLiteral) || - Toy_isDelcaredScopeVariable(interpreter->scope, authorKeyLiteral)) { - interpreter->errorOutput("Can't override an existing variable\n"); - Toy_freeLiteral(alias); - - Toy_freeLiteral(majorKeyLiteral); - Toy_freeLiteral(minorKeyLiteral); - Toy_freeLiteral(patchKeyLiteral); - Toy_freeLiteral(buildKeyLiteral); - Toy_freeLiteral(authorKeyLiteral); - - Toy_freeLiteral(majorIdentifierLiteral); - Toy_freeLiteral(minorIdentifierLiteral); - Toy_freeLiteral(patchIdentifierLiteral); - Toy_freeLiteral(buildIdentifierLiteral); - Toy_freeLiteral(authorIdentifierLiteral); - - Toy_freeLiteral(majorLiteral); - Toy_freeLiteral(minorLiteral); - Toy_freeLiteral(patchLiteral); - Toy_freeLiteral(buildLiteral); - Toy_freeLiteral(authorLiteral); - - return -1; - } - - Toy_Literal intType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_INTEGER, true); - Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true); - - //major - Toy_declareScopeVariable(interpreter->scope, majorIdentifierLiteral, intType); - Toy_setScopeVariable(interpreter->scope, majorIdentifierLiteral, majorLiteral, false); - - //minor - Toy_declareScopeVariable(interpreter->scope, minorIdentifierLiteral, intType); - Toy_setScopeVariable(interpreter->scope, minorIdentifierLiteral, minorLiteral, false); - - //patch - Toy_declareScopeVariable(interpreter->scope, patchIdentifierLiteral, intType); - Toy_setScopeVariable(interpreter->scope, patchIdentifierLiteral, patchLiteral, false); - - //build - Toy_declareScopeVariable(interpreter->scope, buildIdentifierLiteral, strType); - Toy_setScopeVariable(interpreter->scope, buildIdentifierLiteral, buildLiteral, false); - - //author - Toy_declareScopeVariable(interpreter->scope, authorIdentifierLiteral, strType); - Toy_setScopeVariable(interpreter->scope, authorIdentifierLiteral, authorLiteral, false); - - Toy_freeLiteral(intType); - Toy_freeLiteral(strType); - } - - //cleanup - Toy_freeLiteral(majorKeyLiteral); - Toy_freeLiteral(minorKeyLiteral); - Toy_freeLiteral(patchKeyLiteral); - Toy_freeLiteral(buildKeyLiteral); - Toy_freeLiteral(authorKeyLiteral); - - Toy_freeLiteral(majorIdentifierLiteral); - Toy_freeLiteral(minorIdentifierLiteral); - Toy_freeLiteral(patchIdentifierLiteral); - Toy_freeLiteral(buildIdentifierLiteral); - Toy_freeLiteral(authorIdentifierLiteral); - - Toy_freeLiteral(majorLiteral); - Toy_freeLiteral(minorLiteral); - Toy_freeLiteral(patchLiteral); - Toy_freeLiteral(buildLiteral); - Toy_freeLiteral(authorLiteral); - - return 0; -} diff --git a/box/lib_about.h b/box/lib_about.h deleted file mode 100644 index 26b1d4a..0000000 --- a/box/lib_about.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "toy_interpreter.h" - -int Toy_hookAbout(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias); - diff --git a/box/lib_engine.c b/box/lib_engine.c deleted file mode 100644 index 41f5f5c..0000000 --- a/box/lib_engine.c +++ /dev/null @@ -1,221 +0,0 @@ -#include "lib_engine.h" - -#include "box_engine.h" - -#include "repl_tools.h" -#include "toy_memory.h" -#include "toy_drive_system.h" -#include "toy_literal_array.h" - -#include "toy_console_colors.h" - -#include - -//errors here should be fatal -static void fatalError(char* message) { - fprintf(stderr, TOY_CC_ERROR "%s" TOY_CC_RESET, message); - exit(-1); -} - -//native functions to be called -static int nativeInitWindow(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (engine.window != NULL) { - fatalError("Can't re-initialize the window\n"); - } - - if (arguments->count != 4) { - fatalError("Incorrect number of arguments passed to initWindow\n"); - } - - //extract the arguments - Toy_Literal fscreen = Toy_popLiteralArray(arguments); - Toy_Literal screenHeight = Toy_popLiteralArray(arguments); - Toy_Literal screenWidth = Toy_popLiteralArray(arguments); - Toy_Literal caption = Toy_popLiteralArray(arguments); - - Toy_Literal captionIdn = caption; - if (TOY_IS_IDENTIFIER(caption) && Toy_parseIdentifierToValue(interpreter, &caption)) { - Toy_freeLiteral(captionIdn); - } - - Toy_Literal screenWidthIdn = screenWidth; - if (TOY_IS_IDENTIFIER(screenWidth) && Toy_parseIdentifierToValue(interpreter, &screenWidth)) { - Toy_freeLiteral(screenWidthIdn); - } - - Toy_Literal screenHeightIdn = screenHeight; - if (TOY_IS_IDENTIFIER(screenHeight) && Toy_parseIdentifierToValue(interpreter, &screenHeight)) { - Toy_freeLiteral(screenHeightIdn); - } - - Toy_Literal fscreenIdn = fscreen; - if (TOY_IS_IDENTIFIER(fscreen) && Toy_parseIdentifierToValue(interpreter, &fscreen)) { - Toy_freeLiteral(fscreenIdn); - } - - //check argument types - if (!TOY_IS_STRING(caption) || !TOY_IS_INTEGER(screenWidth) || !TOY_IS_INTEGER(screenHeight) || !TOY_IS_BOOLEAN(fscreen)) { - fatalError("Incorrect argument type passed to initWindow\n"); - } - - //init the window - engine.window = SDL_CreateWindow( - Toy_toCString(TOY_AS_STRING(caption)), - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - engine.screenWidth = TOY_AS_INTEGER(screenWidth), - engine.screenHeight = TOY_AS_INTEGER(screenHeight), - TOY_IS_TRUTHY(fscreen) ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE - ); - - if (engine.window == NULL) { - fatalError("Failed to initialize the window\n"); - } - - //init the renderer - // SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software"); - engine.renderer = SDL_CreateRenderer(engine.window, -1, SDL_RENDERER_ACCELERATED); - - if (engine.renderer == NULL) { - fatalError("Failed to initialize the renderer\n"); - } - - SDL_RendererInfo rendererInfo; - SDL_GetRendererInfo(engine.renderer, &rendererInfo); - - printf("Renderer: %s (HW %s)\n", rendererInfo.name, rendererInfo.flags & SDL_RENDERER_ACCELERATED ? "yes" : "no"); - - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); - SDL_RenderSetLogicalSize(engine.renderer, engine.screenWidth, engine.screenHeight); - - //only run with a window - engine.running = true; - - Toy_freeLiteral(caption); - Toy_freeLiteral(screenWidth); - Toy_freeLiteral(screenHeight); - Toy_freeLiteral(fscreen); - - return 0; -} - -static int nativeLoadRootNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to loadRootNode\n"); - return -1; - } - - //extract the arguments - Toy_Literal drivePathLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal drivePathLiteralIdn = drivePathLiteral; - if (TOY_IS_IDENTIFIER(drivePathLiteral) && Toy_parseIdentifierToValue(interpreter, &drivePathLiteral)) { - Toy_freeLiteral(drivePathLiteralIdn); - } - - //check argument types - if (!TOY_IS_STRING(drivePathLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to loadRootNode\n"); - Toy_freeLiteral(drivePathLiteral); - return -1; - } - - Toy_Literal filePathLiteral = Toy_getDrivePathLiteral(interpreter, &drivePathLiteral); - - Toy_freeLiteral(drivePathLiteral); //not needed anymore - - if (!TOY_IS_STRING(filePathLiteral)) { - Toy_freeLiteral(filePathLiteral); - return -1; - } - - //set the signal that a new node is needed - engine.nextRootNodeFilename = Toy_copyLiteral(filePathLiteral); - - Toy_freeLiteral(filePathLiteral); - - return 0; -} - -static int nativeGetRootNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 0) { - interpreter->errorOutput("Incorrect number of arguments passed to getRootNode\n"); - return -1; - } - - if (engine.rootNode == NULL) { - interpreter->errorOutput("Can't access root node until after initialization\n"); - return -1; - } - - Toy_Literal resultLiteral = TOY_TO_OPAQUE_LITERAL(engine.rootNode, engine.rootNode->tag); - - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - - return 1; -} - -//call the hook -typedef struct Natives { - char* name; - Toy_NativeFn fn; -} Natives; - -int Box_hookEngine(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) { - //build the natives list - Natives natives[] = { - {"initWindow", nativeInitWindow}, - {"loadRootNode", nativeLoadRootNode}, - {"getRootNode", nativeGetRootNode}, - {NULL, NULL} - }; - - //store the library in an aliased dictionary - if (!TOY_IS_NULL(alias)) { - //make sure the name isn't taken - if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) { - interpreter->errorOutput("Can't override an existing variable\n"); - Toy_freeLiteral(alias); - return false; - } - - //create the dictionary to load up with functions - Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1); - Toy_initLiteralDictionary(dictionary); - - //load the dict with functions - for (int i = 0; natives[i].name; i++) { - Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name)); - Toy_Literal func = TOY_TO_FUNCTION_NATIVE_LITERAL(natives[i].fn); - - Toy_setLiteralDictionary(dictionary, name, func); - - Toy_freeLiteral(name); - Toy_freeLiteral(func); - } - - //build the type - Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true); - Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true); - Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true); - TOY_TYPE_PUSH_SUBTYPE(&type, strType); - TOY_TYPE_PUSH_SUBTYPE(&type, fnType); - - //set scope - Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary); - Toy_declareScopeVariable(interpreter->scope, alias, type); - Toy_setScopeVariable(interpreter->scope, alias, dict, false); - - //cleanup - Toy_freeLiteral(dict); - Toy_freeLiteral(type); - return 0; - } - - //default - for (int i = 0; natives[i].name; i++) { - Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn); - } - - return 0; -} diff --git a/box/lib_engine.h b/box/lib_engine.h deleted file mode 100644 index 02699b7..0000000 --- a/box/lib_engine.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "toy_interpreter.h" - -int Box_hookEngine(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias); - diff --git a/box/lib_input.c b/box/lib_input.c deleted file mode 100644 index a0c05a4..0000000 --- a/box/lib_input.c +++ /dev/null @@ -1,130 +0,0 @@ -#include "lib_input.h" - -#include "box_common.h" -#include "box_engine.h" - -#include "toy_memory.h" - -static int nativeMapInputEventToKey(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments, Toy_LiteralDictionary* symKeyEventsPtr, char* fnName) { - //checks - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments passed to "); - interpreter->errorOutput(fnName); - interpreter->errorOutput("\n"); - return -1; - } - - Toy_Literal symLiteral = Toy_popLiteralArray(arguments); - Toy_Literal evtLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal evtLiteralIdn = evtLiteral; - if (TOY_IS_IDENTIFIER(evtLiteral) && Toy_parseIdentifierToValue(interpreter, &evtLiteral)) { - Toy_freeLiteral(evtLiteralIdn); - } - - Toy_Literal symLiteralIdn = symLiteral; - if (TOY_IS_IDENTIFIER(symLiteral) && Toy_parseIdentifierToValue(interpreter, &symLiteral)) { - Toy_freeLiteral(symLiteralIdn); - } - - if (!TOY_IS_STRING(symLiteral) || !TOY_IS_STRING(evtLiteral)) { - interpreter->errorOutput("Incorrect type of arguments passed to mapInputEventToKey\n"); - return -1; - } - - //use the keycode for faster lookups - SDL_Keycode keycode = SDL_GetKeyFromName( Toy_toCString(TOY_AS_STRING(symLiteral)) ); - - if (keycode == SDLK_UNKNOWN) { - interpreter->errorOutput("Unknown key found: "); - interpreter->errorOutput(SDL_GetError()); - interpreter->errorOutput("\n"); - return -1; - } - - Toy_Literal keycodeLiteral = TOY_TO_INTEGER_LITERAL( (int)keycode ); - - //save the sym-event pair - Toy_setLiteralDictionary(symKeyEventsPtr, keycodeLiteral, evtLiteral); //I could possibly map multiple events to one sym - - //cleanup - Toy_freeLiteral(symLiteral); - Toy_freeLiteral(evtLiteral); - Toy_freeLiteral(keycodeLiteral); - - return 0; -} - -//dry wrappers -static int nativeMapInputEventToKeyDown(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - return nativeMapInputEventToKey(interpreter, arguments, &engine.symKeyDownEvents, "mapInputEventToKeyDown"); -} - -static int nativeMapInputEventToKeyUp(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - return nativeMapInputEventToKey(interpreter, arguments, &engine.symKeyUpEvents, "mapInputEventToKeyUp"); -} - -//call the hook -typedef struct Natives { - char* name; - Toy_NativeFn fn; -} Natives; - -int Box_hookInput(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) { - //build the natives list - Natives natives[] = { - {"mapInputEventToKeyDown", nativeMapInputEventToKeyDown}, - {"mapInputEventToKeyUp", nativeMapInputEventToKeyUp}, - // {"mapInputEventToMouse", nativeMapInputEventToMouse}, - {NULL, NULL} - }; - - //store the library in an aliased dictionary - if (!TOY_IS_NULL(alias)) { - //make sure the name isn't taken - if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) { - interpreter->errorOutput("Can't override an existing variable\n"); - Toy_freeLiteral(alias); - return false; - } - - //create the dictionary to load up with functions - Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1); - Toy_initLiteralDictionary(dictionary); - - //load the dict with functions - for (int i = 0; natives[i].name; i++) { - Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name)); - Toy_Literal func = TOY_TO_FUNCTION_NATIVE_LITERAL(natives[i].fn); - - Toy_setLiteralDictionary(dictionary, name, func); - - Toy_freeLiteral(name); - Toy_freeLiteral(func); - } - - //build the type - Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true); - Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true); - Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true); - TOY_TYPE_PUSH_SUBTYPE(&type, strType); - TOY_TYPE_PUSH_SUBTYPE(&type, fnType); - - //set scope - Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary); - Toy_declareScopeVariable(interpreter->scope, alias, type); - Toy_setScopeVariable(interpreter->scope, alias, dict, false); - - //cleanup - Toy_freeLiteral(dict); - Toy_freeLiteral(type); - return 0; - } - - //default - for (int i = 0; natives[i].name; i++) { - Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn); - } - - return 0; -} diff --git a/box/lib_input.h b/box/lib_input.h deleted file mode 100644 index 34e2bd4..0000000 --- a/box/lib_input.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "toy_interpreter.h" - -int Box_hookInput(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias); - diff --git a/box/lib_node.c b/box/lib_node.c deleted file mode 100644 index 7e4cd5e..0000000 --- a/box/lib_node.c +++ /dev/null @@ -1,1209 +0,0 @@ -#include "lib_node.h" - -#include "box_node.h" -#include "box_engine.h" - -#include "repl_tools.h" -#include "toy_drive_system.h" -#include "toy_literal_array.h" -#include "toy_memory.h" - -#include - -static int nativeLoadNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to loadNode\n"); - return -1; - } - - //extract the arguments - Toy_Literal drivePathLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal drivePathLiteralIdn = drivePathLiteral; - if (TOY_IS_IDENTIFIER(drivePathLiteral) && Toy_parseIdentifierToValue(interpreter, &drivePathLiteral)) { - Toy_freeLiteral(drivePathLiteralIdn); - } - - //check argument types - if (!TOY_IS_STRING(drivePathLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to loadNode\n"); - Toy_freeLiteral(drivePathLiteral); - return -1; - } - - Toy_Literal filePathLiteral = Toy_getDrivePathLiteral(interpreter, &drivePathLiteral); - - if (!TOY_IS_STRING(filePathLiteral)) { - Toy_freeLiteral(drivePathLiteral); - Toy_freeLiteral(filePathLiteral); - return -1; - } - - Toy_freeLiteral(drivePathLiteral); //not needed anymore - - //load the new 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_Node* node = TOY_ALLOCATE(Box_Node, 1); - - //BUGFIX: make an -interpreter - Toy_Interpreter inner; - - //init the inner interpreter manually - Toy_initLiteralArray(&inner.literalCache); - Toy_initLiteralArray(&inner.stack); - inner.hooks = interpreter->hooks; - 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_setInterpreterPrint(&inner, interpreter->printOutput); - Toy_setInterpreterAssert(&inner, interpreter->assertOutput); - Toy_setInterpreterError(&inner, interpreter->errorOutput); - - Box_initNode(node, &inner, tb, size); - - //immediately call onLoad() after running the script - for loading other nodes - Box_callNode(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); - Toy_freeLiteral(nodeLiteral); - - return 1; -} - -static int nativeInitNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to initNode\n"); - return -1; - } - - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to initNode\n"); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - Box_Node* node = TOY_AS_OPAQUE(nodeLiteral); - - //init the new node (and ONLY this node) - Box_callNode(node, &engine.interpreter, "onInit", NULL); - - //cleanup - Toy_freeLiteral(nodeLiteral); - return 0; -} - -static int nativePushNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //checks - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments passed to pushNode\n"); - return -1; - } - - Toy_Literal child = Toy_popLiteralArray(arguments); - Toy_Literal parent = Toy_popLiteralArray(arguments); - - Toy_Literal parentIdn = parent; - if (TOY_IS_IDENTIFIER(parent) && Toy_parseIdentifierToValue(interpreter, &parent)) { - Toy_freeLiteral(parentIdn); - } - - Toy_Literal childIdn = child; - if (TOY_IS_IDENTIFIER(child) && Toy_parseIdentifierToValue(interpreter, &child)) { - Toy_freeLiteral(childIdn); - } - - if (!TOY_IS_OPAQUE(parent) || !TOY_IS_OPAQUE(child)) { - interpreter->errorOutput("Incorrect argument type passed to pushNode\n"); - Toy_freeLiteral(parent); - Toy_freeLiteral(child); - return -1; - } - - //push the node - Box_Node* parentNode = TOY_AS_OPAQUE(parent); - Box_Node* childNode = TOY_AS_OPAQUE(child); - - Box_pushNode(parentNode, childNode); - - //no return value - Toy_freeLiteral(parent); - Toy_freeLiteral(child); - - return 0; -} - -static int nativeGetChildNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //checks - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments passed to getChildNode\n"); - return -1; - } - - Toy_Literal index = Toy_popLiteralArray(arguments); - Toy_Literal parent = Toy_popLiteralArray(arguments); - - Toy_Literal parentIdn = parent; - if (TOY_IS_IDENTIFIER(parent) && Toy_parseIdentifierToValue(interpreter, &parent)) { - Toy_freeLiteral(parentIdn); - } - - Toy_Literal indexIdn = index; - if (TOY_IS_IDENTIFIER(index) && Toy_parseIdentifierToValue(interpreter, &index)) { - Toy_freeLiteral(indexIdn); - } - - if (!TOY_IS_OPAQUE(parent) || !TOY_IS_INTEGER(index)) { - interpreter->errorOutput("Incorrect argument type passed to getChildNode\n"); - Toy_freeLiteral(parent); - Toy_freeLiteral(index); - return -1; - } - - //push the node - Box_Node* parentNode = TOY_AS_OPAQUE(parent); - int intIndex = TOY_AS_INTEGER(index); - - if (intIndex < 0 || intIndex >= parentNode->count) { - interpreter->errorOutput("index out of bounds in getChildNode\n"); - Toy_freeLiteral(parent); - Toy_freeLiteral(index); - return -1; - } - - Box_Node* childNode = Box_getChildNode(parentNode, intIndex); - Toy_Literal child; - - if (childNode == NULL) { - child = TOY_TO_NULL_LITERAL; - } - else { - child = TOY_TO_OPAQUE_LITERAL(childNode, childNode->tag); - } - - Toy_pushLiteralArray(&interpreter->stack, child); - - //cleanup - Toy_freeLiteral(parent); - Toy_freeLiteral(child); - Toy_freeLiteral(index); - - return 1; -} - -static int nativeFreeChildNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments passed to freeChildNode\n"); - return -1; - } - - Toy_Literal indexLiteral = Toy_popLiteralArray(arguments); - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeLiteralIdn = nodeLiteral; //annoying - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeLiteralIdn); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral) || !TOY_IS_INTEGER(indexLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to freeChildNode\n"); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - Box_Node* node = TOY_AS_OPAQUE(nodeLiteral); - int idx = TOY_AS_INTEGER(indexLiteral); - - //check bounds - if (idx < 0 || idx >= node->count) { - interpreter->errorOutput("Node index out of bounds in freeChildNode\n"); - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(indexLiteral); - return -1; - } - - //TODO: differentiate between onFree() and freeing memory - Box_callRecursiveNode(node, interpreter, "onFree", NULL); - Box_freeChildNode(node, idx); - - //cleanup - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(indexLiteral); - return 0; -} - -static int nativeSortChildrenNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments passed to sortChildrenNode\n"); - return -1; - } - - Toy_Literal fnLiteral = Toy_popLiteralArray(arguments); - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeLiteralIdn = nodeLiteral; //annoying - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeLiteralIdn); - } - - Toy_Literal fnLiteralIdn = fnLiteral; //annoying - if (TOY_IS_IDENTIFIER(fnLiteral) && Toy_parseIdentifierToValue(interpreter, &fnLiteral)) { - Toy_freeLiteral(fnLiteralIdn); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral) || !TOY_IS_FUNCTION(fnLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to sortChildrenNode\n"); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - Box_Node* node = TOY_AS_OPAQUE(nodeLiteral); - - Box_sortChildrenNode(node, interpreter, fnLiteral); - - //cleanup - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(fnLiteral); - return 0; -} - -static int nativeGetParentNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //checks - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to getParentNode\n"); - return -1; - } - - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - if (!TOY_IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to getParentNode\n"); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - //push the node - Box_Node* node = TOY_AS_OPAQUE(nodeLiteral); - Box_Node* parent = node->parent; - - Toy_Literal parentLiteral = TOY_TO_NULL_LITERAL; - if (parent != NULL) { - parentLiteral = TOY_TO_OPAQUE_LITERAL(parent, parent->tag); - } - - Toy_pushLiteralArray(&interpreter->stack, parentLiteral); - - //cleanup - Toy_freeLiteral(parentLiteral); - Toy_freeLiteral(nodeLiteral); - - return 1; -} - -static int nativeGetChildNodeCount(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //checks - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to getChildNodeCount\n"); - return -1; - } - - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeLiteralIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeLiteralIdn); - } - - if (!TOY_IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to getChildNodeCount\n"); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - //get the count - Box_Node* node = TOY_AS_OPAQUE(nodeLiteral); - int childCount = Box_getChildCountNode(node); - Toy_Literal childCountLiteral = TOY_TO_INTEGER_LITERAL(childCount); - - Toy_pushLiteralArray(&interpreter->stack, childCountLiteral); - - //no return value - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(childCountLiteral); - - return 0; -} - -static int nativeLoadNodeTexture(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments passed to loadNodeTexture\n"); - return -1; - } - - //extract the arguments - Toy_Literal drivePathLiteral = Toy_popLiteralArray(arguments); - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal drivePathLiteralIdn = drivePathLiteral; - if (TOY_IS_IDENTIFIER(drivePathLiteral) && Toy_parseIdentifierToValue(interpreter, &drivePathLiteral)) { - Toy_freeLiteral(drivePathLiteralIdn); - } - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - //check argument types - if (!TOY_IS_STRING(drivePathLiteral) || !TOY_IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to loadNodeTexture\n"); - Toy_freeLiteral(drivePathLiteral); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - Toy_Literal filePathLiteral = Toy_getDrivePathLiteral(interpreter, &drivePathLiteral); - - if (!TOY_IS_STRING(filePathLiteral)) { - Toy_freeLiteral(drivePathLiteral); - Toy_freeLiteral(filePathLiteral); - return -1; - } - - Toy_freeLiteral(drivePathLiteral); //not needed anymore - - //actually load TODO: number the opaques, and check the tag - Box_Node* node = (Box_Node*)TOY_AS_OPAQUE(nodeLiteral); - - if (node->texture != NULL) { - Box_freeTextureNode(node); - } - - if (Box_loadTextureNode(node, Toy_toCString(TOY_AS_STRING(filePathLiteral))) != 0) { - interpreter->errorOutput("Failed to load the texture into the Box_Node\n"); - Toy_freeLiteral(filePathLiteral); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - //cleanup - Toy_freeLiteral(filePathLiteral); - Toy_freeLiteral(nodeLiteral); - - return 0; -} - -static int nativeFreeNodeTexture(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to freeNodeTexture\n"); - return -1; - } - - //extract the arguments - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to freeNodeTexture\n"); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - //actually load TODO: number the opaques, and check the numbers - Box_Node* node = (Box_Node*)TOY_AS_OPAQUE(nodeLiteral); - - if (node->texture != NULL) { - Box_freeTextureNode(node); - } - - //cleanup - Toy_freeLiteral(nodeLiteral); - - return 0; -} - -static int nativeSetNodeRect(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 5) { - interpreter->errorOutput("Incorrect number of arguments passed to setNodeRect\n"); - return -1; - } - - //extract the arguments - Toy_Literal h = Toy_popLiteralArray(arguments); - Toy_Literal w = Toy_popLiteralArray(arguments); - Toy_Literal y = Toy_popLiteralArray(arguments); - Toy_Literal x = Toy_popLiteralArray(arguments); - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - Toy_Literal xi = x; - if (TOY_IS_IDENTIFIER(x) && Toy_parseIdentifierToValue(interpreter, &x)) { - Toy_freeLiteral(xi); - } - - Toy_Literal yi = y; - if (TOY_IS_IDENTIFIER(y) && Toy_parseIdentifierToValue(interpreter, &y)) { - Toy_freeLiteral(yi); - } - - Toy_Literal wi = w; - if (TOY_IS_IDENTIFIER(w) && Toy_parseIdentifierToValue(interpreter, &w)) { - Toy_freeLiteral(wi); - } - - Toy_Literal hi = h; - if (TOY_IS_IDENTIFIER(h) && Toy_parseIdentifierToValue(interpreter, &h)) { - Toy_freeLiteral(hi); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral) || !TOY_IS_INTEGER(x) || !TOY_IS_INTEGER(y) || !TOY_IS_INTEGER(w) || !TOY_IS_INTEGER(h)) { - interpreter->errorOutput("Incorrect argument type passed to setNodeRect\n"); - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(x); - Toy_freeLiteral(y); - Toy_freeLiteral(w); - Toy_freeLiteral(h); - return -1; - } - - //actually set - Box_Node* node = (Box_Node*)TOY_AS_OPAQUE(nodeLiteral); - - SDL_Rect r = {TOY_AS_INTEGER(x), TOY_AS_INTEGER(y), TOY_AS_INTEGER(w), TOY_AS_INTEGER(h)}; - Box_setRectNode(node, r); - - //cleanup - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(x); - Toy_freeLiteral(y); - Toy_freeLiteral(w); - Toy_freeLiteral(h); - - return 0; -} - -static int nativeGetNodeRectX(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to getNodeRectX\n"); - return -1; - } - - //extract the arguments - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to getNodeRectX\n"); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - //actually get - Box_Node* node = (Box_Node*)TOY_AS_OPAQUE(nodeLiteral); - Toy_Literal resultLiteral = TOY_TO_INTEGER_LITERAL(node->rect.x); - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - - //cleanup - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(resultLiteral); - - return 1; -} - -static int nativeGetNodeRectY(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to getNodeRectY\n"); - return -1; - } - - //extract the arguments - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to getNodeRectY\n"); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - //actually get - Box_Node* node = (Box_Node*)TOY_AS_OPAQUE(nodeLiteral); - Toy_Literal resultLiteral = TOY_TO_INTEGER_LITERAL(node->rect.y); - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - - //cleanup - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(resultLiteral); - - return 1; -} - -static int nativeGetNodeRectW(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to getNodeRectW\n"); - return -1; - } - - //extract the arguments - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to getNodeRectW\n"); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - //actually get - Box_Node* node = (Box_Node*)TOY_AS_OPAQUE(nodeLiteral); - Toy_Literal resultLiteral = TOY_TO_INTEGER_LITERAL(node->rect.w); - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - - //cleanup - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(resultLiteral); - - return 1; -} - -static int nativeGetNodeRectH(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to getNodeRectH\n"); - return -1; - } - - //extract the arguments - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to getNodeRectH\n"); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - //actually get - Box_Node* node = (Box_Node*)TOY_AS_OPAQUE(nodeLiteral); - Toy_Literal resultLiteral = TOY_TO_INTEGER_LITERAL(node->rect.h); - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - - //cleanup - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(resultLiteral); - - return 1; -} - -static int nativeSetNodeFrames(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments passed to setNodeFrames\n"); - return -1; - } - - //extract the arguments - Toy_Literal framesLiteral = Toy_popLiteralArray(arguments); - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - Toy_Literal frameLiteralIdn = framesLiteral; - if (TOY_IS_IDENTIFIER(framesLiteral) && Toy_parseIdentifierToValue(interpreter, &framesLiteral)) { - Toy_freeLiteral(frameLiteralIdn); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral) || !TOY_IS_INTEGER(framesLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to setNodeFrames\n"); - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(framesLiteral); - return -1; - } - - //actually set - Box_Node* node = (Box_Node*)TOY_AS_OPAQUE(nodeLiteral); - - Box_setFramesNode(node, TOY_AS_INTEGER(framesLiteral)); - - //cleanup - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(framesLiteral); - - return 0; -} - -static int nativeGetNodeFrames(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to getNodeFrames\n"); - return -1; - } - - //extract the arguments - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to getNodeFrames\n"); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - //actually get - Box_Node* node = (Box_Node*)TOY_AS_OPAQUE(nodeLiteral); - Toy_Literal framesLiteral = TOY_TO_INTEGER_LITERAL(node->frames); - - Toy_pushLiteralArray(&interpreter->stack, framesLiteral); - - - //cleanup - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(framesLiteral); - - return 1; -} - -static int nativeSetCurrentNodeFrame(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments passed to setCurrentNodeFrame\n"); - return -1; - } - - //extract the arguments - Toy_Literal currentFrameLiteral = Toy_popLiteralArray(arguments); - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - Toy_Literal currentFrameLiteralIdn = currentFrameLiteral; - if (TOY_IS_IDENTIFIER(currentFrameLiteral) && Toy_parseIdentifierToValue(interpreter, ¤tFrameLiteral)) { - Toy_freeLiteral(currentFrameLiteralIdn); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral) || !TOY_IS_INTEGER(currentFrameLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to setCurrentNodeFrame\n"); - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(currentFrameLiteral); - return -1; - } - - //actually set - Box_Node* node = (Box_Node*)TOY_AS_OPAQUE(nodeLiteral); - - Box_setCurrentFrameNode(node, TOY_AS_INTEGER(currentFrameLiteral)); - - //cleanup - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(currentFrameLiteral); - - return 0; -} - -static int nativeGetCurrentNodeFrame(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to getCurrentNodeFrame\n"); - return -1; - } - - //extract the arguments - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to getCurrentNodeFrame\n"); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - //actually get - Box_Node* node = (Box_Node*)TOY_AS_OPAQUE(nodeLiteral); - Toy_Literal currentFrameLiteral = TOY_TO_INTEGER_LITERAL(node->currentFrame); - - Toy_pushLiteralArray(&interpreter->stack, currentFrameLiteral); - - //cleanup - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(currentFrameLiteral); - - return 1; -} - -static int nativeIncrementCurrentNodeFrame(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to incrementCurrentNodeFrame\n"); - return -1; - } - - //extract the arguments - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to incrementCurrentNodeFrame\n"); - Toy_freeLiteral(nodeLiteral); - return -1; - } - - //actually get - Box_Node* node = (Box_Node*)TOY_AS_OPAQUE(nodeLiteral); - - Box_incrementCurrentFrame(node); - - //cleanup - Toy_freeLiteral(nodeLiteral); - - return 0; -} - -static int nativeDrawNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 3 && arguments->count != 5) { - interpreter->errorOutput("Incorrect number of arguments passed to drawNode\n"); - return -1; - } - - //extract the arguments - Toy_Literal w = TOY_TO_NULL_LITERAL, h = TOY_TO_NULL_LITERAL; - if (arguments->count == 5) { - h = Toy_popLiteralArray(arguments); - w = Toy_popLiteralArray(arguments); - } - - Toy_Literal y = Toy_popLiteralArray(arguments); - Toy_Literal x = Toy_popLiteralArray(arguments); - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - Toy_Literal xi = x; - if (TOY_IS_IDENTIFIER(x) && Toy_parseIdentifierToValue(interpreter, &x)) { - Toy_freeLiteral(xi); - } - - Toy_Literal yi = y; - if (TOY_IS_IDENTIFIER(y) && Toy_parseIdentifierToValue(interpreter, &y)) { - Toy_freeLiteral(yi); - } - - Toy_Literal wi = w; - if (TOY_IS_IDENTIFIER(w) && Toy_parseIdentifierToValue(interpreter, &w)) { - Toy_freeLiteral(wi); - } - - Toy_Literal hi = h; - if (TOY_IS_IDENTIFIER(h) && Toy_parseIdentifierToValue(interpreter, &h)) { - Toy_freeLiteral(hi); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral) || !TOY_IS_INTEGER(x) || !TOY_IS_INTEGER(y) || (!TOY_IS_INTEGER(w) && !TOY_IS_NULL(w)) || (!TOY_IS_INTEGER(h) && !TOY_IS_NULL(h))) { - interpreter->errorOutput("Incorrect argument type passed to drawNode\n"); - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(x); - Toy_freeLiteral(y); - Toy_freeLiteral(w); - Toy_freeLiteral(h); - return -1; - } - - //actually render - Box_Node* node = (Box_Node*)TOY_AS_OPAQUE(nodeLiteral); - - SDL_Rect r = {TOY_AS_INTEGER(x), TOY_AS_INTEGER(y), 0, 0}; - if (TOY_IS_INTEGER(w) && TOY_IS_INTEGER(h)) { - r.w = TOY_AS_INTEGER(w); - r.h = TOY_AS_INTEGER(h); - } - else { - r.w = node->rect.w; - r.h = node->rect.h; - } - - Box_drawNode(node, r); - - //cleanup - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(x); - Toy_freeLiteral(y); - Toy_freeLiteral(w); - Toy_freeLiteral(h); - - return 0; -} - -static int nativeSetNodeText(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 8) { - interpreter->errorOutput("Incorrect number of arguments passed to setNodeText\n"); - return -1; - } - - //extract the arguments - Toy_Literal aLiteral = Toy_popLiteralArray(arguments); - Toy_Literal bLiteral = Toy_popLiteralArray(arguments); - Toy_Literal gLiteral = Toy_popLiteralArray(arguments); - Toy_Literal rLiteral = Toy_popLiteralArray(arguments); - Toy_Literal textLiteral = Toy_popLiteralArray(arguments); - Toy_Literal sizeLiteral = Toy_popLiteralArray(arguments); - Toy_Literal fontLiteral = Toy_popLiteralArray(arguments); - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeLiteralIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeLiteralIdn); - } - - Toy_Literal fontLiteralIdn = fontLiteral; - if (TOY_IS_IDENTIFIER(fontLiteral) && Toy_parseIdentifierToValue(interpreter, &fontLiteral)) { - Toy_freeLiteral(fontLiteralIdn); - } - - Toy_Literal sizeLiteralIdn = sizeLiteral; - if (TOY_IS_IDENTIFIER(sizeLiteral) && Toy_parseIdentifierToValue(interpreter, &sizeLiteral)) { - Toy_freeLiteral(sizeLiteralIdn); - } - - Toy_Literal textLiteralIdn = textLiteral; - if (TOY_IS_IDENTIFIER(textLiteral) && Toy_parseIdentifierToValue(interpreter, &textLiteral)) { - Toy_freeLiteral(textLiteralIdn); - } - - Toy_Literal rLiteralIdn = rLiteral; - if (TOY_IS_IDENTIFIER(rLiteral) && Toy_parseIdentifierToValue(interpreter, &rLiteral)) { - Toy_freeLiteral(rLiteralIdn); - } - - Toy_Literal gLiteralIdn = gLiteral; - if (TOY_IS_IDENTIFIER(gLiteral) && Toy_parseIdentifierToValue(interpreter, &gLiteral)) { - Toy_freeLiteral(gLiteralIdn); - } - - Toy_Literal bLiteralIdn = bLiteral; - if (TOY_IS_IDENTIFIER(bLiteral) && Toy_parseIdentifierToValue(interpreter, &bLiteral)) { - Toy_freeLiteral(bLiteralIdn); - } - - Toy_Literal aLiteralIdn = aLiteral; - if (TOY_IS_IDENTIFIER(aLiteral) && Toy_parseIdentifierToValue(interpreter, &aLiteral)) { - Toy_freeLiteral(aLiteralIdn); - } - - //check argument types - if (!TOY_IS_OPAQUE(nodeLiteral) || !TOY_IS_STRING(fontLiteral) || !TOY_IS_INTEGER(sizeLiteral) || !TOY_IS_STRING(textLiteral) - || !TOY_IS_INTEGER(rLiteral) || !TOY_IS_INTEGER(gLiteral) || !TOY_IS_INTEGER(bLiteral) || !TOY_IS_INTEGER(aLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to setNodeText\n"); - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(fontLiteral); - Toy_freeLiteral(sizeLiteral); - Toy_freeLiteral(textLiteral); - Toy_freeLiteral(rLiteral); - Toy_freeLiteral(gLiteral); - Toy_freeLiteral(bLiteral); - Toy_freeLiteral(aLiteral); - return -1; - } - - //bounds checks - if (TOY_AS_INTEGER(rLiteral) < 0 || TOY_AS_INTEGER(rLiteral) > 255 || - TOY_AS_INTEGER(gLiteral) < 0 || TOY_AS_INTEGER(gLiteral) > 255 || - TOY_AS_INTEGER(bLiteral) < 0 || TOY_AS_INTEGER(bLiteral) > 255 || - TOY_AS_INTEGER(aLiteral) < 0 || TOY_AS_INTEGER(aLiteral) > 255) { - interpreter->errorOutput("Color out of bounds in to setNodeText\n"); - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(fontLiteral); - Toy_freeLiteral(sizeLiteral); - Toy_freeLiteral(textLiteral); - Toy_freeLiteral(rLiteral); - Toy_freeLiteral(gLiteral); - Toy_freeLiteral(bLiteral); - Toy_freeLiteral(aLiteral); - return -1; - } - - //get the font - Toy_Literal fileLiteral = Toy_getDrivePathLiteral(interpreter, &fontLiteral); - - TTF_Font* font = TTF_OpenFont( Toy_toCString(TOY_AS_STRING(fileLiteral)), TOY_AS_INTEGER(sizeLiteral) ); - - if (!font) { - interpreter->errorOutput("Failed to open a font file: "); - interpreter->errorOutput(SDL_GetError()); - interpreter->errorOutput("\n"); - - Toy_freeLiteral(fileLiteral); - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(fontLiteral); - Toy_freeLiteral(sizeLiteral); - Toy_freeLiteral(textLiteral); - Toy_freeLiteral(rLiteral); - Toy_freeLiteral(gLiteral); - Toy_freeLiteral(bLiteral); - Toy_freeLiteral(aLiteral); - return -1; - } - - //make the color - SDL_Color color = (SDL_Color){ .r = TOY_AS_INTEGER(rLiteral), .g = TOY_AS_INTEGER(gLiteral), .b = TOY_AS_INTEGER(bLiteral), .a = TOY_AS_INTEGER(aLiteral) }; - - //actually set - Box_Node* node = (Box_Node*)TOY_AS_OPAQUE(nodeLiteral); - Box_setTextNode(node, font, Toy_toCString(TOY_AS_STRING(textLiteral)), color); - - //cleanup - TTF_CloseFont(font); - - Toy_freeLiteral(fileLiteral); - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(fontLiteral); - Toy_freeLiteral(sizeLiteral); - Toy_freeLiteral(textLiteral); - Toy_freeLiteral(rLiteral); - Toy_freeLiteral(gLiteral); - Toy_freeLiteral(bLiteral); - Toy_freeLiteral(aLiteral); - - return 0; -} - -static int nativeCallNodeFn(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //checks - if (arguments->count < 2) { - interpreter->errorOutput("Too few arguments passed to callNodeFn\n"); - return -1; - } - - Toy_LiteralArray extraArgsBackwards; - Toy_initLiteralArray(&extraArgsBackwards); - - //extract the extra arg values - while (arguments->count > 2) { - Toy_Literal tmp = Toy_popLiteralArray(arguments); - - Toy_Literal idn = tmp; //there's almost certainly a better way of doing all of this stuff - if (TOY_IS_IDENTIFIER(tmp) && Toy_parseIdentifierToValue(interpreter, &tmp)) { - Toy_freeLiteral(idn); - } - - Toy_pushLiteralArray(&extraArgsBackwards, tmp); - Toy_freeLiteral(tmp); - } - - //reverse the extra args - Toy_LiteralArray extraArgs; - Toy_initLiteralArray(&extraArgs); - - while (extraArgsBackwards.count > 0) { - Toy_Literal tmp = Toy_popLiteralArray(&extraArgsBackwards); - Toy_pushLiteralArray(&extraArgs, tmp); - Toy_freeLiteral(tmp); - } - - Toy_freeLiteralArray(&extraArgsBackwards); - - //back on track - Toy_Literal fnName = Toy_popLiteralArray(arguments); - Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal nodeIdn = nodeLiteral; - if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { - Toy_freeLiteral(nodeIdn); - } - - Toy_Literal fnNameIdn = fnName; - if (TOY_IS_IDENTIFIER(fnName) && Toy_parseIdentifierToValue(interpreter, &fnName)) { - Toy_freeLiteral(fnNameIdn); - } - - if (!TOY_IS_OPAQUE(nodeLiteral) || !TOY_IS_STRING(fnName)) { - interpreter->errorOutput("Incorrect argument type passed to callNodeFn\n"); - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(fnName); - return -1; - } - - //allow refstring to do it's magic - Toy_Literal fnNameIdentifier = TOY_TO_IDENTIFIER_LITERAL(Toy_copyRefString(TOY_AS_STRING(fnName))); - - //call the function - Toy_Literal result = Box_callNodeLiteral(TOY_AS_OPAQUE(nodeLiteral), interpreter, fnNameIdentifier, &extraArgs); - - Toy_pushLiteralArray(&interpreter->stack, result); - - //cleanup - Toy_freeLiteralArray(&extraArgs); - Toy_freeLiteral(fnNameIdentifier); - Toy_freeLiteral(nodeLiteral); - Toy_freeLiteral(fnName); - Toy_freeLiteral(result); - - return 1; -} - -//call the hook -typedef struct Natives { - char* name; - Toy_NativeFn fn; -} Natives; - -int Box_hookNode(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) { - //build the natives list - Natives natives[] = { - {"loadNode", nativeLoadNode}, - {"initNode", nativeInitNode}, - {"pushNode", nativePushNode}, - {"getChildNode", nativeGetChildNode}, - {"freeChildNode", nativeFreeChildNode}, - {"sortChildrenNode", nativeSortChildrenNode}, - {"getParentNode", nativeGetParentNode}, - {"getChildNodeCount", nativeGetChildNodeCount}, - {"loadNodeTexture", nativeLoadNodeTexture}, - {"freeNodeTexture", nativeFreeNodeTexture}, - {"setNodeRect", nativeSetNodeRect}, - {"getNodeRectX", nativeGetNodeRectX}, - {"getNodeRectY", nativeGetNodeRectY}, - {"getNodeRectW", nativeGetNodeRectW}, - {"getNodeRectH", nativeGetNodeRectH}, - {"setNodeFrames", nativeSetNodeFrames}, - {"getNodeFrames", nativeGetNodeFrames}, - {"setCurrentNodeFrame", nativeSetCurrentNodeFrame}, - {"getCurrentNodeFrame", nativeGetCurrentNodeFrame}, - {"incrementCurrentNodeFrame", nativeIncrementCurrentNodeFrame}, - {"drawNode", nativeDrawNode}, - {"setNodeText", nativeSetNodeText}, - {"callNodeFn", nativeCallNodeFn}, - - //TODO: get rect, get node var, create empty node, set node color (tinting) - {NULL, NULL}, - }; - - //store the library in an aliased dictionary - if (!TOY_IS_NULL(alias)) { - //make sure the name isn't taken - if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) { - interpreter->errorOutput("Can't override an existing variable\n"); - Toy_freeLiteral(alias); - return false; - } - - //create the dictionary to load up with functions - Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1); - Toy_initLiteralDictionary(dictionary); - - //load the dict with functions - for (int i = 0; natives[i].name; i++) { - Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name)); - Toy_Literal func = TOY_TO_FUNCTION_NATIVE_LITERAL(natives[i].fn); - - Toy_setLiteralDictionary(dictionary, name, func); - - Toy_freeLiteral(name); - Toy_freeLiteral(func); - } - - //build the type - Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true); - Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true); - Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true); - TOY_TYPE_PUSH_SUBTYPE(&type, strType); - TOY_TYPE_PUSH_SUBTYPE(&type, fnType); - - //set scope - Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary); - Toy_declareScopeVariable(interpreter->scope, alias, type); - Toy_setScopeVariable(interpreter->scope, alias, dict, false); - - //cleanup - Toy_freeLiteral(dict); - Toy_freeLiteral(type); - return 0; - } - - //default - for (int i = 0; natives[i].name; i++) { - Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn); - } - - return 0; -} diff --git a/box/lib_node.h b/box/lib_node.h deleted file mode 100644 index febf912..0000000 --- a/box/lib_node.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "toy_interpreter.h" - -int Box_hookNode(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias); - diff --git a/box/lib_random.c b/box/lib_random.c deleted file mode 100644 index 6b70cc8..0000000 --- a/box/lib_random.c +++ /dev/null @@ -1,196 +0,0 @@ -#include "lib_random.h" - -#include "toy_memory.h" - -static int hashInt(int x) { - x = ((x >> 16) ^ x) * 0x45d9f3b; - x = ((x >> 16) ^ x) * 0x45d9f3b; - x = ((x >> 16) ^ x) * 0x45d9f3b; - x = (x >> 16) ^ x; - return x; -} - -typedef struct Toy_RandomGenerator { - int seed; //mutated with each call -} Toy_RandomGenerator; - -//Toy native functions -static int nativeCreateRandomGenerator(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //arguments - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to createRandomGenerator\n"); - return -1; - } - - //get the seed argument - Toy_Literal seedLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal seedLiteralIdn = seedLiteral; - if (TOY_IS_IDENTIFIER(seedLiteral) && Toy_parseIdentifierToValue(interpreter, &seedLiteral)) { - Toy_freeLiteral(seedLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(seedLiteral)) { - Toy_freeLiteral(seedLiteral); - return -1; - } - - if (!TOY_IS_INTEGER(seedLiteral)) { - interpreter->errorOutput("Incorrect literal type passed to createRandomGenerator"); - Toy_freeLiteral(seedLiteral); - return -1; - } - - //generate the generator object - Toy_RandomGenerator* generator = TOY_ALLOCATE(Toy_RandomGenerator, 1); - generator->seed = TOY_AS_INTEGER(seedLiteral); - Toy_Literal generatorLiteral = TOY_TO_OPAQUE_LITERAL(generator, TOY_OPAQUE_TAG_RANDOM); - - //return and cleanup - Toy_pushLiteralArray(&interpreter->stack, generatorLiteral); - - Toy_freeLiteral(seedLiteral); - Toy_freeLiteral(generatorLiteral); - - return 1; -} - -static int nativeGenerateRandomNumber(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to generateRandomNumber\n"); - return -1; - } - - //get the runner object - Toy_Literal generatorLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal generatorLiteralIdn = generatorLiteral; - if (TOY_IS_IDENTIFIER(generatorLiteral) && Toy_parseIdentifierToValue(interpreter, &generatorLiteral)) { - Toy_freeLiteral(generatorLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(generatorLiteral)) { - Toy_freeLiteral(generatorLiteral); - return -1; - } - - if (TOY_GET_OPAQUE_TAG(generatorLiteral) != TOY_OPAQUE_TAG_RANDOM) { - interpreter->errorOutput("Unrecognized opaque literal in generateRandomNumber\n"); - return -1; - } - - Toy_RandomGenerator* generator = TOY_AS_OPAQUE(generatorLiteral); - - //generate the new value and package up the return - generator->seed = hashInt(generator->seed); - - Toy_Literal resultLiteral = TOY_TO_INTEGER_LITERAL(generator->seed); - - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - - //cleanup - Toy_freeLiteral(generatorLiteral); - Toy_freeLiteral(resultLiteral); - - return 0; -} - -static int nativeFreeRandomGenerator(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to freeRandomGenerator\n"); - return -1; - } - - //get the runner object - Toy_Literal generatorLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal generatorLiteralIdn = generatorLiteral; - if (TOY_IS_IDENTIFIER(generatorLiteral) && Toy_parseIdentifierToValue(interpreter, &generatorLiteral)) { - Toy_freeLiteral(generatorLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(generatorLiteral)) { - Toy_freeLiteral(generatorLiteral); - return -1; - } - - if (TOY_GET_OPAQUE_TAG(generatorLiteral) != TOY_OPAQUE_TAG_RANDOM) { - interpreter->errorOutput("Unrecognized opaque literal in freeRandomGenerator\n"); - return -1; - } - - Toy_RandomGenerator* generator = TOY_AS_OPAQUE(generatorLiteral); - - //clear out the runner object - TOY_FREE(Toy_RandomGenerator, generator); - Toy_freeLiteral(generatorLiteral); - - return 0; -} - -//call the hook -typedef struct Natives { - const char* name; - Toy_NativeFn fn; -} Natives; - -int Toy_hookRandom(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) { - //build the natives list - Natives natives[] = { - {"createRandomGenerator", nativeCreateRandomGenerator}, - {"generateRandomNumber", nativeGenerateRandomNumber}, - {"freeRandomGenerator", nativeFreeRandomGenerator}, - {NULL, NULL} - }; - - //store the library in an aliased dictionary - if (!TOY_IS_NULL(alias)) { - //make sure the name isn't taken - if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) { - interpreter->errorOutput("Can't override an existing variable\n"); - Toy_freeLiteral(alias); - return -1; - } - - //create the dictionary to load up with functions - Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1); - Toy_initLiteralDictionary(dictionary); - - //load the dict with functions - for (int i = 0; natives[i].name; i++) { - Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name)); - Toy_Literal func = TOY_TO_FUNCTION_NATIVE_LITERAL(natives[i].fn); - - Toy_setLiteralDictionary(dictionary, name, func); - - Toy_freeLiteral(name); - Toy_freeLiteral(func); - } - - //build the type - Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true); - Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true); - Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true); - TOY_TYPE_PUSH_SUBTYPE(&type, strType); - TOY_TYPE_PUSH_SUBTYPE(&type, fnType); - - //set scope - Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary); - Toy_declareScopeVariable(interpreter->scope, alias, type); - Toy_setScopeVariable(interpreter->scope, alias, dict, false); - - //cleanup - Toy_freeLiteral(dict); - Toy_freeLiteral(type); - return 0; - } - - //default - for (int i = 0; natives[i].name; i++) { - Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn); - } - - return 0; -} diff --git a/box/lib_random.h b/box/lib_random.h deleted file mode 100644 index 2dfae4d..0000000 --- a/box/lib_random.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "toy_interpreter.h" - -int Toy_hookRandom(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias); - -#define TOY_OPAQUE_TAG_RANDOM 200 diff --git a/box/lib_runner.c b/box/lib_runner.c deleted file mode 100644 index 27f05e7..0000000 --- a/box/lib_runner.c +++ /dev/null @@ -1,553 +0,0 @@ -#include "lib_runner.h" - -#include "toy_memory.h" -#include "toy_drive_system.h" -#include "toy_interpreter.h" - -#include "repl_tools.h" - -#include - -typedef struct Toy_Runner { - Toy_Interpreter interpreter; - const unsigned char* bytecode; - size_t size; - - bool dirty; -} Toy_Runner; - -//Toy native functions -static int nativeLoadScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //arguments - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to loadScript\n"); - return -1; - } - - //get the file path literal with a handle - Toy_Literal drivePathLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal drivePathLiteralIdn = drivePathLiteral; - if (TOY_IS_IDENTIFIER(drivePathLiteral) && Toy_parseIdentifierToValue(interpreter, &drivePathLiteral)) { - Toy_freeLiteral(drivePathLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(drivePathLiteral)) { - Toy_freeLiteral(drivePathLiteral); - return -1; - } - - Toy_Literal filePathLiteral = Toy_getDrivePathLiteral(interpreter, &drivePathLiteral); - - if (TOY_IS_NULL(filePathLiteral)) { - Toy_freeLiteral(filePathLiteral); - Toy_freeLiteral(drivePathLiteral); - return -1; - } - - Toy_freeLiteral(drivePathLiteral); - - //use raw types - easier - const char* filePath = Toy_toCString(TOY_AS_STRING(filePathLiteral)); - size_t filePathLength = Toy_lengthRefString(TOY_AS_STRING(filePathLiteral)); - - //load and compile the bytecode - size_t fileSize = 0; - const char* source = (const char*)Toy_readFile(filePath, &fileSize); - - if (!source) { - interpreter->errorOutput("Failed to load source file\n"); - Toy_freeLiteral(filePathLiteral); - return -1; - } - - const unsigned char* bytecode = Toy_compileString(source, &fileSize); - free((void*)source); - - if (!bytecode) { - interpreter->errorOutput("Failed to compile source file\n"); - Toy_freeLiteral(filePathLiteral); - return -1; - } - - //build the runner object - Toy_Runner* runner = TOY_ALLOCATE(Toy_Runner, 1); - Toy_setInterpreterPrint(&runner->interpreter, interpreter->printOutput); - Toy_setInterpreterAssert(&runner->interpreter, interpreter->assertOutput); - Toy_setInterpreterError(&runner->interpreter, interpreter->errorOutput); - runner->interpreter.hooks = interpreter->hooks; - runner->interpreter.scope = NULL; - Toy_resetInterpreter(&runner->interpreter); - runner->bytecode = bytecode; - runner->size = fileSize; - runner->dirty = false; - - //build the opaque object, and push it to the stack - Toy_Literal runnerLiteral = TOY_TO_OPAQUE_LITERAL(runner, TOY_OPAQUE_TAG_RUNNER); - Toy_pushLiteralArray(&interpreter->stack, runnerLiteral); - - //free the drive path - Toy_freeLiteral(filePathLiteral); - - return 1; -} - -static int nativeLoadScriptBytecode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //arguments - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to loadScriptBytecode\n"); - return -1; - } - - //get the argument - Toy_Literal drivePathLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal drivePathLiteralIdn = drivePathLiteral; - if (TOY_IS_IDENTIFIER(drivePathLiteral) && Toy_parseIdentifierToValue(interpreter, &drivePathLiteral)) { - Toy_freeLiteral(drivePathLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(drivePathLiteral)) { - Toy_freeLiteral(drivePathLiteral); - return -1; - } - - Toy_Literal filePathLiteral = Toy_getDrivePathLiteral(interpreter, &drivePathLiteral); - - if (TOY_IS_NULL(filePathLiteral)) { - Toy_freeLiteral(filePathLiteral); - Toy_freeLiteral(drivePathLiteral); - return -1; - } - - Toy_freeLiteral(drivePathLiteral); - - //use raw types - easier - const char* filePath = Toy_toCString(TOY_AS_STRING(filePathLiteral)); - size_t filePathLength = Toy_lengthRefString(TOY_AS_STRING(filePathLiteral)); - - //load the bytecode - size_t fileSize = 0; - unsigned char* bytecode = (unsigned char*)Toy_readFile(filePath, &fileSize); - - if (!bytecode) { - interpreter->errorOutput("Failed to load bytecode file\n"); - return -1; - } - - //build the runner object - Toy_Runner* runner = TOY_ALLOCATE(Toy_Runner, 1); - Toy_setInterpreterPrint(&runner->interpreter, interpreter->printOutput); - Toy_setInterpreterAssert(&runner->interpreter, interpreter->assertOutput); - Toy_setInterpreterError(&runner->interpreter, interpreter->errorOutput); - runner->interpreter.hooks = interpreter->hooks; - runner->interpreter.scope = NULL; - Toy_resetInterpreter(&runner->interpreter); - runner->bytecode = bytecode; - runner->size = fileSize; - runner->dirty = false; - - //build the opaque object, and push it to the stack - Toy_Literal runnerLiteral = TOY_TO_OPAQUE_LITERAL(runner, TOY_OPAQUE_TAG_RUNNER); - Toy_pushLiteralArray(&interpreter->stack, runnerLiteral); - - //free the drive path - Toy_freeLiteral(filePathLiteral); - - return 1; -} - -static int nativeRunScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to runScript\n"); - return -1; - } - - //get the runner object - Toy_Literal runnerLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal runnerIdn = runnerLiteral; - if (TOY_IS_IDENTIFIER(runnerLiteral) && Toy_parseIdentifierToValue(interpreter, &runnerLiteral)) { - Toy_freeLiteral(runnerIdn); - } - - if (TOY_IS_IDENTIFIER(runnerLiteral)) { - Toy_freeLiteral(runnerLiteral); - return -1; - } - - if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) { - interpreter->errorOutput("Unrecognized opaque literal in runScript\n"); - return -1; - } - - Toy_Runner* runner = TOY_AS_OPAQUE(runnerLiteral); - - //run - if (runner->dirty) { - interpreter->errorOutput("Can't re-run a dirty script (try resetting it first)\n"); - Toy_freeLiteral(runnerLiteral); - return -1; - } - - unsigned char* bytecodeCopy = TOY_ALLOCATE(unsigned char, runner->size); - memcpy(bytecodeCopy, runner->bytecode, runner->size); //need a COPY of the bytecode, because the interpreter eats it - - Toy_runInterpreter(&runner->interpreter, bytecodeCopy, runner->size); - runner->dirty = true; - - //cleanup - Toy_freeLiteral(runnerLiteral); - - return 0; -} - -static int nativeGetScriptVar(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments to getScriptVar\n"); - return -1; - } - - //get the runner object - Toy_Literal varName = Toy_popLiteralArray(arguments); - Toy_Literal runnerLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal varNameIdn = varName; - if (TOY_IS_IDENTIFIER(varName) && Toy_parseIdentifierToValue(interpreter, &varName)) { - Toy_freeLiteral(varNameIdn); - } - - Toy_Literal runnerIdn = runnerLiteral; - if (TOY_IS_IDENTIFIER(runnerLiteral) && Toy_parseIdentifierToValue(interpreter, &runnerLiteral)) { - Toy_freeLiteral(runnerIdn); - } - - if (TOY_IS_IDENTIFIER(varName) || TOY_IS_IDENTIFIER(runnerLiteral)) { - Toy_freeLiteral(varName); - Toy_freeLiteral(runnerLiteral); - return -1; - } - - if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) { - interpreter->errorOutput("Unrecognized opaque literal in getScriptVar\n"); - return -1; - } - - Toy_Runner* runner = TOY_AS_OPAQUE(runnerLiteral); - - //dirty check - if (!runner->dirty) { - interpreter->errorOutput("Can't access variable from a non-dirty script (try running it first)\n"); - Toy_freeLiteral(runnerLiteral); - return -1; - } - - //get the desired variable - Toy_Literal varIdn = TOY_TO_IDENTIFIER_LITERAL(Toy_copyRefString(TOY_AS_STRING(varName))); - Toy_Literal result = TOY_TO_NULL_LITERAL; - Toy_getScopeVariable(runner->interpreter.scope, varIdn, &result); - - Toy_pushLiteralArray(&interpreter->stack, result); - - //cleanup - Toy_freeLiteral(result); - Toy_freeLiteral(varIdn); - Toy_freeLiteral(varName); - Toy_freeLiteral(runnerLiteral); - - return 1; -} - -static int nativeCallScriptFn(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count < 2) { - interpreter->errorOutput("Incorrect number of arguments to callScriptFn\n"); - return -1; - } - - //get the rest args - Toy_LiteralArray tmp; - Toy_initLiteralArray(&tmp); - - while (arguments->count > 2) { - Toy_Literal lit = Toy_popLiteralArray(arguments); - Toy_pushLiteralArray(&tmp, lit); - Toy_freeLiteral(lit); - } - - Toy_LiteralArray rest; - Toy_initLiteralArray(&rest); - - while (tmp.count > 0) { //correct the order of the rest args - Toy_Literal lit = Toy_popLiteralArray(&tmp); - Toy_pushLiteralArray(&rest, lit); - Toy_freeLiteral(lit); - } - - Toy_freeLiteralArray(&tmp); - - //get the runner object - Toy_Literal varName = Toy_popLiteralArray(arguments); - Toy_Literal runnerLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal varNameIdn = varName; - if (TOY_IS_IDENTIFIER(varName) && Toy_parseIdentifierToValue(interpreter, &varName)) { - Toy_freeLiteral(varNameIdn); - } - - Toy_Literal runnerIdn = runnerLiteral; - if (TOY_IS_IDENTIFIER(runnerLiteral) && Toy_parseIdentifierToValue(interpreter, &runnerLiteral)) { - Toy_freeLiteral(runnerIdn); - } - - if (TOY_IS_IDENTIFIER(varName) || TOY_IS_IDENTIFIER(runnerLiteral)) { - Toy_freeLiteral(varName); - Toy_freeLiteral(runnerLiteral); - return -1; - } - - if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) { - interpreter->errorOutput("Unrecognized opaque literal in callScriptFn\n"); - return -1; - } - - Toy_Runner* runner = TOY_AS_OPAQUE(runnerLiteral); - - //dirty check - if (!runner->dirty) { - interpreter->errorOutput("Can't access fn from a non-dirty script (try running it first)\n"); - Toy_freeLiteral(runnerLiteral); - Toy_freeLiteralArray(&rest); - return -1; - } - - //get the desired variable - Toy_Literal varIdn = TOY_TO_IDENTIFIER_LITERAL(Toy_copyRefString(TOY_AS_STRING(varName))); - Toy_Literal fn = TOY_TO_NULL_LITERAL; - Toy_getScopeVariable(runner->interpreter.scope, varIdn, &fn); - - if (!TOY_IS_FUNCTION(fn)) { - interpreter->errorOutput("Can't run a non-function literal\n"); - Toy_freeLiteral(fn); - Toy_freeLiteral(varIdn); - Toy_freeLiteral(varName); - Toy_freeLiteral(runnerLiteral); - Toy_freeLiteralArray(&rest); - } - - //call - Toy_LiteralArray resultArray; - Toy_initLiteralArray(&resultArray); - - Toy_callLiteralFn(interpreter, fn, &rest, &resultArray); - - Toy_Literal result = TOY_TO_NULL_LITERAL; - if (resultArray.count > 0) { - result = Toy_popLiteralArray(&resultArray); - } - - Toy_pushLiteralArray(&interpreter->stack, result); - - //cleanup - Toy_freeLiteralArray(&resultArray); - Toy_freeLiteral(result); - Toy_freeLiteral(fn); - Toy_freeLiteral(varIdn); - Toy_freeLiteral(varName); - Toy_freeLiteral(runnerLiteral); - Toy_freeLiteralArray(&rest); - - return 1; -} - -static int nativeResetScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to resetScript\n"); - return -1; - } - - //get the runner object - Toy_Literal runnerLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal runnerIdn = runnerLiteral; - if (TOY_IS_IDENTIFIER(runnerLiteral) && Toy_parseIdentifierToValue(interpreter, &runnerLiteral)) { - Toy_freeLiteral(runnerIdn); - } - - if (TOY_IS_IDENTIFIER(runnerLiteral)) { - Toy_freeLiteral(runnerLiteral); - return -1; - } - - if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) { - interpreter->errorOutput("Unrecognized opaque literal in resetScript\n"); - return -1; - } - - Toy_Runner* runner = TOY_AS_OPAQUE(runnerLiteral); - - //reset - if (!runner->dirty) { - interpreter->errorOutput("Can't reset a non-dirty script (try running it first)\n"); - Toy_freeLiteral(runnerLiteral); - return -1; - } - - Toy_resetInterpreter(&runner->interpreter); - runner->dirty = false; - Toy_freeLiteral(runnerLiteral); - - return 0; -} - -static int nativeFreeScript(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to freeScript\n"); - return -1; - } - - //get the runner object - Toy_Literal runnerLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal runnerIdn = runnerLiteral; - if (TOY_IS_IDENTIFIER(runnerLiteral) && Toy_parseIdentifierToValue(interpreter, &runnerLiteral)) { - Toy_freeLiteral(runnerIdn); - } - - if (TOY_IS_IDENTIFIER(runnerLiteral)) { - Toy_freeLiteral(runnerLiteral); - return -1; - } - - if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) { - interpreter->errorOutput("Unrecognized opaque literal in freeScript\n"); - return -1; - } - - Toy_Runner* runner = TOY_AS_OPAQUE(runnerLiteral); - - //clear out the runner object - runner->interpreter.hooks = NULL; - Toy_freeInterpreter(&runner->interpreter); - TOY_FREE_ARRAY(unsigned char, runner->bytecode, runner->size); - - TOY_FREE(Toy_Runner, runner); - - Toy_freeLiteral(runnerLiteral); - - return 0; -} - -static int nativeCheckScriptDirty(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to checkScriptDirty\n"); - return -1; - } - - //get the runner object - Toy_Literal runnerLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal runnerIdn = runnerLiteral; - if (TOY_IS_IDENTIFIER(runnerLiteral) && Toy_parseIdentifierToValue(interpreter, &runnerLiteral)) { - Toy_freeLiteral(runnerIdn); - } - - if (TOY_IS_IDENTIFIER(runnerLiteral)) { - Toy_freeLiteral(runnerLiteral); - return -1; - } - - if (TOY_GET_OPAQUE_TAG(runnerLiteral) != TOY_OPAQUE_TAG_RUNNER) { - interpreter->errorOutput("Unrecognized opaque literal in checkScriptDirty\n"); - return -1; - } - - Toy_Runner* runner = TOY_AS_OPAQUE(runnerLiteral); - - //run - Toy_Literal result = TOY_TO_BOOLEAN_LITERAL(runner->dirty); - - Toy_pushLiteralArray(&interpreter->stack, result); - - //cleanup - Toy_freeLiteral(result); - Toy_freeLiteral(runnerLiteral); - - return 0; -} - -//call the hook -typedef struct Natives { - const char* name; - Toy_NativeFn fn; -} Natives; - -int Toy_hookRunner(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) { - //build the natives list - Natives natives[] = { - {"loadScript", nativeLoadScript}, - {"loadScriptBytecode", nativeLoadScriptBytecode}, - {"runScript", nativeRunScript}, - {"getScriptVar", nativeGetScriptVar}, - {"callScriptFn", nativeCallScriptFn}, - {"resetScript", nativeResetScript}, - {"freeScript", nativeFreeScript}, - {"checkScriptDirty", nativeCheckScriptDirty}, - {NULL, NULL} - }; - - //store the library in an aliased dictionary - if (!TOY_IS_NULL(alias)) { - //make sure the name isn't taken - if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) { - interpreter->errorOutput("Can't override an existing variable\n"); - Toy_freeLiteral(alias); - return -1; - } - - //create the dictionary to load up with functions - Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1); - Toy_initLiteralDictionary(dictionary); - - //load the dict with functions - for (int i = 0; natives[i].name; i++) { - Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name)); - Toy_Literal func = TOY_TO_FUNCTION_NATIVE_LITERAL(natives[i].fn); - - Toy_setLiteralDictionary(dictionary, name, func); - - Toy_freeLiteral(name); - Toy_freeLiteral(func); - } - - //build the type - Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true); - Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true); - Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true); - TOY_TYPE_PUSH_SUBTYPE(&type, strType); - TOY_TYPE_PUSH_SUBTYPE(&type, fnType); - - //set scope - Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary); - Toy_declareScopeVariable(interpreter->scope, alias, type); - Toy_setScopeVariable(interpreter->scope, alias, dict, false); - - //cleanup - Toy_freeLiteral(dict); - Toy_freeLiteral(type); - return 0; - } - - //default - for (int i = 0; natives[i].name; i++) { - Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn); - } - - return 0; -} - diff --git a/box/lib_runner.h b/box/lib_runner.h deleted file mode 100644 index 549c2ac..0000000 --- a/box/lib_runner.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "toy_interpreter.h" - -int Toy_hookRunner(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias); - -#define TOY_OPAQUE_TAG_RUNNER 100 - diff --git a/box/lib_standard.c b/box/lib_standard.c deleted file mode 100644 index 2a348b1..0000000 --- a/box/lib_standard.c +++ /dev/null @@ -1,2117 +0,0 @@ -#include "lib_standard.h" - -#include "toy_memory.h" - -#include -#include -#include -#include - -static int nativeClock(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 0) { - interpreter->errorOutput("Incorrect number of arguments to clock\n"); - return -1; - } - - //get the time from C (what a pain) - time_t rawtime = time(NULL); - struct tm* timeinfo = localtime( &rawtime ); - char* timestr = asctime(timeinfo); - - //push to the stack - size_t len = strlen(timestr) - 1; //-1 for the newline - Toy_Literal timeLiteral = TOY_TO_STRING_LITERAL(Toy_createRefStringLength(timestr, len)); - - //push to the stack - Toy_pushLiteralArray(&interpreter->stack, timeLiteral); - - //cleanup - Toy_freeLiteral(timeLiteral); - - return 1; -} - -static int nativeHash(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to hash\n"); - return -1; - } - - //get the self - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral)) { - Toy_freeLiteral(selfLiteral); - return -1; - } - - Toy_Literal result = TOY_TO_INTEGER_LITERAL(Toy_hashLiteral(selfLiteral)); - - Toy_pushLiteralArray(&interpreter->stack, result); - - Toy_freeLiteral(result); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeAbs(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to abs\n"); - return -1; - } - - //get the self - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral)) { - Toy_freeLiteral(selfLiteral); - return -1; - } - - if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) { - interpreter->errorOutput("Incorrect argument type passed to abs\n"); - Toy_freeLiteral(selfLiteral); - return -1; - } - - Toy_Literal result; - - if (TOY_IS_INTEGER(selfLiteral)) { - result = TOY_TO_INTEGER_LITERAL( TOY_AS_INTEGER(selfLiteral) > 0 ? TOY_AS_INTEGER(selfLiteral) : -TOY_AS_INTEGER(selfLiteral) ); - } - if (TOY_IS_FLOAT(selfLiteral)) { - result = TOY_TO_FLOAT_LITERAL( TOY_AS_FLOAT(selfLiteral) > 0 ? TOY_AS_FLOAT(selfLiteral) : -TOY_AS_FLOAT(selfLiteral) ); - } - - Toy_pushLiteralArray(&interpreter->stack, result); - - Toy_freeLiteral(result); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeCeil(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to ceil\n"); - return -1; - } - - //get the self - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral)) { - Toy_freeLiteral(selfLiteral); - return -1; - } - - if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) { - interpreter->errorOutput("Incorrect argument type passed to ceil\n"); - Toy_freeLiteral(selfLiteral); - return -1; - } - - Toy_Literal result; - - if (TOY_IS_INTEGER(selfLiteral)) { - //NO-OP - result = Toy_copyLiteral(selfLiteral); - } - if (TOY_IS_FLOAT(selfLiteral)) { - result = TOY_TO_INTEGER_LITERAL( (int)TOY_AS_FLOAT(selfLiteral) - TOY_AS_FLOAT(selfLiteral) == 0 ? (int)TOY_AS_FLOAT(selfLiteral) : (int)TOY_AS_FLOAT(selfLiteral) + 1 ); - } - - Toy_pushLiteralArray(&interpreter->stack, result); - - Toy_freeLiteral(result); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeFloor(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to floor\n"); - return -1; - } - - //get the self - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral)) { - Toy_freeLiteral(selfLiteral); - return -1; - } - - if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) { - interpreter->errorOutput("Incorrect argument type passed to floor\n"); - Toy_freeLiteral(selfLiteral); - return -1; - } - - Toy_Literal result; - - if (TOY_IS_INTEGER(selfLiteral)) { - //NO-OP - result = Toy_copyLiteral(selfLiteral); - } - if (TOY_IS_FLOAT(selfLiteral)) { - result = TOY_TO_INTEGER_LITERAL( (int)TOY_AS_FLOAT(selfLiteral) ); - } - - Toy_pushLiteralArray(&interpreter->stack, result); - - Toy_freeLiteral(result); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeMax(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //return value - Toy_Literal resultLiteral = TOY_TO_NULL_LITERAL; - - //iterate over all arguments - do { - //get the self - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral)) { - Toy_freeLiteral(selfLiteral); - return -1; - } - - if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) { - interpreter->errorOutput("Incorrect argument type passed to max\n"); - Toy_freeLiteral(selfLiteral); - return -1; - } - - //if not comparing yet... - if (TOY_IS_NULL(resultLiteral)) { - resultLiteral = selfLiteral; - continue; - } - - //cooerce if needed - if (TOY_IS_INTEGER(resultLiteral) && TOY_IS_FLOAT(selfLiteral)) { - resultLiteral = TOY_TO_FLOAT_LITERAL( TOY_AS_INTEGER(resultLiteral) ); - } - - if (TOY_IS_FLOAT(resultLiteral) && TOY_IS_INTEGER(selfLiteral)) { - selfLiteral = TOY_TO_FLOAT_LITERAL( TOY_AS_INTEGER(selfLiteral) ); - } - - //compare - if (TOY_IS_INTEGER(resultLiteral) && TOY_AS_INTEGER(resultLiteral) < TOY_AS_INTEGER(selfLiteral)) { - //NOTE: just ints, don't free - resultLiteral = selfLiteral; - } - - else if (TOY_IS_FLOAT(resultLiteral) && TOY_AS_FLOAT(resultLiteral) < TOY_AS_FLOAT(selfLiteral)) { - //NOTE: just floats, don't free - resultLiteral = selfLiteral; - } - } - while (arguments->count > 0); - - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - - Toy_freeLiteral(resultLiteral); - - return 1; -} - -static int nativeMin(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //return value - Toy_Literal resultLiteral = TOY_TO_NULL_LITERAL; - - //iterate over all arguments - do { - //get the self - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral)) { - Toy_freeLiteral(selfLiteral); - return -1; - } - - if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) { - interpreter->errorOutput("Incorrect argument type passed to min\n"); - Toy_freeLiteral(selfLiteral); - return -1; - } - - //if not comparing yet... - if (TOY_IS_NULL(resultLiteral)) { - resultLiteral = selfLiteral; - continue; - } - - //cooerce if needed - if (TOY_IS_INTEGER(resultLiteral) && TOY_IS_FLOAT(selfLiteral)) { - resultLiteral = TOY_TO_FLOAT_LITERAL( TOY_AS_INTEGER(resultLiteral) ); - } - - if (TOY_IS_FLOAT(resultLiteral) && TOY_IS_INTEGER(selfLiteral)) { - selfLiteral = TOY_TO_FLOAT_LITERAL( TOY_AS_INTEGER(selfLiteral) ); - } - - //compare - if (TOY_IS_INTEGER(resultLiteral) && TOY_AS_INTEGER(resultLiteral) > TOY_AS_INTEGER(selfLiteral)) { - //NOTE: just ints, don't free - resultLiteral = selfLiteral; - } - - else if (TOY_IS_FLOAT(resultLiteral) && TOY_AS_FLOAT(resultLiteral) > TOY_AS_FLOAT(selfLiteral)) { - //NOTE: just floats, don't free - resultLiteral = selfLiteral; - } - } - while (arguments->count > 0); - - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - - Toy_freeLiteral(resultLiteral); - - return 1; -} - -static int nativeRound(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to round\n"); - return -1; - } - - //get the self - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral)) { - Toy_freeLiteral(selfLiteral); - return -1; - } - - if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) { - interpreter->errorOutput("Incorrect argument type passed to round\n"); - Toy_freeLiteral(selfLiteral); - return -1; - } - - Toy_Literal result; - - if (TOY_IS_INTEGER(selfLiteral)) { - //NO-OP - result = Toy_copyLiteral(selfLiteral); - } - if (TOY_IS_FLOAT(selfLiteral)) { - //catch the already-rounded case - if (TOY_AS_FLOAT(selfLiteral) == (int)TOY_AS_FLOAT(selfLiteral)) { - result = TOY_TO_INTEGER_LITERAL((int)TOY_AS_FLOAT(selfLiteral)); - } - else { - result = TOY_TO_INTEGER_LITERAL( TOY_AS_FLOAT(selfLiteral) - (int)TOY_AS_FLOAT(selfLiteral) < 0.5 ? (int)TOY_AS_FLOAT(selfLiteral) : (int)TOY_AS_FLOAT(selfLiteral) + 1 ); - } - } - - Toy_pushLiteralArray(&interpreter->stack, result); - - Toy_freeLiteral(result); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments to concat\n"); - return -1; - } - - //get the args - Toy_Literal otherLiteral = Toy_popLiteralArray(arguments); - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - Toy_Literal otherLiteralIdn = otherLiteral; - if (TOY_IS_IDENTIFIER(otherLiteral) && Toy_parseIdentifierToValue(interpreter, &otherLiteral)) { - Toy_freeLiteral(otherLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(otherLiteral)) { - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(otherLiteral); - return -1; - } - - //for each self type - if (TOY_IS_ARRAY(selfLiteral)) { - if (!TOY_IS_ARRAY(otherLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to concat (unknown type for other)\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(otherLiteral); - return -1; - } - - //append each element of other to self, one-by-one - for (int i = 0; i < TOY_AS_ARRAY(otherLiteral)->count; i++) { - Toy_pushLiteralArray(TOY_AS_ARRAY(selfLiteral), TOY_AS_ARRAY(otherLiteral)->literals[i]); - } - - //return and clean up - Toy_pushLiteralArray(&interpreter->stack, selfLiteral); - - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(otherLiteral); - - return 1; - } - - if (TOY_IS_DICTIONARY(selfLiteral)) { - if (!TOY_IS_DICTIONARY(otherLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to concat (unknown type for other)\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(otherLiteral); - return -1; - } - - //append each element of self to other, which will overwrite existing entries - for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) { - if (!TOY_IS_NULL(TOY_AS_DICTIONARY(selfLiteral)->entries[i].key)) { - Toy_setLiteralDictionary(TOY_AS_DICTIONARY(otherLiteral), TOY_AS_DICTIONARY(selfLiteral)->entries[i].key, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value); - } - } - - //return and clean up - Toy_pushLiteralArray(&interpreter->stack, otherLiteral); - - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(otherLiteral); - - return 1; - } - - if (TOY_IS_STRING(selfLiteral)) { //a little redundant - if (!TOY_IS_STRING(otherLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to concat (unknown type for other)\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(otherLiteral); - return -1; - } - - //get the combined length for the new string - size_t length = TOY_AS_STRING(selfLiteral)->length + TOY_AS_STRING(otherLiteral)->length + 1; - - if (length > TOY_MAX_STRING_LENGTH) { - interpreter->errorOutput("Can't concatenate these strings, result is too long (error found in concat)\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(otherLiteral); - return -1; - } - - //allocate the space and generate - char* buffer = TOY_ALLOCATE(char, length); - snprintf(buffer, length, "%s%s", Toy_toCString(TOY_AS_STRING(selfLiteral)), Toy_toCString(TOY_AS_STRING(otherLiteral))); - - Toy_Literal result = TOY_TO_STRING_LITERAL(Toy_createRefString(buffer)); - - //push and clean up - Toy_pushLiteralArray(&interpreter->stack, result); - - TOY_FREE_ARRAY(char, buffer, length); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(otherLiteral); - Toy_freeLiteral(result); - - return 1; - } - - interpreter->errorOutput("Incorrect argument type passed to concat (unknown type for self)\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(otherLiteral); - return -1; -} - -static int nativeContainsKey(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments to containsKey\n"); - return -1; - } - - //get the args - Toy_Literal keyLiteral = Toy_popLiteralArray(arguments); - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - Toy_Literal keyLiteralIdn = keyLiteral; - if (TOY_IS_IDENTIFIER(keyLiteral) && Toy_parseIdentifierToValue(interpreter, &keyLiteral)) { - Toy_freeLiteral(keyLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(keyLiteral)) { - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(keyLiteral); - return -1; - } - - //check type - if (!(/* TOY_IS_ARRAY(selfLiteral) || */ TOY_IS_DICTIONARY(selfLiteral) )) { - interpreter->errorOutput("Incorrect argument type passed to containsKey\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(keyLiteral); - return -1; - } - - Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(false); - if (TOY_IS_DICTIONARY(selfLiteral) && Toy_existsLiteralDictionary( TOY_AS_DICTIONARY(selfLiteral), keyLiteral )) { - //return true of it contains the key - Toy_freeLiteral(resultLiteral); - resultLiteral = TOY_TO_BOOLEAN_LITERAL(true); - } - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - Toy_freeLiteral(resultLiteral); - - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(keyLiteral); - - return 1; -} - -static int nativeContainsValue(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments to containsValue\n"); - return -1; - } - - //get the args - Toy_Literal valueLiteral = Toy_popLiteralArray(arguments); - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - Toy_Literal valueLiteralIdn = valueLiteral; - if (TOY_IS_IDENTIFIER(valueLiteral) && Toy_parseIdentifierToValue(interpreter, &valueLiteral)) { - Toy_freeLiteral(valueLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(valueLiteral)) { - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(valueLiteral); - return -1; - } - - //check type - if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) )) { - interpreter->errorOutput("Incorrect argument type passed to containsValue\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(valueLiteral); - return -1; - } - - Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(false); - if (TOY_IS_DICTIONARY(selfLiteral)) { - for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) { - if (!TOY_IS_NULL(TOY_AS_DICTIONARY(selfLiteral)->entries[i].key) && Toy_literalsAreEqual( TOY_AS_DICTIONARY(selfLiteral)->entries[i].value, valueLiteral )) { - //return true of it contains the value - Toy_freeLiteral(resultLiteral); - resultLiteral = TOY_TO_BOOLEAN_LITERAL(true); - break; - } - } - } - else if (TOY_IS_ARRAY(selfLiteral)) { - for (int i = 0; i < TOY_AS_ARRAY(selfLiteral)->count; i++) { - Toy_Literal indexLiteral = TOY_TO_INTEGER_LITERAL(i); - Toy_Literal elementLiteral = Toy_getLiteralArray(TOY_AS_ARRAY(selfLiteral), indexLiteral); - - - if (Toy_literalsAreEqual(elementLiteral, valueLiteral)) { - Toy_freeLiteral(indexLiteral); - Toy_freeLiteral(elementLiteral); - - //return true of it contains the value - Toy_freeLiteral(resultLiteral); - resultLiteral = TOY_TO_BOOLEAN_LITERAL(true); - break; - } - - Toy_freeLiteral(indexLiteral); - Toy_freeLiteral(elementLiteral); - } - } - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - Toy_freeLiteral(resultLiteral); - - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(valueLiteral); - - return 1; -} - -static int nativeEvery(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments to every\n"); - return -1; - } - - //get the args - Toy_Literal fnLiteral = Toy_popLiteralArray(arguments); - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - Toy_Literal fnLiteralIdn = fnLiteral; - if (TOY_IS_IDENTIFIER(fnLiteral) && Toy_parseIdentifierToValue(interpreter, &fnLiteral)) { - Toy_freeLiteral(fnLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) { - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(fnLiteral); - return -1; - } - - //check type - if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) { - interpreter->errorOutput("Incorrect argument type passed to every\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(fnLiteral); - return -1; - } - - //call the given function on each element, based on the compound type - if (TOY_IS_ARRAY(selfLiteral)) { - bool result = true; - - // - for (int i = 0; i < TOY_AS_ARRAY(selfLiteral)->count; i++) { - Toy_Literal indexLiteral = TOY_TO_INTEGER_LITERAL(i); - - Toy_LiteralArray arguments; - Toy_initLiteralArray(&arguments); - Toy_pushLiteralArray(&arguments, indexLiteral); - Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]); - - Toy_LiteralArray returns; - Toy_initLiteralArray(&returns); - - Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns); - - //grab the results - Toy_Literal lit = Toy_popLiteralArray(&returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - Toy_freeLiteral(indexLiteral); - - //if not truthy - if (!TOY_IS_TRUTHY(lit)) { - Toy_freeLiteral(lit); - result = false; - break; - } - - Toy_freeLiteral(lit); - } - - Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(result); - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - Toy_freeLiteral(resultLiteral); - } - - if (TOY_IS_DICTIONARY(selfLiteral)) { - bool result = true; - - for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) { - //skip nulls - if (TOY_IS_NULL(TOY_AS_DICTIONARY(selfLiteral)->entries[i].key)) { - continue; - } - - Toy_LiteralArray arguments; - Toy_initLiteralArray(&arguments); - Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key); - Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value); - - Toy_LiteralArray returns; - Toy_initLiteralArray(&returns); - - Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns); - - //grab the results - Toy_Literal lit = Toy_popLiteralArray(&returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - - //if not truthy - if (!TOY_IS_TRUTHY(lit)) { - Toy_freeLiteral(lit); - result = false; - break; - } - - Toy_freeLiteral(lit); - } - - Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(result); - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - Toy_freeLiteral(resultLiteral); - } - - Toy_freeLiteral(fnLiteral); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeFilter(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments to filter\n"); - return -1; - } - - //get the args - Toy_Literal fnLiteral = Toy_popLiteralArray(arguments); - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - Toy_Literal fnLiteralIdn = fnLiteral; - if (TOY_IS_IDENTIFIER(fnLiteral) && Toy_parseIdentifierToValue(interpreter, &fnLiteral)) { - Toy_freeLiteral(fnLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) { - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(fnLiteral); - return -1; - } - - //check type - if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) { - interpreter->errorOutput("Incorrect argument type passed to filter\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(fnLiteral); - return -1; - } - - //call the given function on each element, based on the compound type - if (TOY_IS_ARRAY(selfLiteral)) { - Toy_LiteralArray* result = TOY_ALLOCATE(Toy_LiteralArray, 1); - Toy_initLiteralArray(result); - - // - for (int i = 0; i < TOY_AS_ARRAY(selfLiteral)->count; i++) { - Toy_Literal indexLiteral = TOY_TO_INTEGER_LITERAL(i); - - Toy_LiteralArray arguments; - Toy_initLiteralArray(&arguments); - Toy_pushLiteralArray(&arguments, indexLiteral); - Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]); - - Toy_LiteralArray returns; - Toy_initLiteralArray(&returns); - - Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns); - - //grab the results - Toy_Literal lit = Toy_popLiteralArray(&returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - Toy_freeLiteral(indexLiteral); - - //if truthy - if (TOY_IS_TRUTHY(lit)) { - Toy_pushLiteralArray(result, TOY_AS_ARRAY(selfLiteral)->literals[i]); - } - - Toy_freeLiteral(lit); - } - - Toy_Literal resultLiteral = TOY_TO_ARRAY_LITERAL(result); - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - Toy_freeLiteral(resultLiteral); - } - - if (TOY_IS_DICTIONARY(selfLiteral)) { - Toy_LiteralDictionary* result = TOY_ALLOCATE(Toy_LiteralDictionary, 1); - Toy_initLiteralDictionary(result); - - for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) { - //skip nulls - if (TOY_IS_NULL(TOY_AS_DICTIONARY(selfLiteral)->entries[i].key)) { - continue; - } - - Toy_LiteralArray arguments; - Toy_initLiteralArray(&arguments); - Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key); - Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value); - - Toy_LiteralArray returns; - Toy_initLiteralArray(&returns); - - Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns); - - //grab the results - Toy_Literal lit = Toy_popLiteralArray(&returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - - //if truthy - if (TOY_IS_TRUTHY(lit)) { - Toy_setLiteralDictionary(result, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value); - } - - Toy_freeLiteral(lit); - } - - Toy_Literal resultLiteral = TOY_TO_DICTIONARY_LITERAL(result); - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - Toy_freeLiteral(resultLiteral); - } - - Toy_freeLiteral(fnLiteral); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeForEach(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments to forEach\n"); - return -1; - } - - //get the args - Toy_Literal fnLiteral = Toy_popLiteralArray(arguments); - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - Toy_Literal fnLiteralIdn = fnLiteral; - if (TOY_IS_IDENTIFIER(fnLiteral) && Toy_parseIdentifierToValue(interpreter, &fnLiteral)) { - Toy_freeLiteral(fnLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) { - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(fnLiteral); - return -1; - } - - //check type - if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) { - interpreter->errorOutput("Incorrect argument type passed to forEach\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(fnLiteral); - return -1; - } - - //call the given function on each element, based on the compound type - if (TOY_IS_ARRAY(selfLiteral)) { - for (int i = 0; i < TOY_AS_ARRAY(selfLiteral)->count; i++) { - Toy_Literal indexLiteral = TOY_TO_INTEGER_LITERAL(i); - - Toy_LiteralArray arguments; - Toy_initLiteralArray(&arguments); - Toy_pushLiteralArray(&arguments, indexLiteral); - Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]); - - Toy_LiteralArray returns; - Toy_initLiteralArray(&returns); - - Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - Toy_freeLiteral(indexLiteral); - } - } - - if (TOY_IS_DICTIONARY(selfLiteral)) { - for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) { - //skip nulls - if (TOY_IS_NULL(TOY_AS_DICTIONARY(selfLiteral)->entries[i].key)) { - continue; - } - - Toy_LiteralArray arguments; - Toy_initLiteralArray(&arguments); - Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key); - Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value); - - Toy_LiteralArray returns; - Toy_initLiteralArray(&returns); - - Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - } - } - - Toy_freeLiteral(fnLiteral); - Toy_freeLiteral(selfLiteral); - - return 0; -} - -static int nativeGetKeys(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to getKeys\n"); - return -1; - } - - //get the self - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral)) { - Toy_freeLiteral(selfLiteral); - return -1; - } - - //check type - if (!TOY_IS_DICTIONARY(selfLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to getKeys\n"); - Toy_freeLiteral(selfLiteral); - return -1; - } - - //generate the result literal - Toy_LiteralArray* resultPtr = TOY_ALLOCATE(Toy_LiteralArray, 1); - Toy_initLiteralArray(resultPtr); - - //get each key from the dictionary, pass it to the array - for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) { - if (!TOY_IS_NULL( TOY_AS_DICTIONARY(selfLiteral)->entries[i].key )) { - Toy_pushLiteralArray(resultPtr, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key); - } - } - - //return the result - Toy_Literal result = TOY_TO_ARRAY_LITERAL(resultPtr); //no copy - Toy_pushLiteralArray(&interpreter->stack, result); //internal copy - - //clean up - Toy_freeLiteralArray(resultPtr); - TOY_FREE(Toy_LiteralArray, resultPtr); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeGetValues(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to getValues\n"); - return -1; - } - - //get the self - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral)) { - Toy_freeLiteral(selfLiteral); - return -1; - } - - //check type - if (!TOY_IS_DICTIONARY(selfLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to getValues\n"); - Toy_freeLiteral(selfLiteral); - return -1; - } - - //generate the result literal - Toy_LiteralArray* resultPtr = TOY_ALLOCATE(Toy_LiteralArray, 1); - Toy_initLiteralArray(resultPtr); - - //get each key from the dictionary, pass it to the array - for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) { - if (!TOY_IS_NULL( TOY_AS_DICTIONARY(selfLiteral)->entries[i].key )) { - Toy_pushLiteralArray(resultPtr, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value); - } - } - - //return the result - Toy_Literal result = TOY_TO_ARRAY_LITERAL(resultPtr); //no copy - Toy_pushLiteralArray(&interpreter->stack, result); //internal copy - - //clean up - Toy_freeLiteralArray(resultPtr); - TOY_FREE(Toy_LiteralArray, resultPtr); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeIndexOf(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments to indexOf\n"); - return -1; - } - - //get the args - Toy_Literal valueLiteral = Toy_popLiteralArray(arguments); - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - Toy_Literal valueLiteralIdn = valueLiteral; - if (TOY_IS_IDENTIFIER(valueLiteral) && Toy_parseIdentifierToValue(interpreter, &valueLiteral)) { - Toy_freeLiteral(valueLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(valueLiteral)) { - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(valueLiteral); - return -1; - } - - //check type - if (!TOY_IS_ARRAY(selfLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to indexOf\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(valueLiteral); - return -1; - } - - //search the array for the matching literal - Toy_Literal resultLiteral = TOY_TO_NULL_LITERAL; - for (int i = 0; i < TOY_AS_ARRAY(selfLiteral)->count; i++) { - if (Toy_literalsAreEqual(valueLiteral, TOY_AS_ARRAY(selfLiteral)->literals[i])) { - resultLiteral = TOY_TO_INTEGER_LITERAL(i); - break; - } - } - - //return the result and clean up - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - Toy_freeLiteral(resultLiteral); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeMap(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments to map\n"); - return -1; - } - - //get the args - Toy_Literal fnLiteral = Toy_popLiteralArray(arguments); - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - Toy_Literal fnLiteralIdn = fnLiteral; - if (TOY_IS_IDENTIFIER(fnLiteral) && Toy_parseIdentifierToValue(interpreter, &fnLiteral)) { - Toy_freeLiteral(fnLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) { - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(fnLiteral); - return -1; - } - - //check type - if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) { - interpreter->errorOutput("Incorrect argument type passed to map\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(fnLiteral); - return -1; - } - - //call the given function on each element, based on the compound type - if (TOY_IS_ARRAY(selfLiteral)) { - Toy_LiteralArray* returnsPtr = TOY_ALLOCATE(Toy_LiteralArray, 1); - Toy_initLiteralArray(returnsPtr); - - for (int i = 0; i < TOY_AS_ARRAY(selfLiteral)->count; i++) { - Toy_Literal indexLiteral = TOY_TO_INTEGER_LITERAL(i); - - Toy_LiteralArray arguments; - Toy_initLiteralArray(&arguments); - Toy_pushLiteralArray(&arguments, indexLiteral); - Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]); - - Toy_LiteralArray returns; - Toy_initLiteralArray(&returns); - - Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns); - - //grab the results - Toy_Literal lit = Toy_popLiteralArray(&returns); - Toy_pushLiteralArray(returnsPtr, lit); - Toy_freeLiteral(lit); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - Toy_freeLiteral(indexLiteral); - } - - Toy_Literal returnsLiteral = TOY_TO_ARRAY_LITERAL(returnsPtr); - Toy_pushLiteralArray(&interpreter->stack, returnsLiteral); - Toy_freeLiteral(returnsLiteral); - } - - if (TOY_IS_DICTIONARY(selfLiteral)) { - Toy_LiteralArray* returnsPtr = TOY_ALLOCATE(Toy_LiteralArray, 1); - Toy_initLiteralArray(returnsPtr); - - for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) { - //skip nulls - if (TOY_IS_NULL(TOY_AS_DICTIONARY(selfLiteral)->entries[i].key)) { - continue; - } - - Toy_LiteralArray arguments; - Toy_initLiteralArray(&arguments); - Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key); - Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value); - - Toy_LiteralArray returns; - Toy_initLiteralArray(&returns); - - Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns); - - //grab the results - Toy_Literal lit = Toy_popLiteralArray(&returns); - Toy_pushLiteralArray(returnsPtr, lit); - Toy_freeLiteral(lit); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - } - - Toy_Literal returnsLiteral = TOY_TO_ARRAY_LITERAL(returnsPtr); - Toy_pushLiteralArray(&interpreter->stack, returnsLiteral); - Toy_freeLiteral(returnsLiteral); - } - - Toy_freeLiteral(fnLiteral); - Toy_freeLiteral(selfLiteral); - - return 0; -} - -static int nativeReduce(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 3) { - interpreter->errorOutput("Incorrect number of arguments to reduce\n"); - return -1; - } - - //get the args - Toy_Literal fnLiteral = Toy_popLiteralArray(arguments); - Toy_Literal defaultLiteral = Toy_popLiteralArray(arguments); - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - Toy_Literal defaultLiteralIdn = defaultLiteral; - if (TOY_IS_IDENTIFIER(defaultLiteral) && Toy_parseIdentifierToValue(interpreter, &defaultLiteral)) { - Toy_freeLiteral(defaultLiteralIdn); - } - - Toy_Literal fnLiteralIdn = fnLiteral; - if (TOY_IS_IDENTIFIER(fnLiteral) && Toy_parseIdentifierToValue(interpreter, &fnLiteral)) { - Toy_freeLiteral(fnLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(defaultLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) { - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(defaultLiteral); - Toy_freeLiteral(fnLiteral); - return -1; - } - - //check type - if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) { - interpreter->errorOutput("Incorrect argument type passed to reduce\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(defaultLiteral); - Toy_freeLiteral(fnLiteral); - return -1; - } - - //call the given function on each element, based on the compound type - if (TOY_IS_ARRAY(selfLiteral)) { - for (int i = 0; i < TOY_AS_ARRAY(selfLiteral)->count; i++) { - Toy_Literal indexLiteral = TOY_TO_INTEGER_LITERAL(i); - - Toy_LiteralArray arguments; - Toy_initLiteralArray(&arguments); - Toy_pushLiteralArray(&arguments, defaultLiteral); - Toy_pushLiteralArray(&arguments, indexLiteral); - Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]); - - Toy_LiteralArray returns; - Toy_initLiteralArray(&returns); - - Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns); - - //grab the results - Toy_freeLiteral(defaultLiteral); - defaultLiteral = Toy_popLiteralArray(&returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - Toy_freeLiteral(indexLiteral); - } - - Toy_pushLiteralArray(&interpreter->stack, defaultLiteral); - } - - if (TOY_IS_DICTIONARY(selfLiteral)) { - for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) { - //skip nulls - if (TOY_IS_NULL(TOY_AS_DICTIONARY(selfLiteral)->entries[i].key)) { - continue; - } - - Toy_LiteralArray arguments; - Toy_initLiteralArray(&arguments); - Toy_pushLiteralArray(&arguments, defaultLiteral); - Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key); - Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value); - - Toy_LiteralArray returns; - Toy_initLiteralArray(&returns); - - Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns); - - //grab the results - Toy_freeLiteral(defaultLiteral); - defaultLiteral = Toy_popLiteralArray(&returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - } - - Toy_pushLiteralArray(&interpreter->stack, defaultLiteral); - } - - Toy_freeLiteral(fnLiteral); - Toy_freeLiteral(defaultLiteral); - Toy_freeLiteral(selfLiteral); - - return 0; -} - -static int nativeSome(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments to some\n"); - return -1; - } - - //get the args - Toy_Literal fnLiteral = Toy_popLiteralArray(arguments); - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - Toy_Literal fnLiteralIdn = fnLiteral; - if (TOY_IS_IDENTIFIER(fnLiteral) && Toy_parseIdentifierToValue(interpreter, &fnLiteral)) { - Toy_freeLiteral(fnLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) { - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(fnLiteral); - return -1; - } - - //check type - if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) ) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) { - interpreter->errorOutput("Incorrect argument type passed to some\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(fnLiteral); - return -1; - } - - //call the given function on each element, based on the compound type - if (TOY_IS_ARRAY(selfLiteral)) { - bool result = false; - - // - for (int i = 0; i < TOY_AS_ARRAY(selfLiteral)->count; i++) { - Toy_Literal indexLiteral = TOY_TO_INTEGER_LITERAL(i); - - Toy_LiteralArray arguments; - Toy_initLiteralArray(&arguments); - Toy_pushLiteralArray(&arguments, indexLiteral); - Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[i]); - - Toy_LiteralArray returns; - Toy_initLiteralArray(&returns); - - Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns); - - //grab the results - Toy_Literal lit = Toy_popLiteralArray(&returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - Toy_freeLiteral(indexLiteral); - - //if not truthy - if (TOY_IS_TRUTHY(lit)) { - Toy_freeLiteral(lit); - result = true; - break; - } - - Toy_freeLiteral(lit); - } - - Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(result); - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - Toy_freeLiteral(resultLiteral); - } - - if (TOY_IS_DICTIONARY(selfLiteral)) { - bool result = false; - - for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) { - //skip nulls - if (TOY_IS_NULL(TOY_AS_DICTIONARY(selfLiteral)->entries[i].key)) { - continue; - } - - Toy_LiteralArray arguments; - Toy_initLiteralArray(&arguments); - Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].key); - Toy_pushLiteralArray(&arguments, TOY_AS_DICTIONARY(selfLiteral)->entries[i].value); - - Toy_LiteralArray returns; - Toy_initLiteralArray(&returns); - - Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns); - - //grab the results - Toy_Literal lit = Toy_popLiteralArray(&returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - - //if not truthy - if (TOY_IS_TRUTHY(lit)) { - Toy_freeLiteral(lit); - result = true; - break; - } - - Toy_freeLiteral(lit); - } - - Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(result); - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); - Toy_freeLiteral(resultLiteral); - } - - Toy_freeLiteral(fnLiteral); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static void swapLiteralsUtil(Toy_Literal* lhs, Toy_Literal* rhs) { - Toy_Literal tmp = *lhs; - *lhs = *rhs; - *rhs = tmp; -} - -//https://www.youtube.com/watch?v=MZaf_9IZCrc -static void recursiveLiteralQuicksortUtil(Toy_Interpreter* interpreter, Toy_Literal* ptr, int literalCount, Toy_Literal fnCompareLiteral) { - //base case - if (literalCount <= 1) { - return; - } - - int runner = 0; - - //iterate through the array - for (int checker = 0; checker < literalCount - 1; checker++) { - Toy_LiteralArray arguments; - Toy_LiteralArray returns; - - Toy_initLiteralArray(&arguments); - Toy_initLiteralArray(&returns); - - Toy_pushLiteralArray(&arguments, ptr[checker]); - Toy_pushLiteralArray(&arguments, ptr[literalCount - 1]); - - Toy_callLiteralFn(interpreter, fnCompareLiteral, &arguments, &returns); - - Toy_Literal lessThan = Toy_popLiteralArray(&returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - - if (TOY_IS_TRUTHY(lessThan)) { - swapLiteralsUtil(&ptr[runner++], &ptr[checker]); - } - - Toy_freeLiteral(lessThan); - } - - //"shift everything up" so the pivot is in the middle - swapLiteralsUtil(&ptr[runner], &ptr[literalCount - 1]); - - //recurse on each end - if (runner > 0) { - recursiveLiteralQuicksortUtil(interpreter, &ptr[0], runner, fnCompareLiteral); - } - - if (runner < literalCount) { - recursiveLiteralQuicksortUtil(interpreter, &ptr[runner + 1], literalCount - runner - 1, fnCompareLiteral); - } -} - -static int nativeSort(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments to sort\n"); - return -1; - } - - //get the args - Toy_Literal fnLiteral = Toy_popLiteralArray(arguments); - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to value if needed - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - Toy_Literal fnLiteralIdn = fnLiteral; - if (TOY_IS_IDENTIFIER(fnLiteral) && Toy_parseIdentifierToValue(interpreter, &fnLiteral)) { - Toy_freeLiteral(fnLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(fnLiteral)) { - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(fnLiteral); - return -1; - } - - //check type - if (!TOY_IS_ARRAY(selfLiteral) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) { - interpreter->errorOutput("Incorrect argument type passed to sort\n"); - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(fnLiteral); - return -1; - } - - //BUGFIX: check if the array is already sorted - bool sorted = true; - for (int checker = 0; checker < TOY_AS_ARRAY(selfLiteral)->count - 1 && sorted; checker++) { - Toy_LiteralArray arguments; - Toy_LiteralArray returns; - - Toy_initLiteralArray(&arguments); - Toy_initLiteralArray(&returns); - - Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[checker]); - Toy_pushLiteralArray(&arguments, TOY_AS_ARRAY(selfLiteral)->literals[checker + 1]); - - Toy_callLiteralFn(interpreter, fnLiteral, &arguments, &returns); - - Toy_Literal lessThan = Toy_popLiteralArray(&returns); - - Toy_freeLiteralArray(&arguments); - Toy_freeLiteralArray(&returns); - - if (!TOY_IS_TRUTHY(lessThan)) { - sorted = false; - } - - Toy_freeLiteral(lessThan); - } - - //call the quicksort util - if (!sorted) { - recursiveLiteralQuicksortUtil(interpreter, TOY_AS_ARRAY(selfLiteral)->literals, TOY_AS_ARRAY(selfLiteral)->count, fnLiteral); - } - - Toy_pushLiteralArray(&interpreter->stack, selfLiteral); - - Toy_freeLiteral(fnLiteral); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to toLower\n"); - return -1; - } - - //get the argument to a C-string - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral)) { - Toy_freeLiteral(selfLiteral); - return -1; - } - - if (!TOY_IS_STRING(selfLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to toLower\n"); - Toy_freeLiteral(selfLiteral); - return -1; - } - - Toy_RefString* selfRefString = TOY_AS_STRING(selfLiteral); - const char* self = Toy_toCString(selfRefString); - - //allocate buffer space for the result - char* result = TOY_ALLOCATE(char, Toy_lengthRefString(selfRefString) + 1); - - //set each new character - for (int i = 0; i < (int)Toy_lengthRefString(selfRefString); i++) { - result[i] = tolower(self[i]); - } - result[Toy_lengthRefString(selfRefString)] = '\0'; //end the string - - //wrap up and push the new result onto the stack - Toy_RefString* resultRefString = Toy_createRefStringLength(result, Toy_lengthRefString(selfRefString)); //internal copy - Toy_Literal resultLiteral = TOY_TO_STRING_LITERAL(resultRefString); //NO copy - - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); //internal copy - - //cleanup - TOY_FREE_ARRAY(char, result, Toy_lengthRefString(resultRefString) + 1); - Toy_freeLiteral(resultLiteral); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static char* toStringUtilObject = NULL; -static void toStringUtil(const char* input) { - size_t len = strlen(input) + 1; - - if (len > TOY_MAX_STRING_LENGTH) { - len = TOY_MAX_STRING_LENGTH; //TODO: don't truncate - } - - toStringUtilObject = TOY_ALLOCATE(char, len); - - snprintf(toStringUtilObject, len, "%s", input); -} - -static int nativeToString(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to toString\n"); - return -1; - } - - //get the argument - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - //parse to a value - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral)) { - Toy_freeLiteral(selfLiteral); - return -1; - } - - //BUGFIX: probably an undefined variable - if (TOY_IS_IDENTIFIER(selfLiteral)) { - Toy_freeLiteral(selfLiteral); - return -1; - } - - //print it to a custom function - Toy_printLiteralCustom(selfLiteral, toStringUtil); - - //create the resulting string and push it - Toy_Literal result = TOY_TO_STRING_LITERAL(Toy_createRefString(toStringUtilObject)); //internal copy - - Toy_pushLiteralArray(&interpreter->stack, result); - - //cleanup - TOY_FREE_ARRAY(char, toStringUtilObject, Toy_lengthRefString( TOY_AS_STRING(result) ) + 1); - toStringUtilObject = NULL; - - Toy_freeLiteral(result); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeToUpper(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments to toUpper\n"); - return -1; - } - - //get the argument to a C-string - Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral)) { - Toy_freeLiteral(selfLiteral); - return -1; - } - - if (!TOY_IS_STRING(selfLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to toUpper\n"); - Toy_freeLiteral(selfLiteral); - return -1; - } - - Toy_RefString* selfRefString = TOY_AS_STRING(selfLiteral); - const char* self = Toy_toCString(selfRefString); - - //allocate buffer space for the result - char* result = TOY_ALLOCATE(char, Toy_lengthRefString(selfRefString) + 1); - - //set each new character - for (int i = 0; i < (int)Toy_lengthRefString(selfRefString); i++) { - result[i] = toupper(self[i]); - } - result[Toy_lengthRefString(selfRefString)] = '\0'; //end the string - - //wrap up and push the new result onto the stack - Toy_RefString* resultRefString = Toy_createRefStringLength(result, Toy_lengthRefString(selfRefString)); //internal copy - Toy_Literal resultLiteral = TOY_TO_STRING_LITERAL(resultRefString); //NO copy - - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); //internal copy - - //cleanup - TOY_FREE_ARRAY(char, result, Toy_lengthRefString(resultRefString) + 1); - Toy_freeLiteral(resultLiteral); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeTrim(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count < 1 || arguments->count > 2) { - interpreter->errorOutput("Incorrect number of arguments to trim\n"); - return -1; - } - - //get the arguments - Toy_Literal trimCharsLiteral; - Toy_Literal selfLiteral; - - if (arguments->count == 2) { - trimCharsLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal trimCharsLiteralIdn = trimCharsLiteral; - if (TOY_IS_IDENTIFIER(trimCharsLiteral) && Toy_parseIdentifierToValue(interpreter, &trimCharsLiteral)) { - Toy_freeLiteral(trimCharsLiteralIdn); - } - } - else { - trimCharsLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(" \t\n\r")); - } - selfLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(trimCharsLiteral)) { - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(trimCharsLiteral); - return -1; - } - - if (!TOY_IS_STRING(selfLiteral) || !TOY_IS_STRING(trimCharsLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to trim\n"); - Toy_freeLiteral(trimCharsLiteral); - Toy_freeLiteral(selfLiteral); - return -1; - } - - //unwrap the arguments - Toy_RefString* trimCharsRefString = TOY_AS_STRING(trimCharsLiteral); - Toy_RefString* selfRefString = TOY_AS_STRING(selfLiteral); - - //allocate space for the new string - size_t bufferBegin = 0; - size_t bufferEnd = Toy_lengthRefString(selfRefString); - - //for each character in self, check it against each character in trimChars - on a fail, go to end - for (int i = 0; i < (int)Toy_lengthRefString(selfRefString); i++) { - int trimIndex = 0; - - while (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) { - //there is a match - DON'T increment anymore - if (Toy_toCString(selfRefString)[i] == Toy_toCString(trimCharsRefString)[trimIndex]) { - break; - } - - trimIndex++; - } - - //if the match is found, increment buffer begin - if (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) { - bufferBegin++; - continue; - } - else { - break; - } - } - - //again, from the back - for (int i = (int)Toy_lengthRefString(selfRefString); i >= 0; i--) { - int trimIndex = 0; - - while (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) { - //there is a match - DON'T increment anymore - if (Toy_toCString(selfRefString)[i-1] == Toy_toCString(trimCharsRefString)[trimIndex]) { - break; - } - - trimIndex++; - } - - //if the match is found, increment buffer begin - if (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) { - bufferEnd--; - continue; - } - else { - break; - } - } - - //generate the result - Toy_Literal resultLiteral; - if (bufferBegin >= bufferEnd) { //catch errors - resultLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("")); - } - else { - char buffer[TOY_MAX_STRING_LENGTH]; - snprintf(buffer, bufferEnd - bufferBegin + 1, "%s", &Toy_toCString(selfRefString)[ bufferBegin ]); - resultLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(buffer)); //internal copy - } - - //wrap up the buffer and return it - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); //internal copy - - //cleanup - Toy_freeLiteral(resultLiteral); - Toy_freeLiteral(trimCharsLiteral); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeTrimBegin(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count < 1 || arguments->count > 2) { - interpreter->errorOutput("Incorrect number of arguments to trimBegin\n"); - return -1; - } - - //get the arguments - Toy_Literal trimCharsLiteral; - Toy_Literal selfLiteral; - - if (arguments->count == 2) { - trimCharsLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal trimCharsLiteralIdn = trimCharsLiteral; - if (TOY_IS_IDENTIFIER(trimCharsLiteral) && Toy_parseIdentifierToValue(interpreter, &trimCharsLiteral)) { - Toy_freeLiteral(trimCharsLiteralIdn); - } - } - else { - trimCharsLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(" \t\n\r")); - } - selfLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(trimCharsLiteral)) { - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(trimCharsLiteral); - return -1; - } - - if (!TOY_IS_STRING(selfLiteral) || !TOY_IS_STRING(trimCharsLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to trimBegin\n"); - Toy_freeLiteral(trimCharsLiteral); - Toy_freeLiteral(selfLiteral); - return -1; - } - - //unwrap the arguments - Toy_RefString* trimCharsRefString = TOY_AS_STRING(trimCharsLiteral); - Toy_RefString* selfRefString = TOY_AS_STRING(selfLiteral); - - //allocate space for the new string - size_t bufferBegin = 0; - size_t bufferEnd = Toy_lengthRefString(selfRefString); - - //for each character in self, check it against each character in trimChars - on a fail, go to end - for (int i = 0; i < (int)Toy_lengthRefString(selfRefString); i++) { - int trimIndex = 0; - - while (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) { - //there is a match - DON'T increment anymore - if (Toy_toCString(selfRefString)[i] == Toy_toCString(trimCharsRefString)[trimIndex]) { - break; - } - - trimIndex++; - } - - //if the match is found, increment buffer begin - if (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) { - bufferBegin++; - continue; - } - else { - break; - } - } - - //generate the result - Toy_Literal resultLiteral; - if (bufferBegin >= bufferEnd) { //catch errors - resultLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("")); - } - else { - char buffer[TOY_MAX_STRING_LENGTH]; - snprintf(buffer, bufferEnd - bufferBegin + 1, "%s", &Toy_toCString(selfRefString)[ bufferBegin ]); - resultLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(buffer)); //internal copy - } - - //wrap up the buffer and return it - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); //internal copy - - //cleanup - Toy_freeLiteral(resultLiteral); - Toy_freeLiteral(trimCharsLiteral); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -static int nativeTrimEnd(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - if (arguments->count < 1 || arguments->count > 2) { - interpreter->errorOutput("Incorrect number of arguments to trimEnd\n"); - return -1; - } - - //get the arguments - Toy_Literal trimCharsLiteral; - Toy_Literal selfLiteral; - - if (arguments->count == 2) { - trimCharsLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal trimCharsLiteralIdn = trimCharsLiteral; - if (TOY_IS_IDENTIFIER(trimCharsLiteral) && Toy_parseIdentifierToValue(interpreter, &trimCharsLiteral)) { - Toy_freeLiteral(trimCharsLiteralIdn); - } - } - else { - trimCharsLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(" \t\n\r")); - } - selfLiteral = Toy_popLiteralArray(arguments); - - Toy_Literal selfLiteralIdn = selfLiteral; - if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { - Toy_freeLiteral(selfLiteralIdn); - } - - if (TOY_IS_IDENTIFIER(selfLiteral) || TOY_IS_IDENTIFIER(trimCharsLiteral)) { - Toy_freeLiteral(selfLiteral); - Toy_freeLiteral(trimCharsLiteral); - return -1; - } - - if (!TOY_IS_STRING(selfLiteral) || !TOY_IS_STRING(trimCharsLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to trimEnd\n"); - Toy_freeLiteral(trimCharsLiteral); - Toy_freeLiteral(selfLiteral); - return -1; - } - - //unwrap the arguments - Toy_RefString* trimCharsRefString = TOY_AS_STRING(trimCharsLiteral); - Toy_RefString* selfRefString = TOY_AS_STRING(selfLiteral); - - //allocate space for the new string - size_t bufferBegin = 0; - size_t bufferEnd = Toy_lengthRefString(selfRefString); - - //again, from the back - for (int i = (int)Toy_lengthRefString(selfRefString); i >= 0; i--) { - int trimIndex = 0; - - while (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) { - //there is a match - DON'T increment anymore - if (Toy_toCString(selfRefString)[i-1] == Toy_toCString(trimCharsRefString)[trimIndex]) { - break; - } - - trimIndex++; - } - - //if the match is found, increment buffer begin - if (trimIndex < (int)Toy_lengthRefString(trimCharsRefString)) { - bufferEnd--; - continue; - } - else { - break; - } - } - - //generate the result - Toy_Literal resultLiteral; - if (bufferBegin >= bufferEnd) { //catch errors - resultLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("")); - } - else { - char buffer[TOY_MAX_STRING_LENGTH]; - snprintf(buffer, bufferEnd - bufferBegin + 1, "%s", &Toy_toCString(selfRefString)[ bufferBegin ]); - resultLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(buffer)); //internal copy - } - - //wrap up the buffer and return it - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); //internal copy - - //cleanup - Toy_freeLiteral(resultLiteral); - Toy_freeLiteral(trimCharsLiteral); - Toy_freeLiteral(selfLiteral); - - return 1; -} - -//call the hook -typedef struct Natives { - char* name; - Toy_NativeFn fn; -} Natives; - -int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) { - //build the natives list - Natives natives[] = { - //misc. utils - {"clock", nativeClock}, - {"hash", nativeHash}, - - //math utils - {"abs", nativeAbs}, - {"ceil", nativeCeil}, - {"floor", nativeFloor}, - {"max", nativeMax}, - {"min", nativeMin}, - {"round", nativeRound}, - - //compound utils - {"concat", nativeConcat}, //array, dictionary, string - {"containsKey", nativeContainsKey}, //dictionary - {"containsValue", nativeContainsValue}, //array, dictionary - {"every", nativeEvery}, //array, dictionary - {"filter", nativeFilter}, //array, dictionary - {"forEach", nativeForEach}, //array, dictionary - {"getKeys", nativeGetKeys}, //dictionary - {"getValues", nativeGetValues}, //dictionary - {"indexOf", nativeIndexOf}, //array - {"map", nativeMap}, //array, dictionary - {"reduce", nativeReduce}, //array, dictionary - {"some", nativeSome}, //array, dictionary - {"sort", nativeSort}, //array - {"toLower", nativeToLower}, //string - {"toString", nativeToString}, //array, dictionary - {"toUpper", nativeToUpper}, //string - {"trim", nativeTrim}, //string - {"trimBegin", nativeTrimBegin}, //string - {"trimEnd", nativeTrimEnd}, //string - {NULL, NULL} - }; - - //store the library in an aliased dictionary - if (!TOY_IS_NULL(alias)) { - //make sure the name isn't taken - if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) { - interpreter->errorOutput("Can't override an existing variable\n"); - Toy_freeLiteral(alias); - return -1; - } - - //create the dictionary to load up with functions - Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1); - Toy_initLiteralDictionary(dictionary); - - //load the dict with functions - for (int i = 0; natives[i].name; i++) { - Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name)); - Toy_Literal func = TOY_TO_FUNCTION_NATIVE_LITERAL(natives[i].fn); - - Toy_setLiteralDictionary(dictionary, name, func); - - Toy_freeLiteral(name); - Toy_freeLiteral(func); - } - - //build the type - Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true); - Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true); - Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true); - TOY_TYPE_PUSH_SUBTYPE(&type, strType); - TOY_TYPE_PUSH_SUBTYPE(&type, fnType); - - //set scope - Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary); - Toy_declareScopeVariable(interpreter->scope, alias, type); - Toy_setScopeVariable(interpreter->scope, alias, dict, false); - - //cleanup - Toy_freeLiteral(dict); - Toy_freeLiteral(type); - return 0; - } - - //default - for (int i = 0; natives[i].name; i++) { - Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn); - } - - return 0; -} diff --git a/box/lib_standard.h b/box/lib_standard.h deleted file mode 100644 index d1b9816..0000000 --- a/box/lib_standard.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "toy_interpreter.h" - -int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias); - diff --git a/box/makefile b/box/makefile deleted file mode 100644 index 75dbbb9..0000000 --- a/box/makefile +++ /dev/null @@ -1,51 +0,0 @@ -CC=gcc - -IDIR+=. ../Toy/source -CFLAGS+=$(addprefix -I,$(IDIR)) -g -Wall -W -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable -LIBS+=-lSDL2 -lSDL2_image -ltoy - -ODIR = obj -SRC = $(wildcard *.c) -OBJ = $(addprefix $(ODIR)/,$(SRC:.c=.o)) - -REPLLIBS = $(wildcard ../Toy/repl/lib*) $(wildcard ../Toy/repl/repl_tools.*) - -OUTNAME=box - -ifeq ($(findstring CYGWIN, $(shell uname)),CYGWIN) - LIBLINE =-Wl,--out-implib=$(BOX_OUTDIR)/lib$(OUTNAME).dll.a -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--whole-archive $(OBJ) -Wl,--no-whole-archive - OUT=$(BOX_OUTDIR)/$(OUTNAME).dll -else ifeq ($(shell uname),Linux) - LIBLINE=-Wl,--out-implib=./$(BOX_OUTDIR)/lib$(OUTNAME).a -Wl,--whole-archive $(OBJ) -Wl,--no-whole-archive - OUT=./$(BOX_OUTDIR)/lib$(OUTNAME).so - CFLAGS += -fPIC -else ifeq ($(OS),Windows_NT) - LIBLINE =-Wl,--out-implib=$(BOX_OUTDIR)/lib$(OUTNAME).dll.a -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--whole-archive $(OBJ) -Wl,--no-whole-archive - OUT=$(BOX_OUTDIR)/$(OUTNAME).dll -else - @echo "Platform test failed - what platform is this?" - exit 1 -endif - -library: repllibs $(OBJ) - $(CC) -DBOX_EXPORT $(CFLAGS) -shared -o $(OUT) $(LIBLINE) -L../$(LIBDIR) $(LIBS) - -static: repllibs $(OBJ) - ar crs $(BOX_OUTDIR)/lib$(OUTNAME).a $(OBJ) -L../$(LIBDIR) $(LIBS) - -#copy the stuff from Toy/repl that is needed -repllibs: - cp $(REPLLIBS) . - -$(OBJ): | $(ODIR) - -$(ODIR): - mkdir $(ODIR) - -$(ODIR)/%.o: %.c - $(CC) -c -o $@ $< $(CFLAGS) - -.PHONY: clean - -clean-repllibs: - $(RM) $(notdir $(REPLLIBS)) \ No newline at end of file diff --git a/box/repl_tools.c b/box/repl_tools.c deleted file mode 100644 index 63090f9..0000000 --- a/box/repl_tools.c +++ /dev/null @@ -1,207 +0,0 @@ -#include "repl_tools.h" -#include "lib_about.h" -#include "lib_standard.h" -#include "lib_random.h" -#include "lib_runner.h" - -#include "toy_console_colors.h" - -#include "toy_lexer.h" -#include "toy_parser.h" -#include "toy_compiler.h" -#include "toy_interpreter.h" - -#include -#include - -//IO functions -const unsigned char* Toy_readFile(const char* path, size_t* fileSize) { - FILE* file = fopen(path, "rb"); - - if (file == NULL) { - fprintf(stderr, TOY_CC_ERROR "Could not open file \"%s\"\n" TOY_CC_RESET, path); - return NULL; - } - - fseek(file, 0L, SEEK_END); - *fileSize = ftell(file); - rewind(file); - - unsigned char* buffer = (unsigned char*)malloc(*fileSize + 1); - - if (buffer == NULL) { - fprintf(stderr, TOY_CC_ERROR "Not enough memory to read \"%s\"\n" TOY_CC_RESET, path); - return NULL; - } - - size_t bytesRead = fread(buffer, sizeof(unsigned char), *fileSize, file); - - buffer[*fileSize] = '\0'; //NOTE: fread doesn't append this - - if (bytesRead < *fileSize) { - fprintf(stderr, TOY_CC_ERROR "Could not read file \"%s\"\n" TOY_CC_RESET, path); - return NULL; - } - - fclose(file); - - return buffer; -} - -int Toy_writeFile(const char* path, const unsigned char* bytes, size_t size) { - FILE* file = fopen(path, "wb"); - - if (file == NULL) { - fprintf(stderr, TOY_CC_ERROR "Could not open file \"%s\"\n" TOY_CC_RESET, path); - return -1; - } - - size_t written = fwrite(bytes, size, 1, file); - - if (written != 1) { - fprintf(stderr, TOY_CC_ERROR "Could not write file \"%s\"\n" TOY_CC_RESET, path); - return -1; - } - - fclose(file); - - return 0; -} - -//repl functions -const unsigned char* Toy_compileString(const char* source, size_t* size) { - Toy_Lexer lexer; - Toy_Parser parser; - Toy_Compiler compiler; - - Toy_initLexer(&lexer, source); - Toy_initParser(&parser, &lexer); - Toy_initCompiler(&compiler); - - //step 1 - run the parser until the end of the source - Toy_ASTNode* node = Toy_scanParser(&parser); - while(node != NULL) { - //on error, pack up and leave - if (node->type == TOY_AST_NODE_ERROR) { - Toy_freeASTNode(node); - Toy_freeCompiler(&compiler); - Toy_freeParser(&parser); - return NULL; - } - - Toy_writeCompiler(&compiler, node); - Toy_freeASTNode(node); - node = Toy_scanParser(&parser); - } - - //step 2 - get the bytecode dump - const unsigned char* tb = Toy_collateCompiler(&compiler, size); - - //cleanup - Toy_freeCompiler(&compiler); - Toy_freeParser(&parser); - //no lexer to clean up - - //finally - return tb; -} - -void Toy_runBinary(const unsigned char* tb, size_t size) { - Toy_Interpreter interpreter; - Toy_initInterpreter(&interpreter); - - //inject the libs - Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout); - Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard); - Toy_injectNativeHook(&interpreter, "random", Toy_hookRandom); - Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner); - - Toy_runInterpreter(&interpreter, tb, (int)size); - Toy_freeInterpreter(&interpreter); -} - -void Toy_runBinaryFile(const char* fname) { - size_t size = 0; //not used - const unsigned char* tb = Toy_readFile(fname, &size); - if (!tb) { - return; - } - Toy_runBinary(tb, size); - //interpreter takes ownership of the binary data -} - -void Toy_runSource(const char* source) { - size_t size = 0; - const unsigned char* tb = Toy_compileString(source, &size); - if (!tb) { - return; - } - - Toy_runBinary(tb, size); -} - -void Toy_runSourceFile(const char* fname) { - size_t size = 0; //not used - const char* source = (const char*)Toy_readFile(fname, &size); - if (!source) { - return; - } - Toy_runSource(source); - free((void*)source); -} - -//utils for debugging the header -static unsigned char readByte(const unsigned char* tb, int* count) { - unsigned char ret = *(unsigned char*)(tb + *count); - *count += 1; - return ret; -} - -static const char* readString(const unsigned char* tb, int* count) { - const unsigned char* ret = tb + *count; - *count += strlen((char*)ret) + 1; //+1 for null character - return (const char*)ret; -} - -void Toy_parseBinaryFileHeader(const char* fname) { - size_t size = 0; //not used - const unsigned char* tb = Toy_readFile(fname, &size); - if (!tb || size < 4) { - return; - } - - int count = 0; - - //header section - const unsigned char major = readByte(tb, &count); - const unsigned char minor = readByte(tb, &count); - const unsigned char patch = readByte(tb, &count); - - const char* build = readString(tb, &count); - - printf("Toy Programming Language Interpreter Version %d.%d.%d (interpreter built on %s)\n\n", TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, TOY_VERSION_BUILD); - - printf("Toy Programming Language Bytecode Version "); - - //print the output - if (major == TOY_VERSION_MAJOR && minor == TOY_VERSION_MINOR && patch == TOY_VERSION_PATCH) { - printf("%d.%d.%d", major, minor, patch); - } - else { - printf(TOY_CC_FONT_YELLOW TOY_CC_BACK_BLACK "%d.%d.%d" TOY_CC_RESET, major, minor, patch); - } - - printf(" (interpreter built on "); - - if (strncmp(build, TOY_VERSION_BUILD, strlen(TOY_VERSION_BUILD)) == 0) { - printf("%s", build); - } - else { - printf(TOY_CC_FONT_YELLOW TOY_CC_BACK_BLACK "%s" TOY_CC_RESET, build); - } - - printf(")\n"); - - //cleanup - free((void*)tb); -} \ No newline at end of file diff --git a/box/repl_tools.h b/box/repl_tools.h deleted file mode 100644 index 5fda23e..0000000 --- a/box/repl_tools.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "toy_common.h" - -const unsigned char* Toy_readFile(const char* path, size_t* fileSize); -int Toy_writeFile(const char* path, const unsigned char* bytes, size_t size); - -const unsigned char* Toy_compileString(const char* source, size_t* size); - -void Toy_runBinary(const unsigned char* tb, size_t size); -void Toy_runBinaryFile(const char* fname); -void Toy_runSource(const char* source); -void Toy_runSourceFile(const char* fname); - -void Toy_parseBinaryFileHeader(const char* fname); \ No newline at end of file diff --git a/makefile b/makefile index 6389a3c..0c3763d 100644 --- a/makefile +++ b/makefile @@ -1,34 +1,19 @@ export OUTDIR = out -export LIBDIR = lib -export TOY_OUTDIR = ../$(LIBDIR) -export BOX_OUTDIR = ../$(LIBDIR) +export BOX_OUTDIR = ../$(OUTDIR) +export TOY_OUTDIR = ../../$(OUTDIR) -all: $(OUTDIR) $(LIBDIR) toy box +all: $(OUTDIR) toy box $(MAKE) -j8 -C source -ifeq ($(findstring CYGWIN, $(shell uname)),CYGWIN) - cp $(LIBDIR)/*.dll $(OUTDIR) -else ifeq ($(shell uname),Linux) - cp $(LIBDIR)/*.so $(OUTDIR) -else ifeq ($(OS),Windows_NT) - cp $(LIBDIR)/*.dll $(OUTDIR) -endif - -test: clean $(OUTDIR) toy box - $(MAKE) -C test toy: $(LIBDIR) - $(MAKE) -j8 -C Toy/source + $(MAKE) -j8 -C Box/Toy/source box: $(LIBDIR) - $(MAKE) -j8 -C box repllibs - $(MAKE) -j8 -C box library + $(MAKE) -j8 -C Box/source $(OUTDIR): mkdir $(OUTDIR) -$(LIBDIR): - mkdir $(LIBDIR) - .PHONY: clean clean: @@ -56,24 +41,3 @@ else endif rebuild: clean all - - -#utils for the manual android build -INCLUDEDIR=include - -SOURCEDIR=bundle - -$(INCLUDEDIR): - mkdir $(INCLUDEDIR) - -$(SOURCEDIR): - mkdir $(SOURCEDIR) - -sourcelist: - @echo $(addprefix ../airport/,$(wildcard Toy/source/*.c) $(wildcard box/*.c) $(wildcard source/*.c)) > source.list - -bundleincludes: $(INCLUDEDIR) - cp $(addprefix ../airport/,$(wildcard Toy/source/*.h) $(wildcard box/*.h) $(wildcard source/*.h)) $(INCLUDEDIR) - -bundlesource: $(SOURCEDIR) - cp $(addprefix ../airport/,$(wildcard Toy/source/*.c) $(wildcard box/*.c) $(wildcard source/*.c)) $(SOURCEDIR) \ No newline at end of file diff --git a/test/makefile b/test/makefile deleted file mode 100644 index b3866bd..0000000 --- a/test/makefile +++ /dev/null @@ -1,41 +0,0 @@ -CC=gcc - -IDIR+=. ../Toy/source ../box -CFLAGS+=$(addprefix -I,$(IDIR)) -DSDL_MAIN_HANDLED -g -Wall -W -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable -LIBS+=-lSDL2 -lSDL2_image -ltoy -lbox - -ODIR = obj -TARGETS = $(wildcard ../box/*.c) -TESTS = $(wildcard *.c) -OBJ = $(addprefix $(ODIR)/,$(TARGETS:../box/%.c=%.o)) $(addprefix $(ODIR)/,$(TESTS:.c=.o)) - -.PRECIOUS: $(TESTS:%.c=../$(OUTDIR)/%.exe) - -all: $(OBJ) $(TESTS:%.c=../$(OUTDIR)/%.exe) - -../$(OUTDIR)/%.exe: $(ODIR)/%.o -ifeq ($(shell uname),Linux) - @$(CC) -o $@ $< $(TARGETS:../box/%.c=$(ODIR)/%.o) $(CFLAGS) -Wl,-rpath,../out -L../$(LIBDIR) $(LIBS) - cp ../$(LIBDIR)/*.so ../$(OUTDIR) - valgrind --leak-check=full --track-origins=yes $@ -else - @$(CC) -o $@ $< $(TARGETS:../box/%.c=$(ODIR)/%.o) $(CFLAGS) -L../$(LIBDIR) $(LIBS) - cp ../$(LIBDIR)/*.dll ../$(OUTDIR) - $@ -endif - -$(OBJ): | $(ODIR) - -$(ODIR): - mkdir $(ODIR) - -$(ODIR)/%.o: %.c - @$(CC) -c -o $@ $< $(CFLAGS) - -$(ODIR)/%.o: ../box/%.c - @$(CC) -c -o $@ $< $(CFLAGS) - -.PHONY: clean - -clean: - $(RM) $(ODIR) diff --git a/test/scripts/child_engine_node.toy b/test/scripts/child_engine_node.toy deleted file mode 100644 index ee6f6f9..0000000 --- a/test/scripts/child_engine_node.toy +++ /dev/null @@ -1,14 +0,0 @@ -var tally: int = 0; - -fn onInit(node: opaque) { - print "child init called"; -} - -fn onStep(node: opaque) { - print "child step called"; - print ++tally; -} - -fn onFree(node: opaque) { - print "child free called"; -} \ No newline at end of file diff --git a/test/scripts/parent_engine_node.toy b/test/scripts/parent_engine_node.toy deleted file mode 100644 index 4d85bf4..0000000 --- a/test/scripts/parent_engine_node.toy +++ /dev/null @@ -1,11 +0,0 @@ -fn onInit(node: opaque) { - print "init called"; -} - -fn onStep(node: opaque) { - print "step called"; -} - -fn onFree(node: opaque) { - print "free called"; -} \ No newline at end of file diff --git a/test/test_engine_node.c b/test/test_engine_node.c deleted file mode 100644 index d6e1d8d..0000000 --- a/test/test_engine_node.c +++ /dev/null @@ -1,110 +0,0 @@ -#include "box_engine_node.h" - -#include "toy_lexer.h" -#include "toy_parser.h" -#include "toy_compiler.h" -#include "toy_interpreter.h" -#include "toy_console_colors.h" -#include "toy_memory.h" - -#include "repl_tools.h" - -#include -#include -#include - -//suppress the print keyword -static void noPrintFn(const char* output) { - //NO OP -} - -int main() { - { - //setup interpreter - Toy_Interpreter interpreter; - Toy_initInterpreter(&interpreter); - Toy_setInterpreterPrint(&interpreter, noPrintFn); - - size_t size = 0; - - const char* source = Toy_readFile("./scripts/parent_engine_node.toy", &size); - const unsigned char* tb = Toy_compileString(source, &size); - - //create and test the engine node - Box_EngineNode* node = TOY_ALLOCATE(Box_EngineNode, 1); - - Box_initEngineNode(node, &interpreter, tb, size); - - Toy_Literal nodeLiteral = TOY_TO_OPAQUE_LITERAL(node, OPAQUE_TAG_ENGINE_NODE); - - //argument list to pass in the node - Toy_LiteralArray arguments; - Toy_initLiteralArray(&arguments); - - //call each function - Box_callRecursiveEngineNode(node, &interpreter, "onInit", &arguments); - Box_callRecursiveEngineNode(node, &interpreter, "onStep", &arguments); - Box_callRecursiveEngineNode(node, &interpreter, "onQuit", &arguments); - - //cleanup - Toy_freeLiteralArray(&arguments); - Box_freeEngineNode(node); - free((void*)source); - - Toy_freeInterpreter(&interpreter); - } - - { - //setup interpreter - Toy_Interpreter interpreter; - Toy_initInterpreter(&interpreter); - Toy_setInterpreterPrint(&interpreter, noPrintFn); - - size_t size = 0; - - const char* source = Toy_readFile("./scripts/parent_engine_node.toy", &size); - const unsigned char* tb = Toy_compileString(source, &size); - - //create and test the engine node - Box_EngineNode* node = TOY_ALLOCATE(Box_EngineNode, 1); - - Box_initEngineNode(node, &interpreter, tb, size); - Toy_resetInterpreter(&interpreter); - - for (int i = 0; i < 10; i++) { - const char* source = Toy_readFile("./scripts/child_engine_node.toy", &size); - const unsigned char* tb = Toy_compileString(source, &size); - - Box_EngineNode* child = TOY_ALLOCATE(Box_EngineNode, 1); - Box_initEngineNode(child, &interpreter, tb, size); - Toy_resetInterpreter(&interpreter); - - Box_pushEngineNode(node, child); - - free((void*)source); - } - - //argument list to pass in each time - Toy_LiteralArray arguments; - Toy_initLiteralArray(&arguments); - - //test the calls - Box_callRecursiveEngineNode(node, &interpreter, "onInit", &arguments); - - for (int i = 0; i < 10; i++) { - Box_callRecursiveEngineNode(node, &interpreter, "onStep", &arguments); - } - - Box_callRecursiveEngineNode(node, &interpreter, "onFree", &arguments); - - //cleanup - Toy_freeLiteralArray(&arguments); - Box_freeEngineNode(node); //frees all children - free((void*)source); - - Toy_freeInterpreter(&interpreter); - } - - printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); - return 0; -}