diff --git a/repl/lib_standard.c b/repl/lib_standard.c index 9e4836f..3d55fb7 100644 --- a/repl/lib_standard.c +++ b/repl/lib_standard.c @@ -47,11 +47,6 @@ static int nativeHash(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) 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); @@ -77,11 +72,6 @@ static int nativeAbs(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) 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); @@ -120,11 +110,6 @@ static int nativeCeil(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) 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); @@ -164,11 +149,6 @@ static int nativeFloor(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments 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); @@ -208,11 +188,6 @@ static int nativeMax(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) 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); @@ -269,11 +244,6 @@ static int nativeMin(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) 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); @@ -330,11 +300,6 @@ static int nativeRound(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments 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); @@ -365,6 +330,109 @@ static int nativeRound(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments return 1; } +static int nativeSign(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { + if (arguments->count != 1) { + interpreter->errorOutput("Incorrect number of arguments to sign\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_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) { + interpreter->errorOutput("Incorrect argument type passed to sign\n"); + Toy_freeLiteral(selfLiteral); + return -1; + } + + Toy_Literal resultLiteral = TOY_TO_NULL_LITERAL; + + if (TOY_IS_INTEGER(selfLiteral)) { + if (TOY_AS_INTEGER(selfLiteral) < 0) { + resultLiteral = TOY_TO_INTEGER_LITERAL(-1); + } + else { + resultLiteral = TOY_TO_INTEGER_LITERAL(1); + } + } + if (TOY_IS_FLOAT(selfLiteral)) { + if (TOY_AS_FLOAT(selfLiteral) < 0) { + resultLiteral = TOY_TO_INTEGER_LITERAL(-1); + } + else { + resultLiteral = TOY_TO_INTEGER_LITERAL(1); + } + } + + Toy_pushLiteralArray(&interpreter->stack, resultLiteral); + + Toy_freeLiteral(resultLiteral); + Toy_freeLiteral(selfLiteral); + + return 1; +} + +static int nativeNormalize(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { + //NOTE: this is identical to `sign`, except it returns 0 when the argument is 0. + if (arguments->count != 1) { + interpreter->errorOutput("Incorrect number of arguments to normalize\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_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) { + interpreter->errorOutput("Incorrect argument type passed to normalize\n"); + Toy_freeLiteral(selfLiteral); + return -1; + } + + Toy_Literal resultLiteral = TOY_TO_NULL_LITERAL; + + if (TOY_IS_INTEGER(selfLiteral)) { + if (TOY_AS_INTEGER(selfLiteral) < 0) { + resultLiteral = TOY_TO_INTEGER_LITERAL(-1); + } + else if (TOY_AS_INTEGER(selfLiteral) > 0) { + resultLiteral = TOY_TO_INTEGER_LITERAL(1); + } + else { + resultLiteral = TOY_TO_INTEGER_LITERAL(0); + } + } + if (TOY_IS_FLOAT(selfLiteral)) { + if (TOY_AS_FLOAT(selfLiteral) < 0) { + resultLiteral = TOY_TO_INTEGER_LITERAL(-1); + } + else if (TOY_AS_FLOAT(selfLiteral) > 0) { + resultLiteral = TOY_TO_INTEGER_LITERAL(1); + } + else { + resultLiteral = TOY_TO_INTEGER_LITERAL(0); + } + } + + Toy_pushLiteralArray(&interpreter->stack, resultLiteral); + + Toy_freeLiteral(resultLiteral); + Toy_freeLiteral(selfLiteral); + + return 1; +} + static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { //no arguments if (arguments->count != 2) { @@ -387,12 +455,6 @@ static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* argument 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)) { @@ -503,12 +565,6 @@ static int nativeContainsKey(Toy_Interpreter* interpreter, Toy_LiteralArray* arg 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"); @@ -554,12 +610,6 @@ static int nativeContainsValue(Toy_Interpreter* interpreter, Toy_LiteralArray* a 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"); @@ -630,12 +680,6 @@ static int nativeEvery(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments 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"); @@ -752,12 +796,6 @@ static int nativeFilter(Toy_Interpreter* interpreter, Toy_LiteralArray* argument 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"); @@ -872,12 +910,6 @@ static int nativeForEach(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen 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"); @@ -950,11 +982,6 @@ static int nativeGetKeys(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen 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"); @@ -1000,11 +1027,6 @@ static int nativeGetValues(Toy_Interpreter* interpreter, Toy_LiteralArray* argum 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"); @@ -1057,12 +1079,6 @@ static int nativeIndexOf(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen 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"); @@ -1110,12 +1126,6 @@ static int nativeMap(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) 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"); @@ -1225,13 +1235,6 @@ static int nativeReduce(Toy_Interpreter* interpreter, Toy_LiteralArray* argument 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"); @@ -1327,12 +1330,6 @@ static int nativeSome(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) 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"); @@ -1997,6 +1994,8 @@ int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L {"max", nativeMax}, {"min", nativeMin}, {"round", nativeRound}, + {"sign", nativeSign}, + {"normalize", nativeNormalize}, //compound utils {"concat", nativeConcat}, //array, dictionary, string diff --git a/source/toy_common.h b/source/toy_common.h index 5d09295..7d8b621 100644 --- a/source/toy_common.h +++ b/source/toy_common.h @@ -64,7 +64,7 @@ The current patch version of Toy. This value is embedded into the bytecode. This value MUST fit into an unsigned char. !*/ -#define TOY_VERSION_PATCH 0 +#define TOY_VERSION_PATCH 1 /*! ### TOY_VERSION_BUILD diff --git a/test/scripts/lib/standard.toy b/test/scripts/lib/standard.toy index 8d64d36..a273878 100644 --- a/test/scripts/lib/standard.toy +++ b/test/scripts/lib/standard.toy @@ -101,6 +101,38 @@ import standard; } +//test sign +{ + assert sign(4) == 1, "sign(int) failed"; + assert sign(-4) == -1, "sign(-int) failed"; + assert sign(4.1) == 1, "sign(float) failed"; + assert sign(-4.1) == -1, "sign(-float) failed"; + assert sign(0) == 1, "sign(0) failed"; + + var x = 4.1; + + assert x.sign() == 1, "var.sign() failed"; + + assert typeof sign(1.0) == int, "typeof sign() == int failed"; +} + + +//test normalize +{ + assert normalize(4) == 1, "normalize(int) failed"; + assert normalize(-4) == -1, "normalize(-int) failed"; + assert normalize(4.1) == 1, "normalize(float) failed"; + assert normalize(-4.1) == -1, "normalize(-float) failed"; + assert normalize(0) == 0, "normalize(0) failed"; + + var x = 4.1; + + assert x.normalize() == 1, "var.normalize() failed"; + + assert typeof normalize(1.0) == int, "typeof normalize() == int failed"; +} + + //test concat { //test array concat