mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
100
repl/main.c
100
repl/main.c
@@ -105,6 +105,29 @@ int getFileName(char* dest, const char* src) {
|
|||||||
return len;
|
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
|
//handle command line arguments
|
||||||
typedef struct CmdLine {
|
typedef struct CmdLine {
|
||||||
bool error;
|
bool error;
|
||||||
@@ -112,6 +135,9 @@ typedef struct CmdLine {
|
|||||||
bool version;
|
bool version;
|
||||||
char* infile;
|
char* infile;
|
||||||
int infileLength;
|
int infileLength;
|
||||||
|
bool silentPrint;
|
||||||
|
bool silentAssert;
|
||||||
|
bool removeAssert;
|
||||||
} CmdLine;
|
} CmdLine;
|
||||||
|
|
||||||
void usageCmdLine(int argc, const char* argv[]) {
|
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(" -h, --help\t\t\tShow this help then exit.\n");
|
||||||
printf(" -v, --version\t\t\tShow version and copyright information 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(" -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[]) {
|
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 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++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
|
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 {
|
else {
|
||||||
cmd.error = true;
|
cmd.error = true;
|
||||||
}
|
}
|
||||||
@@ -201,13 +251,21 @@ CmdLine parseCmdLine(int argc, const char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//repl function
|
//repl function
|
||||||
static void errorAndContinueCallback(const char* msg) {
|
int repl(const char* filepath, CmdLine cmd) {
|
||||||
fprintf(stderr, "%s\n", msg);
|
//output options
|
||||||
|
if (cmd.silentPrint) {
|
||||||
|
Toy_setPrintCallback(noOpCallback);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Toy_setPrintCallback(printCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
int repl(const char* filepath) {
|
if (cmd.silentAssert) {
|
||||||
Toy_setErrorCallback(errorAndContinueCallback);
|
Toy_setAssertFailureCallback(silentExitCallback);
|
||||||
|
}
|
||||||
|
else {
|
||||||
Toy_setAssertFailureCallback(errorAndContinueCallback);
|
Toy_setAssertFailureCallback(errorAndContinueCallback);
|
||||||
|
}
|
||||||
|
|
||||||
//vars to use
|
//vars to use
|
||||||
char prompt[256];
|
char prompt[256];
|
||||||
@@ -246,6 +304,7 @@ int repl(const char* filepath) {
|
|||||||
Toy_bindLexer(&lexer, inputBuffer);
|
Toy_bindLexer(&lexer, inputBuffer);
|
||||||
Toy_Parser parser;
|
Toy_Parser parser;
|
||||||
Toy_bindParser(&parser, &lexer);
|
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
|
Toy_Ast* ast = Toy_scanParser(&bucket, &parser); //Ast is in the bucket, so it doesn't need to be freed
|
||||||
|
|
||||||
//parsing error, retry
|
//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
|
//main file
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
Toy_setPrintCallback(printCallback);
|
Toy_setPrintCallback(noOpCallback);
|
||||||
Toy_setErrorCallback(errorAndExitCallback);
|
Toy_setErrorCallback(errorAndExitCallback);
|
||||||
Toy_setAssertFailureCallback(errorAndExitCallback);
|
Toy_setAssertFailureCallback(errorAndExitCallback);
|
||||||
|
|
||||||
//repl
|
|
||||||
if (argc == 1) {
|
|
||||||
return repl(argv[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if there's args, process them
|
//if there's args, process them
|
||||||
CmdLine cmd = parseCmdLine(argc, argv);
|
CmdLine cmd = parseCmdLine(argc, argv);
|
||||||
|
|
||||||
|
//output options
|
||||||
|
if (cmd.silentPrint) {
|
||||||
|
Toy_setPrintCallback(noOpCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd.silentAssert) {
|
||||||
|
Toy_setAssertFailureCallback(silentExitCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
//process
|
||||||
if (cmd.error) {
|
if (cmd.error) {
|
||||||
usageCmdLine(argc, argv);
|
usageCmdLine(argc, argv);
|
||||||
}
|
}
|
||||||
@@ -470,6 +524,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
Toy_Parser parser;
|
Toy_Parser parser;
|
||||||
Toy_bindParser(&parser, &lexer);
|
Toy_bindParser(&parser, &lexer);
|
||||||
|
|
||||||
|
Toy_configureParser(&parser, cmd.removeAssert);
|
||||||
|
|
||||||
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
||||||
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
|
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
|
||||||
|
|
||||||
@@ -493,7 +549,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
free(source);
|
free(source);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
usageCmdLine(argc, argv);
|
repl(argv[0], cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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
|
Toy_Ast* ast = NULL; //assert's emit function is a bit different
|
||||||
makeExpr(bucketHandle, parser, &ast);
|
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
|
//NOTE: if it's a compound, then it's got a second arg
|
||||||
if (ast->type == TOY_AST_COMPOUND) {
|
if (ast->type == TOY_AST_COMPOUND) {
|
||||||
Toy_private_emitAstAssert(bucketHandle, rootHandle, ast->compound.left, ast->compound.right);
|
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 {
|
else {
|
||||||
Toy_private_emitAstAssert(bucketHandle, rootHandle, ast, NULL);
|
Toy_private_emitAstAssert(bucketHandle, rootHandle, ast, NULL);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
consume(parser, TOY_TOKEN_OPERATOR_SEMICOLON, "Expected ';' at the end of assert statement");
|
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->error = false;
|
||||||
parser->panic = 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 error;
|
||||||
bool panic; //currently processing an error
|
bool panic; //currently processing an error
|
||||||
|
|
||||||
|
//configs
|
||||||
|
bool removeAssert;
|
||||||
} Toy_Parser;
|
} Toy_Parser;
|
||||||
|
|
||||||
TOY_API void Toy_bindParser(Toy_Parser* parser, Toy_Lexer* lexer);
|
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 Toy_Ast* Toy_scanParser(Toy_Bucket** bucketHandle, Toy_Parser* parser);
|
||||||
TOY_API void Toy_resetParser(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
|
//do the check
|
||||||
if (TOY_VALUE_IS_NULL(value) || Toy_checkValueIsTruthy(value) == false) {
|
if (TOY_VALUE_IS_NULL(value) || Toy_checkValueIsTruthy(value) == false) {
|
||||||
//on a failure, print the message
|
//on a failure, print the message
|
||||||
Toy_stringifyValue(message, Toy_error);
|
Toy_stringifyValue(message, Toy_assertFailure);
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
|
|||||||
Reference in New Issue
Block a user