From 4fe57f9562f07b37e81d1ac2951fc95a971fc1b5 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 10 Feb 2023 15:27:39 +0000 Subject: [PATCH] Added _containsKey() and _containsValue() --- repl/lib_compound.c | 129 ++++++++++++++++++++++++++++++++-- scripts/small.toy | 11 +-- test/scripts/lib/compound.toy | 21 ++++++ 3 files changed, 148 insertions(+), 13 deletions(-) diff --git a/repl/lib_compound.c b/repl/lib_compound.c index dc2d1e0..6fb5c45 100644 --- a/repl/lib_compound.c +++ b/repl/lib_compound.c @@ -115,6 +115,121 @@ static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* argument return -1; } +static int nativeContainsKey(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { + //no arguments + if (arguments->count != 2) { + interpreter->errorOutput("Incorrect number of arguments to _containsKey\n"); + return -1; + } + + //get the args + Toy_Literal keyLiteral = Toy_popLiteralArray(arguments); + 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); + } + + Toy_Literal keyLiteralIdn = keyLiteral; + if (TOY_IS_IDENTIFIER(keyLiteral) && Toy_parseIdentifierToValue(interpreter, &keyLiteral)) { + Toy_freeLiteral(keyLiteralIdn); + } + + //check type + if (!(/* TOY_IS_ARRAY(selfLiteral) || */ TOY_IS_DICTIONARY(selfLiteral) )) { + interpreter->errorOutput("Incorrect argument type passed to _containsKey\n"); + Toy_freeLiteral(selfLiteral); + Toy_freeLiteral(keyLiteral); + return -1; + } + + Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(false); + if (TOY_IS_DICTIONARY(selfLiteral) && Toy_existsLiteralDictionary( TOY_AS_DICTIONARY(selfLiteral), keyLiteral )) { + //return true of it contains the key + Toy_freeLiteral(resultLiteral); + resultLiteral = TOY_TO_BOOLEAN_LITERAL(true); + } + Toy_pushLiteralArray(&interpreter->stack, resultLiteral); + Toy_freeLiteral(resultLiteral); + + Toy_freeLiteral(selfLiteral); + Toy_freeLiteral(keyLiteral); + + return 1; +} + +static int nativeContainsValue(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { + //no arguments + if (arguments->count != 2) { + interpreter->errorOutput("Incorrect number of arguments to _containsValue\n"); + return -1; + } + + //get the args + Toy_Literal valueLiteral = Toy_popLiteralArray(arguments); + 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); + } + + Toy_Literal valueLiteralIdn = valueLiteral; + if (TOY_IS_IDENTIFIER(valueLiteral) && Toy_parseIdentifierToValue(interpreter, &valueLiteral)) { + Toy_freeLiteral(valueLiteralIdn); + } + + //check type + if (!( TOY_IS_ARRAY(selfLiteral) || TOY_IS_DICTIONARY(selfLiteral) )) { + interpreter->errorOutput("Incorrect argument type passed to _containsValue\n"); + Toy_freeLiteral(selfLiteral); + Toy_freeLiteral(valueLiteral); + return -1; + } + + Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(false); + if (TOY_IS_DICTIONARY(selfLiteral)) { + for (int i = 0; i < TOY_AS_DICTIONARY(selfLiteral)->capacity; i++) { + if (!TOY_IS_NULL(TOY_AS_DICTIONARY(selfLiteral)->entries[i].key) && Toy_literalsAreEqual( TOY_AS_DICTIONARY(selfLiteral)->entries[i].value, valueLiteral )) { + //return true of it contains the value + Toy_freeLiteral(resultLiteral); + resultLiteral = TOY_TO_BOOLEAN_LITERAL(true); + break; + } + } + } + else if (TOY_IS_ARRAY(selfLiteral)) { + for (int i = 0; i < TOY_AS_ARRAY(selfLiteral)->count; i++) { + Toy_Literal indexLiteral = TOY_TO_INTEGER_LITERAL(i); + Toy_Literal elementLiteral = Toy_getLiteralArray(TOY_AS_ARRAY(selfLiteral), indexLiteral); + + + if (Toy_literalsAreEqual(elementLiteral, valueLiteral)) { + Toy_freeLiteral(indexLiteral); + Toy_freeLiteral(elementLiteral); + + //return true of it contains the value + Toy_freeLiteral(resultLiteral); + resultLiteral = TOY_TO_BOOLEAN_LITERAL(true); + break; + } + + Toy_freeLiteral(indexLiteral); + Toy_freeLiteral(elementLiteral); + } + } + Toy_pushLiteralArray(&interpreter->stack, resultLiteral); + Toy_freeLiteral(resultLiteral); + + Toy_freeLiteral(selfLiteral); + Toy_freeLiteral(valueLiteral); + + return 1; +} + static int nativeEvery(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { //no arguments if (arguments->count != 2) { @@ -141,6 +256,7 @@ static int nativeEvery(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments 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"); Toy_freeLiteral(selfLiteral); + Toy_freeLiteral(fnLiteral); return -1; } @@ -227,7 +343,7 @@ static int nativeEvery(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments Toy_freeLiteral(fnLiteral); Toy_freeLiteral(selfLiteral); - return 0; + return 1; } static int nativeForEach(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { @@ -256,6 +372,7 @@ static int nativeForEach(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen 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"); Toy_freeLiteral(selfLiteral); + Toy_freeLiteral(fnLiteral); return -1; } @@ -424,6 +541,7 @@ static int nativeMap(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) 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"); Toy_freeLiteral(selfLiteral); + Toy_freeLiteral(fnLiteral); return -1; } @@ -532,6 +650,8 @@ static int nativeReduce(Toy_Interpreter* interpreter, Toy_LiteralArray* argument 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"); Toy_freeLiteral(selfLiteral); + Toy_freeLiteral(defaultLiteral); + Toy_freeLiteral(fnLiteral); return -1; } @@ -625,6 +745,7 @@ static int nativeSome(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) 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"); Toy_freeLiteral(selfLiteral); + Toy_freeLiteral(fnLiteral); return -1; } @@ -711,7 +832,7 @@ static int nativeSome(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) Toy_freeLiteral(fnLiteral); Toy_freeLiteral(selfLiteral); - return 0; + return 1; } static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { @@ -1158,8 +1279,8 @@ int Toy_hookCompound(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L //build the natives list Natives natives[] = { {"_concat", nativeConcat}, //array, dictionary, string - // {"_containsKey", native}, //dictionary - // {"_containsValue", native}, //array, dictionary + {"_containsKey", nativeContainsKey}, //dictionary + {"_containsValue", nativeContainsValue}, //array, dictionary {"_every", nativeEvery}, //array, dictionary // {"_filter", native}, //array, dictionary {"_forEach", nativeForEach}, //array, dictionary diff --git a/scripts/small.toy b/scripts/small.toy index 3a5666d..602d440 100644 --- a/scripts/small.toy +++ b/scripts/small.toy @@ -3,13 +3,6 @@ import compound; var a = [false, false, false]; var d = ["one": false, "two": false]; -fn f(k, v) { return v; } +print d.containsKey("one"); +print d.containsKey("three"); -print a.some(f); -print d.some(f); - -a[1] = true; -d["two"] = true; - -print a.some(f); -print d.some(f); diff --git a/test/scripts/lib/compound.toy b/test/scripts/lib/compound.toy index 3609aa8..c6d2de5 100644 --- a/test/scripts/lib/compound.toy +++ b/test/scripts/lib/compound.toy @@ -46,6 +46,27 @@ import compound; } +//test containsKey +{ + var d = ["one": 1, "two": 2]; + + assert d.containsKey("one") == true, "dictionary.containsKey() == true failed"; + assert d.containsKey("three") == false, "dictionary.containsKey() == false failed"; +} + + +//test containsValue +{ + var a = [1, 2, 3]; + var d = ["one": 1, "two": 2]; + + assert a.containsValue(1) == true, "array.containsValue() == true failed"; + assert a.containsValue(5) == false, "array.containsValue() == false failed"; + assert d.containsValue(1) == true, "dictionary.containsValue() == true failed"; + assert d.containsValue(3) == false, "dictionary.containsValue() == false failed"; +} + + //test every { var a = [1, 2, 3];