From f9b154c12ee520b47525c0ff066d3efb0a4ec178 Mon Sep 17 00:00:00 2001 From: Ratstail91 Date: Mon, 27 Feb 2023 22:09:46 +1100 Subject: [PATCH] Moved polyfills into standard library --- Toy | 2 +- assets/scripts/init.toy | 2 +- assets/scripts/tilemap/layer-background.toy | 47 +-- assets/scripts/tilemap/layer-walls.toy | 48 +-- assets/scripts/tilemap/tilemap.toy | 41 +-- box/lib_standard.c | 364 +++++++++++++++++--- 6 files changed, 352 insertions(+), 152 deletions(-) diff --git a/Toy b/Toy index e243ad9..c5c0122 160000 --- a/Toy +++ b/Toy @@ -1 +1 @@ -Subproject commit e243ad949a822044a6d5710b7390e1a48b784dff +Subproject commit c5c01222437ca24556c3dd2181221b2ce5c7ded9 diff --git a/assets/scripts/init.toy b/assets/scripts/init.toy index 73c724c..eddaf2c 100644 --- a/assets/scripts/init.toy +++ b/assets/scripts/init.toy @@ -28,4 +28,4 @@ mapInputEventToKeyUp("character_right", "right"); //event, keysym initWindow("Airport Game", 1080, 720, false); //kick off the logic of the scene graph -loadRootNode("scripts:/frames.toy"); +loadRootNode("scripts:/scene.toy"); diff --git a/assets/scripts/tilemap/layer-background.toy b/assets/scripts/tilemap/layer-background.toy index 9e8c904..1a4cd20 100644 --- a/assets/scripts/tilemap/layer-background.toy +++ b/assets/scripts/tilemap/layer-background.toy @@ -5,11 +5,11 @@ import node; var childCounter: int = 0; //TODO: reference these from a global source (root?) -var tileWidth: float const = 100; -var tileHeight: float const = 100; +var tileWidth: int const = 100; +var tileHeight: int const = 100; -var roomWidth: float const = 10; -var roomHeight: float const = 10; +var roomWidth: int const = 10; +var roomHeight: int const = 10; var levelXCount: int const = 4; var levelYCount: int const = 4; @@ -40,16 +40,16 @@ fn drawLayer(node: opaque, camX, camY, camW, camH, depth) { //calc the modifier ratio to offset things var mod: float = float tileWidth / (tileWidth - depth); - var tileWidth_mod = round(tileWidth * mod); - var tileHeight_mod = round(tileHeight * mod); - var camX_mod = (camX - camW) * mod + camW / 2; - var camY_mod = (camY - camH) * mod + camH / 2; + var tileWidth_mod: int = round(tileWidth * mod); + var tileHeight_mod: int = round(tileHeight * mod); + var camX_mod: int = round((camX - camW) * mod + camW / 2); + var camY_mod: int = round((camY - camH) * mod + camH / 2); //calc the region to render - var lowerX = round((camX - camW/2) / tileWidth); - var upperX = round((camX - camW*1.5) / tileWidth); - var lowerY = round((camY - camH/2) / tileHeight); - var upperY = round((camY - camH*1.5) / tileHeight); + var lowerX: int = round((camX - camW/2) / tileWidth); + var upperX: int = round((camX - camW*1.5) / tileWidth); + var lowerY: int = round((camY - camH/2) / tileHeight); + var upperY: int = round((camY - camH*1.5) / tileHeight); //bounds check lowerX = max(0, abs(lowerX)); @@ -64,26 +64,3 @@ fn drawLayer(node: opaque, camX, camY, camW, camH, depth) { } } } - -//math utils -fn round(x): int { - var f = floor(x); - return x - f >= 0.5 ? f + 1 : f; -} - -fn floor(x): int { - return int x; -} - -fn ceil(x): int { - var f = floor(x); - return x - f != 0 ? f + 1 : f; -} - -fn min(a, b) { - return a < b ? a : b; -} - -fn max(a, b) { - return a > b ? a : b; -} \ No newline at end of file diff --git a/assets/scripts/tilemap/layer-walls.toy b/assets/scripts/tilemap/layer-walls.toy index afef670..4e5af7f 100644 --- a/assets/scripts/tilemap/layer-walls.toy +++ b/assets/scripts/tilemap/layer-walls.toy @@ -5,11 +5,11 @@ import node; var childCounter: int = 0; //TODO: reference these from a global source (root?) -var tileWidth: float const = 100; -var tileHeight: float const = 100; +var tileWidth: int const = 100; +var tileHeight: int const = 100; -var roomWidth: float const = 10; -var roomHeight: float const = 10; +var roomWidth: int const = 10; +var roomHeight: int const = 10; var levelXCount: int const = 4; var levelYCount: int const = 4; @@ -40,16 +40,16 @@ fn drawLayer(node: opaque, camX, camY, camW, camH, depth) { //calc the modifier ratio to offset things var mod: float = float tileWidth / (tileWidth - depth); - var tileWidth_mod = round(tileWidth * mod); - var tileHeight_mod = round(tileHeight * mod); - var camX_mod = (camX - camW) * mod + camW / 2; - var camY_mod = (camY - camH) * mod + camH / 2; + var tileWidth_mod: int = round(tileWidth * mod); + var tileHeight_mod: int = round(tileHeight * mod); + var camX_mod: int = round((camX - camW) * mod + camW / 2); + var camY_mod: int = round((camY - camH) * mod + camH / 2); //calc the region to render - var lowerX = round((camX - camW/2) / tileWidth); - var upperX = round((camX - camW*1.5) / tileWidth); - var lowerY = round((camY - camH/2) / tileHeight); - var upperY = round((camY - camH*1.5) / tileHeight); + var lowerX: int = round((camX - camW/2) / tileWidth); + var upperX: int = round((camX - camW*1.5) / tileWidth); + var lowerY: int = round((camY - camH/2) / tileHeight); + var upperY: int = round((camY - camH*1.5) / tileHeight); //bounds check lowerX = max(0, abs(lowerX)); @@ -68,27 +68,3 @@ fn drawLayer(node: opaque, camX, camY, camW, camH, depth) { } } } - - -//math utils -fn round(x): int { - var f = floor(x); - return x - f >= 0.5 ? f + 1 : f; -} - -fn floor(x): int { - return int x; -} - -fn ceil(x): int { - var f = floor(x); - return x - f != 0 ? f + 1 : f; -} - -fn min(a, b) { - return a < b ? a : b; -} - -fn max(a, b) { - return a > b ? a : b; -} \ No newline at end of file diff --git a/assets/scripts/tilemap/tilemap.toy b/assets/scripts/tilemap/tilemap.toy index 092ed67..30f69ed 100644 --- a/assets/scripts/tilemap/tilemap.toy +++ b/assets/scripts/tilemap/tilemap.toy @@ -5,21 +5,21 @@ import node; //TODO: get child count var childCounter: int = 0; -var levelXCount: int const = 4; -var levelYCount: int const = 4; - var camX: float = 0; var camY: float = 0; //TODO: reference these from a global source (root?) -var tileWidth: float const = 100; -var tileHeight: float const = 100; +var tileWidth: int const = 100; +var tileHeight: int const = 100; -var roomWidth: float const = 10; -var roomHeight: float const = 10; +var roomWidth: int const = 10; +var roomHeight: int const = 10; -var screenWidth: float = 1080; -var screenHeight: float = 720; +var levelXCount: int const = 4; +var levelYCount: int const = 4; + +var screenWidth: int const = 1080; +var screenHeight: int const = 720; //util to generate and init a child node of a given parent @@ -53,26 +53,3 @@ fn onDraw(node: opaque) { node.getChildNode(c).callNodeFn("drawLayer", camX, camY, screenWidth, screenHeight, c * 2); } } - -//math utils -fn round(x): int { - var f = floor(x); - return x - f >= 0.5 ? f + 1 : f; -} - -fn floor(x): int { - return int x; -} - -fn ceil(x): int { - var f = floor(x); - return x - f != 0 ? f + 1 : f; -} - -fn min(a, b) { - return a < b ? a : b; -} - -fn max(a, b) { - return a > b ? a : b; -} \ No newline at end of file diff --git a/box/lib_standard.c b/box/lib_standard.c index 4375488..2b2966d 100644 --- a/box/lib_standard.c +++ b/box/lib_standard.c @@ -7,6 +7,61 @@ #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"); @@ -50,27 +105,262 @@ static int nativeAbs(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) return 1; } -static int nativeClock(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { - //no arguments - if (arguments->count != 0) { - interpreter->errorOutput("Incorrect number of arguments to clock\n"); +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 time from C (what a pain) - time_t rawtime = time(NULL); - struct tm* timeinfo = localtime( &rawtime ); - char* timestr = asctime(timeinfo); + //get the self + Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); - //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)); + //parse to value if needed + Toy_Literal selfLiteralIdn = selfLiteral; + if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { + Toy_freeLiteral(selfLiteralIdn); + } - //push to the stack - Toy_pushLiteralArray(&interpreter->stack, timeLiteral); + if (TOY_IS_IDENTIFIER(selfLiteral)) { + Toy_freeLiteral(selfLiteral); + return -1; + } - //cleanup - Toy_freeLiteral(timeLiteral); + 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) == 0) { + result = 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; } @@ -745,36 +1035,6 @@ 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) { @@ -1740,8 +2000,19 @@ typedef struct Natives { int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) { //build the natives list Natives natives[] = { - {"abs", nativeAbs}, + //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 @@ -1750,7 +2021,6 @@ 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