From 7ea249f7235c22d20d547eb0e9ad836f09908661 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sun, 5 Feb 2023 14:42:53 +0000 Subject: [PATCH] Added the about library, resolved #51 --- repl/lib_about.c | 162 +++++++++++++++++++++++++++++++++++++ repl/lib_about.h | 6 ++ repl/lib_compound.c | 2 +- repl/lib_runner.c | 2 +- repl/lib_standard.c | 2 +- repl/lib_timer.c | 2 +- repl/repl_main.c | 2 + repl/repl_tools.c | 2 + source/toy_common.c | 2 +- source/toy_interpreter.c | 2 +- test/scripts/lib/about.toy | 7 ++ test/test_libraries.c | 2 + 12 files changed, 187 insertions(+), 6 deletions(-) create mode 100644 repl/lib_about.c create mode 100644 repl/lib_about.h create mode 100644 test/scripts/lib/about.toy diff --git a/repl/lib_about.c b/repl/lib_about.c new file mode 100644 index 0000000..fe5b0c8 --- /dev/null +++ b/repl/lib_about.c @@ -0,0 +1,162 @@ +#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/repl/lib_about.h b/repl/lib_about.h new file mode 100644 index 0000000..26b1d4a --- /dev/null +++ b/repl/lib_about.h @@ -0,0 +1,6 @@ +#pragma once + +#include "toy_interpreter.h" + +int Toy_hookAbout(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias); + diff --git a/repl/lib_compound.c b/repl/lib_compound.c index a7c9850..0811a7a 100644 --- a/repl/lib_compound.c +++ b/repl/lib_compound.c @@ -390,7 +390,7 @@ int Toy_hookCompound(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) { interpreter->errorOutput("Can't override an existing variable\n"); Toy_freeLiteral(alias); - return false; + return -1; } //create the dictionary to load up with functions diff --git a/repl/lib_runner.c b/repl/lib_runner.c index 5d4bbd6..1f5104f 100644 --- a/repl/lib_runner.c +++ b/repl/lib_runner.c @@ -516,7 +516,7 @@ int Toy_hookRunner(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Lit if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) { interpreter->errorOutput("Can't override an existing variable\n"); Toy_freeLiteral(alias); - return false; + return -1; } //create the dictionary to load up with functions diff --git a/repl/lib_standard.c b/repl/lib_standard.c index bb427b7..33d612f 100644 --- a/repl/lib_standard.c +++ b/repl/lib_standard.c @@ -49,7 +49,7 @@ int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) { interpreter->errorOutput("Can't override an existing variable\n"); Toy_freeLiteral(alias); - return false; + return -1; } //create the dictionary to load up with functions diff --git a/repl/lib_timer.c b/repl/lib_timer.c index f0d3194..d05011e 100644 --- a/repl/lib_timer.c +++ b/repl/lib_timer.c @@ -366,7 +366,7 @@ int Toy_hookTimer(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Lite if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) { interpreter->errorOutput("Can't override an existing variable\n"); Toy_freeLiteral(alias); - return false; + return -1; } //create the dictionary to load up with functions diff --git a/repl/repl_main.c b/repl/repl_main.c index 482eb21..8013c96 100644 --- a/repl/repl_main.c +++ b/repl/repl_main.c @@ -1,4 +1,5 @@ #include "repl_tools.h" +#include "lib_about.h" #include "lib_compound.h" #include "lib_standard.h" #include "lib_timer.h" @@ -27,6 +28,7 @@ void repl() { Toy_initInterpreter(&interpreter); //inject the libs + Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout); Toy_injectNativeHook(&interpreter, "compound", Toy_hookCompound); Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard); Toy_injectNativeHook(&interpreter, "timer", Toy_hookTimer); diff --git a/repl/repl_tools.c b/repl/repl_tools.c index f7e0afc..1b8269d 100644 --- a/repl/repl_tools.c +++ b/repl/repl_tools.c @@ -1,4 +1,5 @@ #include "repl_tools.h" +#include "lib_about.h" #include "lib_compound.h" #include "lib_standard.h" #include "lib_timer.h" @@ -111,6 +112,7 @@ void Toy_runBinary(unsigned char* tb, size_t size) { Toy_initInterpreter(&interpreter); //inject the libs + Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout); Toy_injectNativeHook(&interpreter, "compound", Toy_hookCompound); Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard); Toy_injectNativeHook(&interpreter, "timer", Toy_hookTimer); diff --git a/source/toy_common.c b/source/toy_common.c index 4831c92..3405553 100644 --- a/source/toy_common.c +++ b/source/toy_common.c @@ -114,7 +114,7 @@ void Toy_helpCommandLine(int argc, const char* argv[]) { void Toy_copyrightCommandLine(int argc, const char* argv[]) { printf("Toy Programming Language Interpreter Version %d.%d.%d (built on %s)\n\n", TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, TOY_VERSION_BUILD); - printf("Copyright (c) 2020-2022 Kayne Ruse, KR Game Studios\n\n"); + printf("Copyright (c) 2020-2023 Kayne Ruse, KR Game Studios\n\n"); printf("This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.\n\n"); printf("Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:\n\n"); printf("1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n\n"); diff --git a/source/toy_interpreter.c b/source/toy_interpreter.c index 7b96768..1706000 100644 --- a/source/toy_interpreter.c +++ b/source/toy_interpreter.c @@ -822,7 +822,7 @@ static bool execTypeOf(Toy_Interpreter* interpreter) { type = Toy_getScopeType(interpreter->scope, rhs); } else { - type = TOY_TO_TYPE_LITERAL(rhs.type, false); + type = TOY_TO_TYPE_LITERAL(rhs.type, false); //see issue #53 } Toy_pushLiteralArray(&interpreter->stack, type); diff --git a/test/scripts/lib/about.toy b/test/scripts/lib/about.toy new file mode 100644 index 0000000..51de8c1 --- /dev/null +++ b/test/scripts/lib/about.toy @@ -0,0 +1,7 @@ +import about as about; +import about; + +assert author == "Kayne Ruse, KR Game Studios", "Author failed"; + + +print "All good"; diff --git a/test/test_libraries.c b/test/test_libraries.c index b335000..9478442 100644 --- a/test/test_libraries.c +++ b/test/test_libraries.c @@ -13,6 +13,7 @@ #include "../repl/repl_tools.h" +#include "../repl/lib_about.h" #include "../repl/lib_compound.h" #include "../repl/lib_runner.h" #include "../repl/lib_standard.h" @@ -74,6 +75,7 @@ int main() { //run each file in test/scripts Payload payloads[] = { {"interactions.toy", "standard", Toy_hookStandard}, //interactions needs standard + {"about.toy", "about", Toy_hookAbout}, {"compound.toy", "compound", Toy_hookCompound}, {"runner.toy", "runner", Toy_hookRunner}, {"standard.toy", "standard", Toy_hookStandard},