From d3df01c1c4ae625fb7a3a36eb0ae8afee31bfefa Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Thu, 23 Feb 2023 03:33:52 +1100 Subject: [PATCH 1/4] Updated .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index dccf75b..408efe4 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,8 @@ bin/ *.db *.o *.a +*.so +*.dll *.exe *.meta *.log From 3e6d21afbbecc172653f7dc9ba9ef40b3a1aba76 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Thu, 23 Feb 2023 18:36:12 +1100 Subject: [PATCH 2/4] Added abs(), hash() to libstandard --- repl/lib_standard.c | 75 +++++++++++++++++++++++++++++++++++ test/scripts/lib/standard.toy | 20 ++++++++++ 2 files changed, 95 insertions(+) diff --git a/repl/lib_standard.c b/repl/lib_standard.c index d7d5a8c..4375488 100644 --- a/repl/lib_standard.c +++ b/repl/lib_standard.c @@ -7,6 +7,49 @@ #include #include +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 nativeClock(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { //no arguments if (arguments->count != 0) { @@ -702,6 +745,36 @@ static int nativeGetValues(Toy_Interpreter* interpreter, Toy_LiteralArray* argum 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 nativeIndexOf(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { //no arguments if (arguments->count != 2) { @@ -1667,6 +1740,7 @@ typedef struct Natives { int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) { //build the natives list Natives natives[] = { + {"abs", nativeAbs}, {"clock", nativeClock}, {"concat", nativeConcat}, //array, dictionary, string {"containsKey", nativeContainsKey}, //dictionary @@ -1676,6 +1750,7 @@ int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L {"forEach", nativeForEach}, //array, dictionary {"getKeys", nativeGetKeys}, //dictionary {"getValues", nativeGetValues}, //dictionary + {"hash", nativeHash}, {"indexOf", nativeIndexOf}, //array {"map", nativeMap}, //array, dictionary {"reduce", nativeReduce}, //array, dictionary diff --git a/test/scripts/lib/standard.toy b/test/scripts/lib/standard.toy index 5c9c17e..117bb70 100644 --- a/test/scripts/lib/standard.toy +++ b/test/scripts/lib/standard.toy @@ -1,5 +1,18 @@ import standard; +//test abs +{ + assert abs(-5) == 5, "abs(-integer) failed"; + assert abs(-5.5) == 5.5, "abs(-float) failed"; + assert abs(5) == 5, "abs(+integer) failed"; + assert abs(5.5) == 5.5, "abs(+float) failed"; + + var x = -5; + + assert x.abs() == 5, "var.abs() failed"; +} + + //test clock { //this depends on external factors, so only check the length @@ -162,6 +175,13 @@ import standard; } +//test hash +{ + assert typeof "Hello world".hash() == int, "typeof \"Hello world\".hash() failed"; + assert "Hello world".hash() == 994097935, "\"Hello world\".hash() failed"; //NOTE: specific value based on algorithm +} + + //test indexOf { var a = [1, 2, 42, 3]; From 92c71a374d3a13e91ea28bc13dd2ddfb282798aa Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Thu, 23 Feb 2023 19:19:17 +1100 Subject: [PATCH 3/4] Implemented a basic random library --- repl/lib_random.c | 196 ++++++++++++++++++++++++++++++ repl/lib_random.h | 7 ++ repl/repl_main.c | 2 + repl/repl_tools.c | 2 + scripts/small.toy | 12 ++ test/scripts/lib/random-stuff.toy | 0 test/scripts/lib/random.toy | 17 +++ test/test_libraries.c | 58 +-------- 8 files changed, 241 insertions(+), 53 deletions(-) create mode 100644 repl/lib_random.c create mode 100644 repl/lib_random.h delete mode 100644 test/scripts/lib/random-stuff.toy create mode 100644 test/scripts/lib/random.toy diff --git a/repl/lib_random.c b/repl/lib_random.c new file mode 100644 index 0000000..6b70cc8 --- /dev/null +++ b/repl/lib_random.c @@ -0,0 +1,196 @@ +#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/repl/lib_random.h b/repl/lib_random.h new file mode 100644 index 0000000..2dfae4d --- /dev/null +++ b/repl/lib_random.h @@ -0,0 +1,7 @@ +#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/repl/repl_main.c b/repl/repl_main.c index 2f601b2..c7249a5 100644 --- a/repl/repl_main.c +++ b/repl/repl_main.c @@ -1,6 +1,7 @@ #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" @@ -29,6 +30,7 @@ void repl(const char* initialInput) { //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); for(;;) { diff --git a/repl/repl_tools.c b/repl/repl_tools.c index 0b46080..e26b861 100644 --- a/repl/repl_tools.c +++ b/repl/repl_tools.c @@ -1,6 +1,7 @@ #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" @@ -112,6 +113,7 @@ void Toy_runBinary(const unsigned char* tb, size_t size) { //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); diff --git a/scripts/small.toy b/scripts/small.toy index e69de29..a9afb07 100644 --- a/scripts/small.toy +++ b/scripts/small.toy @@ -0,0 +1,12 @@ +import standard; +import random; + +for (var i: int = 0; i < 1_000_000; i++) { + var generator: opaque = createRandomGenerator(clock().hash()); + + print generator.generateRandomNumber(); + print generator.generateRandomNumber(); + print generator.generateRandomNumber(); + + generator.freeRandomGenerator(); +} \ No newline at end of file diff --git a/test/scripts/lib/random-stuff.toy b/test/scripts/lib/random-stuff.toy deleted file mode 100644 index e69de29..0000000 diff --git a/test/scripts/lib/random.toy b/test/scripts/lib/random.toy new file mode 100644 index 0000000..b2bf955 --- /dev/null +++ b/test/scripts/lib/random.toy @@ -0,0 +1,17 @@ +import standard; +import random; + +var generator: opaque = createRandomGenerator(clock().hash()); //create a new generator object, from a non-determinant source + +var a: int = generator.generateRandomNumber(); +var b: int = generator.generateRandomNumber(); +var c: int = generator.generateRandomNumber(); + +generator.freeRandomGenerator(); + +assert a != b, "random a != random b failed"; +assert a != c, "random a != random c failed"; +assert b != c, "random b != random c failed"; + + +print "All good"; diff --git a/test/test_libraries.c b/test/test_libraries.c index d850358..dadd25b 100644 --- a/test/test_libraries.c +++ b/test/test_libraries.c @@ -14,6 +14,7 @@ #include "../repl/repl_tools.h" #include "../repl/lib_about.h" +#include "../repl/lib_random.h" #include "../repl/lib_runner.h" #include "../repl/lib_standard.h" @@ -45,30 +46,15 @@ void runBinaryWithLibrary(const unsigned char* tb, size_t size, const char* libr Toy_setInterpreterError(&interpreter, errorWrapper); //inject the standard libraries into this interpreter + if (hook != Toy_hookStandard) { + Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard); + } Toy_injectNativeHook(&interpreter, library, hook); Toy_runInterpreter(&interpreter, tb, size); Toy_freeInterpreter(&interpreter); } -void runBinaryQuietly(const unsigned char* tb, size_t size) { - Toy_Interpreter interpreter; - Toy_initInterpreter(&interpreter); - - //NOTE: supress print output for testing - Toy_setInterpreterPrint(&interpreter, noPrintFn); - Toy_setInterpreterAssert(&interpreter, assertWrapper); - Toy_setInterpreterError(&interpreter, errorWrapper); - - //inject the libs - Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout); - Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard); - Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner); - - Toy_runInterpreter(&interpreter, tb, size); - Toy_freeInterpreter(&interpreter); -} - typedef struct Payload { char* fname; char* libname; @@ -94,6 +80,7 @@ int main() { {"about.toy", "about", Toy_hookAbout}, {"standard.toy", "standard", Toy_hookStandard}, {"runner.toy", "runner", Toy_hookRunner}, + {"random.toy", "random", Toy_hookRandom}, {NULL, NULL, NULL} }; @@ -125,41 +112,6 @@ int main() { } } - { - //run whatever, testing stuff together to check for memory leaks - char* whatever[] = { - "random-stuff.toy", - NULL - }; - - for (int i = 0; whatever[i]; i++) { - printf("Running %s\n", whatever[i]); - - char fname[128]; - snprintf(fname, 128, "scripts/lib/%s", whatever[i]); - - //compile the source - size_t size = 0; - const char* source = (const char*)Toy_readFile(fname, &size); - if (!source) { - printf(TOY_CC_ERROR "Failed to load file: %s\n" TOY_CC_RESET, fname); - failedAsserts++; - continue; - } - - const unsigned char* tb = Toy_compileString(source, &size); - free((void*)source); - - if (!tb) { - printf(TOY_CC_ERROR "Failed to compile file: %s\n" TOY_CC_RESET, fname); - failedAsserts++; - continue; - } - - runBinaryQuietly(tb, size); - } - } - //lib cleanup Toy_freeDriveDictionary(); From 1513ba98783c837464f5777851d26ae2c894f35d Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Thu, 23 Feb 2023 20:23:10 +1100 Subject: [PATCH 4/4] tweaked scripts folder --- scripts/example-entity.toy | 125 ------------------------------------ scripts/example.toy | 89 ------------------------- scripts/level.toy | 6 +- scripts/roguelike-seeds.toy | 36 +++++++++++ scripts/small.toy | 12 ---- 5 files changed, 39 insertions(+), 229 deletions(-) delete mode 100644 scripts/example-entity.toy delete mode 100644 scripts/example.toy create mode 100644 scripts/roguelike-seeds.toy delete mode 100644 scripts/small.toy diff --git a/scripts/example-entity.toy b/scripts/example-entity.toy deleted file mode 100644 index 4206550..0000000 --- a/scripts/example-entity.toy +++ /dev/null @@ -1,125 +0,0 @@ -import node; - -//constants -var SPEED: int const = 10; - -//variables -var parent: opaque = null; -var posX: int = 50; -var posY: int = 50; -var WIDTH: int const = 100; -var HEIGHT: int const = 100; - -var xspeed: int = 0; -var yspeed: int = 0; - -//accessors - variables are private, functions are public -fn getX(node: opaque) { - return posX; -} - -fn getY(node: opaque) { - return posY; -} - -//lifecycle functions -fn onInit(node: opaque) { - print "render.toy:onInit() called\n"; - - node.loadTexture("sprites:/character.png"); - parent = node.getNodeParent(); -} - -fn onStep(node: opaque) { - posX += xspeed; - posY += yspeed; -} - -fn onFree(node: opaque) { - print "render.toy:onFree() called\n"; - - node.freeTexture(); -} - -fn onDraw(node: opaque) { -// print "render.toy:onDraw() called\n"; - - var px = parent.callNode("getX"); - var py = parent.callNode("getY"); - - if (px == null) { - px = 0; - } - - if (py == null) { - py = 0; - } - - node.drawNode(posX + px, posY + py, WIDTH, HEIGHT); -} - -//event functions -fn onKeyDown(node: opaque, event: string) { - if (event == "character_up") { - yspeed -= SPEED; - return; - } - - if (event == "character_down") { - yspeed += SPEED; - return; - } - - if (event == "character_left") { - xspeed -= SPEED; - return; - } - - if (event == "character_right") { - xspeed += SPEED; - return; - } -} - -fn onKeyUp(node: opaque, event: string) { - if (event == "character_up" && yspeed < 0) { - yspeed = 0; - return; - } - - if (event == "character_down" && yspeed > 0) { - yspeed = 0; - return; - } - - if (event == "character_left" && xspeed < 0) { - xspeed = 0; - return; - } - - if (event == "character_right" && xspeed > 0) { - xspeed = 0; - return; - } -} - -fn onMouseMotion(node: opaque, x: int, y: int, xrel: int, yrel: int) { - // print "entity.toy:onMouseMotion(" + string x + ", " + string y + ", " + string xrel + ", " + string yrel + ")\n"; -} - -fn onMouseButtonDown(node: opaque, x: int, y: int, button: string) { - // print "entity.toy:onMouseButtonDown(" + string x + ", " + string y + ", " + button + ")\n"; - - //jump to pos - posX = x - WIDTH / 2; - posY = y - HEIGHT / 2; -} - -fn onMouseButtonUp(node: opaque, x: int, y: int, button: string) { - // print "entity.toy:onMouseButtonUp(" + string x + ", " + string y + ", " + button + ")\n"; -} - -fn onMouseWheel(node: opaque, xrel: int, yrel: int) { - // print "entity.toy:onMouseWheel(" + string xrel + ", " + string yrel + ")\n"; -} - diff --git a/scripts/example.toy b/scripts/example.toy deleted file mode 100644 index 1489908..0000000 --- a/scripts/example.toy +++ /dev/null @@ -1,89 +0,0 @@ -//single line comment - -/* -multi line comment -*/ - -//test primitive literals -print "hello world"; -print null; -print true; -print false; -print 42; -print 3.14; -print -69; -print -4.20; -print 2 + (3 * 3); - -//test operators (integers) -print 1 + 1; -print 1 - 1; -print 2 * 2; -print 1 / 2; -print 4 % 2; - -//test operators (floats) -print 1.0 + 1.0; -print 1.0 - 1.0; -print 2.0 * 2.0; -print 1.0 / 2.0; - -//test scopes -{ - print "This statement is within a scope."; - { - print "This is a deeper scope."; - } -} -print "Back to the outer scope."; - -//test scope will delegate to higher scope -var a = 1; -{ - a = 2; - print a; -} -print a; - -//test scope will shadow higher scope on redefine -var b: int = 3; -{ - var b = 4; - print b; -} -print b; - -//test compounds, repeatedly -print [1, 2, 3]; -print [4, 5]; -print ["key":"value"]; -print [1, 2, 3]; -print [4, 5]; -print ["key":"value"]; - -//test empties -print []; -print [:]; - -//test nested compounds -print [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; - -//var declarations -var x = 31; -var y : int = 42; -var arr : [int] = [1, 2, 3, 42]; -var dict : [string:int] = ["hello": 1, "world":2]; - -//printing expressions -print x; -print x + y; -print arr; -print dict; - -//test asserts at the end of the file -assert x, "This won't be seen"; -assert true, "This won't be seen"; -assert false, "This is a failed assert, and will end execution"; - -print "This will not be printed because of the above assert"; - diff --git a/scripts/level.toy b/scripts/level.toy index 0bf5362..1cf9ac3 100644 --- a/scripts/level.toy +++ b/scripts/level.toy @@ -34,8 +34,8 @@ var tiles: [[int]] const = [ ]; var tileset: [int: string] const = [ - 0: " ", - 1: " X " + 0: " ", + 1: "X " ]; //variables @@ -48,7 +48,7 @@ fn draw() { for (var i: int = 0; i < WIDTH; i++) { //draw the player pos if (i == posX && j == posY) { - print " O "; + print "O "; continue; } diff --git a/scripts/roguelike-seeds.toy b/scripts/roguelike-seeds.toy new file mode 100644 index 0000000..130efe4 --- /dev/null +++ b/scripts/roguelike-seeds.toy @@ -0,0 +1,36 @@ +/* + +Since this is a pseudo-random generator, and there's no internal state to the algorithm other +than the generator opaque, there needs to be a "call counter" (current depth) to shuffle the +initial seeds, otherwise generators created from other generators will resemble their parents, +but one call greater. + +*/ + +import standard; +import random; + +var DEPTH: int const = 20; +var levels = []; + +//generate the level seeds +var generator: opaque = createRandomGenerator(clock().hash()); + +for (var i: int = 0; i < DEPTH; i++) { + levels.push(generator.generateRandomNumber()); +} + +generator.freeRandomGenerator(); + +//generate "levels" of a roguelike +for (var i = 0; i < DEPTH; i++) { + var rng: opaque = createRandomGenerator(levels[i] + i); + + print "---"; + print levels[i]; + print rng.generateRandomNumber(); + print rng.generateRandomNumber(); + print rng.generateRandomNumber(); + + rng.freeRandomGenerator(); +} \ No newline at end of file diff --git a/scripts/small.toy b/scripts/small.toy deleted file mode 100644 index a9afb07..0000000 --- a/scripts/small.toy +++ /dev/null @@ -1,12 +0,0 @@ -import standard; -import random; - -for (var i: int = 0; i < 1_000_000; i++) { - var generator: opaque = createRandomGenerator(clock().hash()); - - print generator.generateRandomNumber(); - print generator.generateRandomNumber(); - print generator.generateRandomNumber(); - - generator.freeRandomGenerator(); -} \ No newline at end of file