major main.c refactoring

- now takes command line arguments:
Usage: ./bin/cosmo [-clsr] [args]

available options are:
-c <in> <out>   compile <in> and dump to <out>
-l <in>         load dump from <in>
-s <in...>              compile and run <in...> script(s)
-r                      start the repl
This commit is contained in:
CPunch 2023-05-28 20:52:12 -05:00
parent 93a09698a9
commit 8c6ba18848
3 changed files with 137 additions and 38 deletions

View File

@ -1,8 +1,8 @@
# make clean && make && ./bin/cosmo # make clean && make && ./bin/cosmo
CC=clang CC=clang
CFLAGS=-fPIE -Wall -O0 -Isrc -std=c99 -g CFLAGS=-fPIE -Wall -O3 -Isrc -std=c99
LDFLAGS=-lm -fsanitize=address LDFLAGS=-lm #-fsanitize=address
OUT=bin/cosmo OUT=bin/cosmo
CHDR=\ CHDR=\

165
main.c
View File

@ -1,21 +1,29 @@
#include "cosmo.h" #include "cbaselib.h"
#include "cchunk.h" #include "cchunk.h"
#include "cdebug.h" #include "cdebug.h"
#include "cvm.h" #include "cdump.h"
#include "cparse.h"
#include "cbaselib.h"
#include "cmem.h" #include "cmem.h"
#include "cosmo.h"
#include "cparse.h"
#include "cundump.h"
#include "cvm.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
static bool _ACTIVE = false; static bool _ACTIVE = false;
int cosmoB_quitRepl(CState *state, int nargs, CValue *args) { int cosmoB_quitRepl(CState *state, int nargs, CValue *args)
{
_ACTIVE = false; _ACTIVE = false;
return 0; // we don't return anything return 0; // we don't return anything
} }
int cosmoB_input(CState *state, int nargs, CValue *args) { int cosmoB_input(CState *state, int nargs, CValue *args)
{
// input() accepts the same params as print()! // input() accepts the same params as print()!
for (int i = 0; i < nargs; i++) { for (int i = 0; i < nargs; i++) {
CObjString *str = cosmoV_toString(state, args[i]); CObjString *str = cosmoV_toString(state, args[i]);
@ -26,12 +34,14 @@ int cosmoB_input(CState *state, int nargs, CValue *args) {
char line[1024]; char line[1024];
fgets(line, sizeof(line), stdin); fgets(line, sizeof(line), stdin);
cosmoV_pushRef(state, (CObj*)cosmoO_copyString(state, line, strlen(line)-1)); // -1 for the \n cosmoV_pushRef(state,
(CObj *)cosmoO_copyString(state, line, strlen(line) - 1)); // -1 for the \n
return 1; // 1 return value return 1; // 1 return value
} }
static bool interpret(CState *state, const char *script, const char *mod) { static bool interpret(CState *state, const char *script, const char *mod)
{
bool ret; bool ret;
// cosmoV_compileString pushes the result onto the stack (COBJ_ERROR or COBJ_CLOSURE) // cosmoV_compileString pushes the result onto the stack (COBJ_ERROR or COBJ_CLOSURE)
@ -50,15 +60,11 @@ static bool interpret(CState *state, const char *script, const char *mod) {
return !ret; return !ret;
} }
static void repl() { static void repl(CState *state)
{
char line[1024]; char line[1024];
_ACTIVE = true; _ACTIVE = true;
CState *state = cosmoV_newState();
cosmoB_loadLibrary(state);
cosmoB_loadOSLib(state);
cosmoB_loadVM(state);
// add our custom REPL functions // add our custom REPL functions
cosmoV_pushString(state, "quit"); cosmoV_pushString(state, "quit");
cosmoV_pushCFunction(state, cosmoB_quitRepl); cosmoV_pushCFunction(state, cosmoB_quitRepl);
@ -78,12 +84,11 @@ static void repl() {
interpret(state, line, "REPL"); interpret(state, line, "REPL");
} }
cosmoV_freeState(state);
} }
static char *readFile(const char* path) { static char *readFile(const char *path)
FILE* file = fopen(path, "rb"); {
FILE *file = fopen(path, "rb");
if (file == NULL) { if (file == NULL) {
fprintf(stderr, "Could not open file \"%s\".\n", path); fprintf(stderr, "Could not open file \"%s\".\n", path);
exit(74); exit(74);
@ -94,7 +99,7 @@ static char *readFile(const char* path) {
size_t fileSize = ftell(file); size_t fileSize = ftell(file);
rewind(file); rewind(file);
char *buffer = (char*)malloc(fileSize + 1); // make room for the null byte char *buffer = (char *)malloc(fileSize + 1); // make room for the null byte
if (buffer == NULL) { if (buffer == NULL) {
fprintf(stderr, "failed to allocate!"); fprintf(stderr, "failed to allocate!");
exit(1); exit(1);
@ -114,12 +119,10 @@ static char *readFile(const char* path) {
return buffer; return buffer;
} }
static bool runFile(const char* fileName) { static bool runFile(CState *state, const char *fileName)
{
bool ret; bool ret;
char* script = readFile(fileName); char *script = readFile(fileName);
CState *state = cosmoV_newState();
cosmoB_loadLibrary(state);
cosmoB_loadOSLib(state);
// add our input() function to the global table // add our input() function to the global table
cosmoV_pushString(state, "input"); cosmoV_pushString(state, "input");
@ -129,21 +132,119 @@ static bool runFile(const char* fileName) {
ret = interpret(state, script, fileName); ret = interpret(state, script, fileName);
cosmoV_freeState(state);
free(script); free(script);
return ret; // let the caller know if the script failed return ret; // let the caller know if the script failed
} }
int main(int argc, const char *argv[]) { int fileWriter(CState *state, const void *data, size_t size, const void *ud)
if (argc == 1) { {
repl(); return !fwrite(data, size, 1, (FILE *)ud);
} else if (argc >= 2) { // they passed a file (or more lol) }
for (int i = 1; i < argc; i++) {
if (!runFile(argv[i])) { int fileReader(CState *state, void *data, size_t size, const void *ud)
{
return fread(data, size, 1, (FILE *)ud) != 1;
}
void compileScript(CState *state, const char *in, const char *out)
{
char *script = readFile(in);
FILE *fout = fopen(out, "wb");
if (cosmoV_compileString(state, script, in)) {
CObjFunction *func = cosmoV_readClosure(*cosmoV_getTop(state, 0))->function;
cosmoD_dump(state, func, fileWriter, (void *)fout);
} else {
cosmoV_pop(state); // pop the error off the stack
cosmoV_printError(state, state->error);
}
free(script);
fclose(fout);
printf("[!] compiled %s to %s successfully!\n", in, out);
}
void loadScript(CState *state, const char *in)
{
FILE *file;
file = fopen(in, "rb");
if (!cosmoV_undump(state, fileReader, file)) {
cosmoV_pop(state); // pop the error off the stack
cosmoV_printError(state, state->error);
return;
};
printf("[!] loaded %s!\n", in);
COSMOVMRESULT res = cosmoV_call(state, 0, 0); // 0 args being passed, 0 results expected
if (res == COSMOVM_RUNTIME_ERR)
cosmoV_printError(state, state->error);
fclose(file);
}
void printUsage(const char *name)
{
printf("Usage: %s [-clsr] [args]\n\n", name);
printf("available options are:\n"
"-c <in> <out>\tcompile <in> and dump to <out>\n"
"-l <in>\t\tload dump from <in>\n"
"-s <in...>\t\tcompile and run <in...> script(s)\n"
"-r\t\t\tstart the repl\n\n");
}
int main(int argc, char *const argv[])
{
CState *state = cosmoV_newState();
cosmoB_loadLibrary(state);
cosmoB_loadOSLib(state);
cosmoB_loadVM(state);
int opt;
bool isValid = false;
while ((opt = getopt(argc, argv, "clsr")) != -1) {
switch (opt) {
case 'c':
if (optind >= argc - 1) {
printf("Usage: %s -c <in> <out>\n", argv[0]);
exit(EXIT_FAILURE);
} else {
compileScript(state, argv[optind], argv[optind + 1]);
}
isValid = true;
break;
case 'l':
if (optind >= argc) {
printf("Usage: %s -l <in>\n", argv[0]);
exit(EXIT_FAILURE);
} else {
loadScript(state, argv[optind]);
}
isValid = true;
break;
case 's':
for (int i = optind; i < argc; i++) {
if (!runFile(state, argv[i])) {
printf("failed to run %s!\n", argv[i]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
isValid = true;
break;
case 'r':
repl(state);
isValid = true;
break;
}
} }
if (!isValid) {
printUsage(argv[0]);
}
cosmoV_freeState(state);
return 0; return 0;
} }

View File

@ -980,6 +980,4 @@ void cosmoB_loadVM(CState *state)
// register "vm" to the global table // register "vm" to the global table
cosmoV_register(state, 1); cosmoV_register(state, 1);
printf("[WARNING] the vm.* library has been loaded!\n");
} }