diff --git a/repl/lib_standard.c b/repl/lib_standard.c index 1c333db..ebfb0a3 100644 --- a/repl/lib_standard.c +++ b/repl/lib_standard.c @@ -439,48 +439,49 @@ static int nativeClamp(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments return -1; } - //get the max + //get the arguments Toy_Literal maxLiteral = Toy_popLiteralArray(arguments); - - //parse the max - Toy_Literal maxLiteralIdn = maxLiteral; - if (TOY_IS_IDENTIFIER(maxLiteral) && Toy_parseIdentifierToValue(interpreter, &maxLiteral)) { - Toy_freeLiteral(maxLiteralIdn); - } - - if (!(TOY_IS_INTEGER(maxLiteral) || TOY_IS_FLOAT(maxLiteral))) { - interpreter->errorOutput("Incorrect argument type passed to clamp\n"); - Toy_freeLiteral(maxLiteral); - return -1; - } - - //get the min Toy_Literal minLiteral = Toy_popLiteralArray(arguments); - - //parse the min - Toy_Literal minLiteralIdn = minLiteral; - if (TOY_IS_IDENTIFIER(minLiteral) && Toy_parseIdentifierToValue(interpreter, &minLiteral)) { - Toy_freeLiteral(minLiteralIdn); - } - - if (!(TOY_IS_INTEGER(minLiteral) || TOY_IS_FLOAT(minLiteral))) { - interpreter->errorOutput("Incorrect argument type passed to clamp\n"); - Toy_freeLiteral(minLiteral); - return -1; - } - - //get the value Toy_Literal valueLiteral = Toy_popLiteralArray(arguments); - //parse the value + //parse the arguments (if they're identifiers) Toy_Literal valueLiteralIdn = valueLiteral; if (TOY_IS_IDENTIFIER(valueLiteral) && Toy_parseIdentifierToValue(interpreter, &valueLiteral)) { Toy_freeLiteral(valueLiteralIdn); } + Toy_Literal minLiteralIdn = minLiteral; + if (TOY_IS_IDENTIFIER(minLiteral) && Toy_parseIdentifierToValue(interpreter, &minLiteral)) { + Toy_freeLiteral(minLiteralIdn); + } + + Toy_Literal maxLiteralIdn = maxLiteral; + if (TOY_IS_IDENTIFIER(maxLiteral) && Toy_parseIdentifierToValue(interpreter, &maxLiteral)) { + Toy_freeLiteral(maxLiteralIdn); + } + + //check the types if (!(TOY_IS_INTEGER(valueLiteral) || TOY_IS_FLOAT(valueLiteral))) { interpreter->errorOutput("Incorrect argument type passed to clamp\n"); Toy_freeLiteral(valueLiteral); + Toy_freeLiteral(minLiteral); + Toy_freeLiteral(maxLiteral); + return -1; + } + + if (!(TOY_IS_INTEGER(minLiteral) || TOY_IS_FLOAT(minLiteral))) { + interpreter->errorOutput("Incorrect argument type passed to clamp\n"); + Toy_freeLiteral(valueLiteral); + Toy_freeLiteral(minLiteral); + Toy_freeLiteral(maxLiteral); + return -1; + } + + if (!(TOY_IS_INTEGER(maxLiteral) || TOY_IS_FLOAT(maxLiteral))) { + interpreter->errorOutput("Incorrect argument type passed to clamp\n"); + Toy_freeLiteral(valueLiteral); + Toy_freeLiteral(minLiteral); + Toy_freeLiteral(maxLiteral); return -1; } @@ -489,18 +490,24 @@ static int nativeClamp(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments float min = TOY_IS_INTEGER(minLiteral)? TOY_AS_INTEGER(minLiteral) : TOY_AS_FLOAT(minLiteral); float max = TOY_IS_INTEGER(maxLiteral)? TOY_AS_INTEGER(maxLiteral) : TOY_AS_FLOAT(maxLiteral); - float result = (value < min)? min : value; - if (result > max) result = max; + //determine which literal to return (this way, we retain the original type) + if (min > value) { + Toy_pushLiteralArray(&interpreter->stack, minLiteral); + } - Toy_Literal resultLiteral = TOY_TO_FLOAT_LITERAL(result); - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); + else if (max < value) { + Toy_pushLiteralArray(&interpreter->stack, maxLiteral); + } + + else { + Toy_pushLiteralArray(&interpreter->stack, valueLiteral); + } - Toy_freeLiteral(resultLiteral); Toy_freeLiteral(valueLiteral); Toy_freeLiteral(minLiteral); Toy_freeLiteral(maxLiteral); - - return 1; + + return 1; } static int nativeLerp(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { @@ -509,48 +516,49 @@ static int nativeLerp(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) return -1; } - //get the amount + //get the arguments Toy_Literal amountLiteral = Toy_popLiteralArray(arguments); - - //parse the amount - Toy_Literal amountLiteralIdn = amountLiteral; - if (TOY_IS_IDENTIFIER(amountLiteral) && Toy_parseIdentifierToValue(interpreter, &amountLiteral)) { - Toy_freeLiteral(amountLiteralIdn); - } - - if (!(TOY_IS_INTEGER(amountLiteral) || TOY_IS_FLOAT(amountLiteral))) { - interpreter->errorOutput("Incorrect argument type passed to lerp\n"); - Toy_freeLiteral(amountLiteral); - return -1; - } - - //get the end Toy_Literal endLiteral = Toy_popLiteralArray(arguments); - - //parse the end - Toy_Literal endLiteralIdn = endLiteral; - if (TOY_IS_IDENTIFIER(endLiteral) && Toy_parseIdentifierToValue(interpreter, &endLiteral)) { - Toy_freeLiteral(endLiteralIdn); - } - - if (!(TOY_IS_INTEGER(endLiteral) || TOY_IS_FLOAT(endLiteral))) { - interpreter->errorOutput("Incorrect argument type passed to lerp\n"); - Toy_freeLiteral(endLiteral); - return -1; - } - - //get the value Toy_Literal startLiteral = Toy_popLiteralArray(arguments); - //parse the value + //parse the arguments (if they're identifiers) Toy_Literal startLiteralIdn = startLiteral; if (TOY_IS_IDENTIFIER(startLiteral) && Toy_parseIdentifierToValue(interpreter, &startLiteral)) { Toy_freeLiteral(startLiteralIdn); } + Toy_Literal endLiteralIdn = endLiteral; + if (TOY_IS_IDENTIFIER(endLiteral) && Toy_parseIdentifierToValue(interpreter, &endLiteral)) { + Toy_freeLiteral(endLiteralIdn); + } + + Toy_Literal amountLiteralIdn = amountLiteral; + if (TOY_IS_IDENTIFIER(amountLiteral) && Toy_parseIdentifierToValue(interpreter, &amountLiteral)) { + Toy_freeLiteral(amountLiteralIdn); + } + + //check the argument types if (!(TOY_IS_INTEGER(startLiteral) || TOY_IS_FLOAT(startLiteral))) { interpreter->errorOutput("Incorrect argument type passed to lerp\n"); Toy_freeLiteral(startLiteral); + Toy_freeLiteral(endLiteral); + Toy_freeLiteral(amountLiteral); + return -1; + } + + if (!(TOY_IS_INTEGER(endLiteral) || TOY_IS_FLOAT(endLiteral))) { + interpreter->errorOutput("Incorrect argument type passed to lerp\n"); + Toy_freeLiteral(startLiteral); + Toy_freeLiteral(endLiteral); + Toy_freeLiteral(amountLiteral); + return -1; + } + + if (!(TOY_IS_INTEGER(amountLiteral) || TOY_IS_FLOAT(amountLiteral))) { + interpreter->errorOutput("Incorrect argument type passed to lerp\n"); + Toy_freeLiteral(startLiteral); + Toy_freeLiteral(endLiteral); + Toy_freeLiteral(amountLiteral); return -1; } @@ -559,17 +567,20 @@ static int nativeLerp(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) float end = TOY_IS_INTEGER(endLiteral)? TOY_AS_INTEGER(endLiteral) : TOY_AS_FLOAT(endLiteral); float amount = TOY_IS_INTEGER(amountLiteral)? TOY_AS_INTEGER(amountLiteral) : TOY_AS_FLOAT(amountLiteral); + //calculate the result float result = start + amount * (end - start); + //return the result Toy_Literal resultLiteral = TOY_TO_FLOAT_LITERAL(result); Toy_pushLiteralArray(&interpreter->stack, resultLiteral); + //cleanup Toy_freeLiteral(resultLiteral); Toy_freeLiteral(startLiteral); Toy_freeLiteral(endLiteral); Toy_freeLiteral(amountLiteral); - - return 1; + + return 1; } static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { diff --git a/test/scripts/lib/standard.toy b/test/scripts/lib/standard.toy index a273878..ab50ff4 100644 --- a/test/scripts/lib/standard.toy +++ b/test/scripts/lib/standard.toy @@ -133,6 +133,31 @@ import standard; } +//test clamp +{ + assert clamp(1, 0, 5) == 1, "clamp(1, 0, 5) failed"; + assert clamp(0, 1, 5) == 1, "clamp(0, 1, 5) failed"; + assert clamp(10, 1, 5) == 5, "clamp(10, 1, 5) failed"; + + assert clamp(1.0, 0.0, 5.0) == 1, "clamp(1.0, 0.0, 5.0) failed"; + assert clamp(0.0, 1.0, 5.0) == 1, "clamp(0.0, 1.0, 5.0) failed"; + assert clamp(10.0, 1.0, 5.0) == 5, "clamp(10.0, 1.0, 5.0) failed"; + + assert typeof clamp(10, 1, 5) == int, "typeof clamp(10, 1, 5) == int failed"; + assert typeof clamp(10.0, 1, 5) == int, "typeof clamp(10.0, 1, 5) == int failed"; + assert typeof clamp(10, 1, 5.0) == float, "typeof clamp(10, 1, 5.0) == float failed"; +} + + +//test lerp +{ + assert lerp(0, 10, 0.5) == 5, "lerp 50% failed"; + assert lerp(0, 10, 1.5) == 15, "lerp 150% failed"; + + assert typeof lerp(0, 10, 0) == float, "typeof lerp result failed"; +} + + //test concat { //test array concat