From 436bd3ffca1653610f20c7bce3054846c762b68d Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sun, 10 Nov 2024 10:27:50 +1100 Subject: [PATCH] Added silent cmd args Fixed #145 --- repl/main.c | 104 ++++++++++++++++++++++++++++++++++---------- source/toy_parser.c | 20 +++++++-- source/toy_parser.h | 5 +++ source/toy_vm.c | 2 +- 4 files changed, 102 insertions(+), 29 deletions(-) diff --git a/repl/main.c b/repl/main.c index 499fb91..ef8e6a4 100644 --- a/repl/main.c +++ b/repl/main.c @@ -105,6 +105,29 @@ int getFileName(char* dest, const char* src) { return len; } +//callbacks +static void printCallback(const char* msg) { + fprintf(stdout, "%s\n", msg); +} + +static void errorAndExitCallback(const char* msg) { + fprintf(stderr, "%s\n", msg); + exit(-1); +} + +static void errorAndContinueCallback(const char* msg) { + fprintf(stderr, "%s\n", msg); +} + +static void noOpCallback(const char* msg) { + //NO-OP +} + +static void silentExitCallback(const char* msg) { + //NO-OP + exit(-1); +} + //handle command line arguments typedef struct CmdLine { bool error; @@ -112,6 +135,9 @@ typedef struct CmdLine { bool version; char* infile; int infileLength; + bool silentPrint; + bool silentAssert; + bool removeAssert; } CmdLine; void usageCmdLine(int argc, const char* argv[]) { @@ -126,6 +152,9 @@ void helpCmdLine(int argc, const char* argv[]) { printf(" -h, --help\t\t\tShow this help then exit.\n"); printf(" -v, --version\t\t\tShow version and copyright information then exit.\n"); printf(" -f, --file infile\t\tParse, compile and execute the source file then exit.\n"); + printf(" --silent-print\t\tSuppress output from the print keyword.\n"); + printf(" --silent-assert\t\tSuppress output from the assert keyword.\n"); + printf(" --remove-assert\t\tDo not include the assert statement in the bytecode.\n"); } void versionCmdLine(int argc, const char* argv[]) { @@ -155,7 +184,16 @@ freely, subject to the following restrictions:\n\ } CmdLine parseCmdLine(int argc, const char* argv[]) { - CmdLine cmd = { .error = false, .help = false, .version = false, .infile = NULL, .infileLength = 0 }; + CmdLine cmd = { + .error = false, + .help = false, + .version = false, + .infile = NULL, + .infileLength = 0, + .silentPrint = false, + .silentAssert = false, + .removeAssert = false + }; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { @@ -192,6 +230,18 @@ CmdLine parseCmdLine(int argc, const char* argv[]) { } } + else if (!strcmp(argv[i], "--silent-print")) { + cmd.silentPrint = true; + } + + else if (!strcmp(argv[i], "--silent-assert")) { + cmd.silentAssert = true; + } + + else if (!strcmp(argv[i], "--remove-assert")) { + cmd.removeAssert = true; + } + else { cmd.error = true; } @@ -201,13 +251,21 @@ CmdLine parseCmdLine(int argc, const char* argv[]) { } //repl function -static void errorAndContinueCallback(const char* msg) { - fprintf(stderr, "%s\n", msg); -} +int repl(const char* filepath, CmdLine cmd) { + //output options + if (cmd.silentPrint) { + Toy_setPrintCallback(noOpCallback); + } + else { + Toy_setPrintCallback(printCallback); + } -int repl(const char* filepath) { - Toy_setErrorCallback(errorAndContinueCallback); - Toy_setAssertFailureCallback(errorAndContinueCallback); + if (cmd.silentAssert) { + Toy_setAssertFailureCallback(silentExitCallback); + } + else { + Toy_setAssertFailureCallback(errorAndContinueCallback); + } //vars to use char prompt[256]; @@ -246,6 +304,7 @@ int repl(const char* filepath) { Toy_bindLexer(&lexer, inputBuffer); Toy_Parser parser; Toy_bindParser(&parser, &lexer); + Toy_configureParser(&parser, cmd.removeAssert); Toy_Ast* ast = Toy_scanParser(&bucket, &parser); //Ast is in the bucket, so it doesn't need to be freed //parsing error, retry @@ -403,30 +462,25 @@ static void debugScopePrint(Toy_Scope* scope, int depth) { } } -//callbacks -static void printCallback(const char* msg) { - fprintf(stdout, "%s\n", msg); -} - -static void errorAndExitCallback(const char* msg) { - fprintf(stderr, "%s\n", msg); - exit(-1); -} - //main file int main(int argc, const char* argv[]) { - Toy_setPrintCallback(printCallback); + Toy_setPrintCallback(noOpCallback); Toy_setErrorCallback(errorAndExitCallback); Toy_setAssertFailureCallback(errorAndExitCallback); - //repl - if (argc == 1) { - return repl(argv[0]); - } - //if there's args, process them CmdLine cmd = parseCmdLine(argc, argv); + //output options + if (cmd.silentPrint) { + Toy_setPrintCallback(noOpCallback); + } + + if (cmd.silentAssert) { + Toy_setAssertFailureCallback(silentExitCallback); + } + + //process if (cmd.error) { usageCmdLine(argc, argv); } @@ -470,6 +524,8 @@ int main(int argc, const char* argv[]) { Toy_Parser parser; Toy_bindParser(&parser, &lexer); + Toy_configureParser(&parser, cmd.removeAssert); + Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); Toy_Ast* ast = Toy_scanParser(&bucket, &parser); @@ -493,7 +549,7 @@ int main(int argc, const char* argv[]) { free(source); } else { - usageCmdLine(argc, argv); + repl(argv[0], cmd); } return 0; diff --git a/source/toy_parser.c b/source/toy_parser.c index daeb123..ec77d9c 100644 --- a/source/toy_parser.c +++ b/source/toy_parser.c @@ -659,12 +659,18 @@ static void makeAssertStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_As Toy_Ast* ast = NULL; //assert's emit function is a bit different makeExpr(bucketHandle, parser, &ast); - //NOTE: if it's a compound, then it's got a second arg - if (ast->type == TOY_AST_COMPOUND) { - Toy_private_emitAstAssert(bucketHandle, rootHandle, ast->compound.left, ast->compound.right); + //if assert is disabled, don't emit the assert + if (parser->removeAssert) { + Toy_private_emitAstPass(bucketHandle, rootHandle); } else { - Toy_private_emitAstAssert(bucketHandle, rootHandle, ast, NULL); + //NOTE: if it's a compound, then it's got a second arg + if (ast->type == TOY_AST_COMPOUND) { + Toy_private_emitAstAssert(bucketHandle, rootHandle, ast->compound.left, ast->compound.right); + } + else { + Toy_private_emitAstAssert(bucketHandle, rootHandle, ast, NULL); + } } consume(parser, TOY_TOKEN_OPERATOR_SEMICOLON, "Expected ';' at the end of assert statement"); @@ -836,4 +842,10 @@ void Toy_resetParser(Toy_Parser* parser) { parser->error = false; parser->panic = false; + + parser->removeAssert = false; } + +void Toy_configureParser(Toy_Parser* parser, bool removeAssert) { + parser->removeAssert = removeAssert; +} \ No newline at end of file diff --git a/source/toy_parser.h b/source/toy_parser.h index 823e78a..52e32fc 100644 --- a/source/toy_parser.h +++ b/source/toy_parser.h @@ -14,9 +14,14 @@ typedef struct Toy_Parser { bool error; bool panic; //currently processing an error + + //configs + bool removeAssert; } Toy_Parser; TOY_API void Toy_bindParser(Toy_Parser* parser, Toy_Lexer* lexer); TOY_API Toy_Ast* Toy_scanParser(Toy_Bucket** bucketHandle, Toy_Parser* parser); TOY_API void Toy_resetParser(Toy_Parser* parser); +//configure certain options +TOY_API void Toy_configureParser(Toy_Parser* parser, bool removeAssert); diff --git a/source/toy_vm.c b/source/toy_vm.c index d8c25ce..b765f4b 100644 --- a/source/toy_vm.c +++ b/source/toy_vm.c @@ -372,7 +372,7 @@ static void processAssert(Toy_VM* vm) { //do the check if (TOY_VALUE_IS_NULL(value) || Toy_checkValueIsTruthy(value) == false) { //on a failure, print the message - Toy_stringifyValue(message, Toy_error); + Toy_stringifyValue(message, Toy_assertFailure); } //cleanup