diff --git a/repl/lib_compound.c b/repl/lib_compound.c index 3a02c77..3e6a681 100644 --- a/repl/lib_compound.c +++ b/repl/lib_compound.c @@ -3,6 +3,7 @@ #include "toy_memory.h" #include +#include static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { //no arguments @@ -13,6 +14,12 @@ static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen //get the argument to a C-string Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); + + Toy_Literal selfLiteralIdn = selfLiteral; + if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { + Toy_freeLiteral(selfLiteralIdn); + } + Toy_RefString* selfRefString = TOY_AS_STRING(selfLiteral); char* self = Toy_toCString(selfRefString); @@ -36,7 +43,7 @@ static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen Toy_freeLiteral(resultLiteral); Toy_freeLiteral(selfLiteral); - return -1; + return 1; } static int nativeToUpper(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { @@ -48,6 +55,12 @@ static int nativeToUpper(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen //get the argument to a C-string Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); + + Toy_Literal selfLiteralIdn = selfLiteral; + if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { + Toy_freeLiteral(selfLiteralIdn); + } + Toy_RefString* selfRefString = TOY_AS_STRING(selfLiteral); char* self = Toy_toCString(selfRefString); @@ -71,7 +84,106 @@ static int nativeToUpper(Toy_Interpreter* interpreter, Toy_LiteralArray* argumen Toy_freeLiteral(resultLiteral); Toy_freeLiteral(selfLiteral); - return -1; + return 1; +} + +static int nativeTrim(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { + if (arguments->count < 1 || arguments->count > 2) { + interpreter->errorOutput("Incorrect number of arguments to clock\n"); + return -1; + } + + //get the arguments + Toy_Literal trimCharsLiteral; + Toy_Literal selfLiteral; + + if (arguments->count == 2) { + trimCharsLiteral = Toy_popLiteralArray(arguments); + } + else { + trimCharsLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(" \t\n\r")); + } + selfLiteral = Toy_popLiteralArray(arguments); + + Toy_Literal selfLiteralIdn = selfLiteral; + if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { + Toy_freeLiteral(selfLiteralIdn); + } + + //unwrap the arguments + Toy_RefString* trimCharsRefString = TOY_AS_STRING(trimCharsLiteral); + Toy_RefString* selfRefString = TOY_AS_STRING(selfLiteral); + + //allocate space for the new string + int bufferBegin = 0; + int bufferEnd = Toy_lengthRefString(selfRefString); + + //for each character in self, check it against each character in trimChars - on a fail, go to end + for (int i = 0; i < Toy_lengthRefString(selfRefString); i++) { + int trimIndex = 0; + + while (trimIndex < Toy_lengthRefString(trimCharsRefString)) { + //there is a match - DON'T increment anymore + if (Toy_toCString(selfRefString)[i] == Toy_toCString(trimCharsRefString)[trimIndex]) { + break; + } + + trimIndex++; + } + + //if the match is found, increment buffer begin + if (trimIndex < Toy_lengthRefString(trimCharsRefString)) { + bufferBegin++; + continue; + } + else { + break; + } + } + + //again, from the back + for (int i = Toy_lengthRefString(selfRefString); i >= 0; i--) { + int trimIndex = 0; + + while (trimIndex < Toy_lengthRefString(trimCharsRefString)) { + //there is a match - DON'T increment anymore + if (Toy_toCString(selfRefString)[i-1] == Toy_toCString(trimCharsRefString)[trimIndex]) { + break; + } + + trimIndex++; + } + + //if the match is found, increment buffer begin + if (trimIndex < Toy_lengthRefString(trimCharsRefString)) { + bufferEnd--; + continue; + } + else { + break; + } + } + + //generate the result + Toy_Literal resultLiteral; + if (bufferBegin >= bufferEnd) { //catch errors + resultLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("")); + } + else { + char buffer[TOY_MAX_STRING_LENGTH]; + snprintf(buffer, bufferEnd - bufferBegin + 1, "%s", &Toy_toCString(selfRefString)[ bufferBegin ]); + resultLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(buffer)); //internal copy + } + + //wrap up the buffer and return it + Toy_pushLiteralArray(&interpreter->stack, resultLiteral); //internal copy + + //cleanup + Toy_freeLiteral(resultLiteral); + Toy_freeLiteral(trimCharsLiteral); + Toy_freeLiteral(selfLiteral); + + return 1; } //call the hook @@ -100,7 +212,7 @@ int Toy_hookCompound(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L {"_toLower", nativeToLower}, //string // {"_toString", native}, //array, dictionary {"_toUpper", nativeToUpper}, //string - // {"_trim", native}, //string + {"_trim", nativeTrim}, //string // {"_values", native}, //dictionary {NULL, NULL} }; diff --git a/repl/lib_runner.c b/repl/lib_runner.c index 6ea1eba..5d4bbd6 100644 --- a/repl/lib_runner.c +++ b/repl/lib_runner.c @@ -26,6 +26,12 @@ static int nativeLoadScript(Toy_Interpreter* interpreter, Toy_LiteralArray* argu //get the file path literal with a handle Toy_Literal drivePathLiteral = Toy_popLiteralArray(arguments); + + Toy_Literal drivePathLiteralIdn = drivePathLiteral; + if (TOY_IS_IDENTIFIER(drivePathLiteral) && Toy_parseIdentifierToValue(interpreter, &drivePathLiteral)) { + Toy_freeLiteral(drivePathLiteralIdn); + } + Toy_Literal filePathLiteral = Toy_getFilePathLiteral(interpreter, &drivePathLiteral); if (TOY_IS_NULL(filePathLiteral)) { @@ -90,6 +96,12 @@ static int nativeLoadScriptBytecode(Toy_Interpreter* interpreter, Toy_LiteralArr //get the argument Toy_Literal drivePathLiteral = Toy_popLiteralArray(arguments); + + Toy_Literal drivePathLiteralIdn = drivePathLiteral; + if (TOY_IS_IDENTIFIER(drivePathLiteral) && Toy_parseIdentifierToValue(interpreter, &drivePathLiteral)) { + Toy_freeLiteral(drivePathLiteralIdn); + } + Toy_RefString* drivePath = Toy_copyRefString(TOY_AS_STRING(drivePathLiteral)); //get the drive and path as a string (can't trust that pesky strtok - custom split) TODO: move this to refstring library diff --git a/repl/repl_main.c b/repl/repl_main.c index 5824045..a68415a 100644 --- a/repl/repl_main.c +++ b/repl/repl_main.c @@ -1,4 +1,5 @@ #include "repl_tools.h" +#include "lib_compound.h" #include "lib_standard.h" #include "lib_timer.h" #include "lib_runner.h" @@ -26,6 +27,7 @@ void repl() { Toy_initInterpreter(&interpreter); //inject the libs + Toy_injectNativeHook(&interpreter, "compound", Toy_hookCompound); Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard); Toy_injectNativeHook(&interpreter, "timer", Toy_hookTimer); Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner); diff --git a/repl/repl_tools.c b/repl/repl_tools.c index 0b67a57..f7e0afc 100644 --- a/repl/repl_tools.c +++ b/repl/repl_tools.c @@ -1,4 +1,5 @@ #include "repl_tools.h" +#include "lib_compound.h" #include "lib_standard.h" #include "lib_timer.h" #include "lib_runner.h" @@ -110,6 +111,7 @@ void Toy_runBinary(unsigned char* tb, size_t size) { Toy_initInterpreter(&interpreter); //inject the libs + Toy_injectNativeHook(&interpreter, "compound", Toy_hookCompound); Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard); Toy_injectNativeHook(&interpreter, "timer", Toy_hookTimer); Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner); diff --git a/test/scripts/lib/compound.toy b/test/scripts/lib/compound.toy index 25fddfa..3d727d1 100644 --- a/test/scripts/lib/compound.toy +++ b/test/scripts/lib/compound.toy @@ -2,12 +2,35 @@ import compound; //test toLower { - assert "Hello World".toLower() == "hello world", "toLower() failed"; + assert "Hello World".toLower() == "hello world", "_toLower() failed"; } //test toUpper { - assert "Hello World".toUpper() == "HELLO WORLD", "toUpper() failed"; + assert "Hello World".toUpper() == "HELLO WORLD", "_toUpper() failed"; +} + +//test trim +{ + //test a bunch + fn test(s, pass) { + var result = s.trim(); + assert result == pass, "_trim(" + result + ") failed"; + } + + test("hello world", "hello world"); + test(" hello world", "hello world"); + test("hello world ", "hello world"); + test(" hello world ", "hello world"); + test(" hello world", "hello world"); + test("hello world ", "hello world"); + test(" hello world ", "hello world"); + test(" hello world", "hello world"); + test("hello world ", "hello world"); + test(" hello world ", "hello world"); + + //one for goot luck + assert " hello world ".trim() == "hello world", "hello world.trim() failed"; } print "All good";