mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
100
repl/main.c
100
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);
|
||||
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;
|
||||
|
||||
@@ -659,6 +659,11 @@ 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);
|
||||
|
||||
//if assert is disabled, don't emit the assert
|
||||
if (parser->removeAssert) {
|
||||
Toy_private_emitAstPass(bucketHandle, rootHandle);
|
||||
}
|
||||
else {
|
||||
//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);
|
||||
@@ -666,6 +671,7 @@ static void makeAssertStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_As
|
||||
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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user