Basic infile reading is working, untested

This commit is contained in:
2024-09-28 12:26:42 +10:00
parent 3d1d3b3b77
commit 57fb1ece81
6 changed files with 198 additions and 16 deletions

View File

@@ -1,11 +1,89 @@
#include "toy_memory.h"
#include "toy.h"
#include <stdio.h>
#include <string.h>
//handle command line arguments
typedef struct CmdLine {
bool error;
bool help;
bool version;
const char* infile;
} CmdLine;
void usageCmdLine(int argc, const char* argv[]) {
printf("Usage: %s [ -h | -v | -f source.toy ]\n\n", argv[0]);
}
void helpCmdLine(int argc, const char* argv[]) {
usageCmdLine(argc, 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");
}
void versionCmdLine(int argc, const char* argv[]) {
printf("The Toy Programming Language, Version %d.%d.%d %s\n\n", TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, TOY_VERSION_BUILD);
//copy/pasted from the license file - there's a way to include it directly, but it's too finnicky to bother
const char* license = "\
Copyright (c) 2020-2024 Kayne Ruse, KR Game Studios\n\
\n\
This software is provided 'as-is', without any express or implied\n\
warranty. In no event will the authors be held liable for any damages\n\
arising from the use of this software.\n\
\n\
Permission is granted to anyone to use this software for any purpose,\n\
including commercial applications, and to alter it and redistribute it\n\
freely, subject to the following restrictions:\n\
\n\
1. The origin of this software must not be misrepresented; you must not\n\
claim that you wrote the original software. If you use this software\n\
in a product, an acknowledgment in the product documentation would be\n\
appreciated but is not required.\n\
2. Altered source versions must be plainly marked as such, and must not be\n\
misrepresented as being the original software.\n\
3. This notice may not be removed or altered from any source distribution.\n\n";
printf(license);
}
CmdLine parseCmdLine(int argc, const char* argv[]) {
CmdLine cmd = { .error = false, .help = false, .version = false, .infile = NULL };
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
cmd.help = true;
}
else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
cmd.version = true;
}
else if (!strcmp(argv[i], "-f") || !strcmp(argv[i], "--file")) {
if (argc < i + 1) {
cmd.error = true;
}
else {
cmd.infile = argv[++i];
}
}
else {
cmd.error = true;
}
}
return cmd;
}
//utilities
unsigned char* readFile(const char* path, int* size) {
//open the file
FILE* file = fopen(path, "rb");
if (file == NULL) {
*size = -1; //missing file error
return NULL;
}
@@ -24,7 +102,7 @@ unsigned char* readFile(const char* path, int* size) {
//
if (fread(buffer, sizeof(unsigned char), *size, file) < *size) {
fclose(file);
*size = -1; //singal a read error
*size = -2; //singal a read error
return NULL;
}
@@ -32,21 +110,120 @@ unsigned char* readFile(const char* path, int* size) {
return buffer;
}
void dir(char* dest, const char* src) {
//extract the directory from src, and store it in dest
const char* p = strrchr(src, '/');
int len = p != NULL ? p - src + 1 : 0;
strncpy(dest, src, len);
dest[len] = '\0';
}
int main(int argc, char* argv[]) {
int size = 0;
unsigned char* buffer = readFile("../repl/main.c", &size); //for now, just grab the main.c file as a test
#define APPEND(dest, src) \
sprintf(dest + strlen(dest), src)
if (buffer == NULL) {
fprintf(stderr, "Failed to open the file\n");
//main file
int main(int argc, const char* argv[]) {
CmdLine cmd = parseCmdLine(argc, argv);
if (cmd.error) {
usageCmdLine(argc, argv);
}
else if (cmd.help) {
helpCmdLine(argc, argv);
}
else if (cmd.version) {
versionCmdLine(argc, argv);
}
else if (cmd.infile != NULL) {
//run the given file
int size;
unsigned char* source = readFile(cmd.infile, &size);
//check the file
if (source == NULL) {
if (size == 0) {
fprintf(stderr, TOY_CC_ERROR "ERROR: Could not parse an empty file, exiting\n" TOY_CC_RESET);
return -1;
}
else if (size == -1) {
fprintf(stderr, TOY_CC_ERROR "ERROR: File not found, exiting\n" TOY_CC_RESET);
return -1;
}
else {
fprintf(stderr, TOY_CC_ERROR "ERROR: Unknown error while reading file, exiting\n" TOY_CC_RESET);
return -1;
}
}
Toy_Lexer lexer;
Toy_bindLexer(&lexer, (char*)source);
Toy_Parser parser;
Toy_bindParser(&parser, &lexer);
Toy_Bucket* bucket = NULL;
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
Toy_Bytecode bc = Toy_compileBytecode(ast);
//run the setup
Toy_VM vm;
Toy_initVM(&vm);
Toy_bindVM(&vm, bc.ptr, bc.capacity);
//run
Toy_runVM(&vm);
//debugging result
printf("printing the stack result\n\ntype\tvalue\n");
for (int i = 0; i < vm.stack.count; i++) {
Toy_Value v = vm.stack.ptr[i];
printf(" %d\t ", v.type);
switch(v.type) {
case TOY_VALUE_NULL:
printf("null");
break;
case TOY_VALUE_BOOLEAN:
printf("%s", TOY_VALUE_AS_BOOLEAN(v) ? "true" : "false");
break;
case TOY_VALUE_INTEGER:
printf("%d", TOY_VALUE_AS_INTEGER(v));
break;
case TOY_VALUE_FLOAT:
printf("%f", TOY_VALUE_AS_FLOAT(v));
break;
case TOY_VALUE_STRING:
case TOY_VALUE_ARRAY:
case TOY_VALUE_DICTIONARY:
case TOY_VALUE_FUNCTION:
case TOY_VALUE_OPAQUE:
printf("???");
break;
}
printf("\n");
}
//cleanup
Toy_freeVM(&vm);
TOY_BUCKET_FREE(bucket);
TOY_FREE_ARRAY(unsigned char, source, size);
}
else {
usageCmdLine(argc, argv);
}
if (size < 0) {
fprintf(stderr, "Failed to read the file\n");
}
TOY_FREE_ARRAY(unsigned char, buffer, size);
printf("All good\n");
return 0;
}
//TODO: simple and consistent way to print an AST and Toy_Value