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 committed by cpunch
parent c44dc88972
commit 9537a2c7b8
3 changed files with 137 additions and 38 deletions

View File

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

169
main.c
View File

@ -1,21 +1,29 @@
#include "cosmo.h"
#include "cbaselib.h"
#include "cchunk.h"
#include "cdebug.h"
#include "cvm.h"
#include "cparse.h"
#include "cbaselib.h"
#include "cdump.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;
int cosmoB_quitRepl(CState *state, int nargs, CValue *args) {
int cosmoB_quitRepl(CState *state, int nargs, CValue *args)
{
_ACTIVE = false;
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()!
for (int i = 0; i < nargs; i++) {
CObjString *str = cosmoV_toString(state, args[i]);
@ -26,16 +34,18 @@ int cosmoB_input(CState *state, int nargs, CValue *args) {
char line[1024];
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
}
static bool interpret(CState *state, const char *script, const char *mod) {
static bool interpret(CState *state, const char *script, const char *mod)
{
bool ret;
// cosmoV_compileString pushes the result onto the stack (COBJ_ERROR or COBJ_CLOSURE)
if (cosmoV_compileString(state, script, mod)) {
if (cosmoV_compileString(state, script, mod)) {
COSMOVMRESULT res = cosmoV_call(state, 0, 0); // 0 args being passed, 0 results expected
if (res == COSMOVM_RUNTIME_ERR)
@ -50,15 +60,11 @@ static bool interpret(CState *state, const char *script, const char *mod) {
return !ret;
}
static void repl() {
static void repl(CState *state)
{
char line[1024];
_ACTIVE = true;
CState *state = cosmoV_newState();
cosmoB_loadLibrary(state);
cosmoB_loadOSLib(state);
cosmoB_loadVM(state);
// add our custom REPL functions
cosmoV_pushString(state, "quit");
cosmoV_pushCFunction(state, cosmoB_quitRepl);
@ -78,12 +84,11 @@ static void repl() {
interpret(state, line, "REPL");
}
cosmoV_freeState(state);
}
static char *readFile(const char* path) {
FILE* file = fopen(path, "rb");
static char *readFile(const char *path)
{
FILE *file = fopen(path, "rb");
if (file == NULL) {
fprintf(stderr, "Could not open file \"%s\".\n", path);
exit(74);
@ -94,7 +99,7 @@ static char *readFile(const char* path) {
size_t fileSize = ftell(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) {
fprintf(stderr, "failed to allocate!");
exit(1);
@ -106,7 +111,7 @@ static char *readFile(const char* path) {
printf("failed to read file \"%s\"!\n", path);
exit(74);
}
buffer[bytesRead] = '\0'; // place our null terminator
// close the file handler and return the script buffer
@ -114,12 +119,10 @@ static char *readFile(const char* path) {
return buffer;
}
static bool runFile(const char* fileName) {
static bool runFile(CState *state, const char *fileName)
{
bool ret;
char* script = readFile(fileName);
CState *state = cosmoV_newState();
cosmoB_loadLibrary(state);
cosmoB_loadOSLib(state);
char *script = readFile(fileName);
// add our input() function to the global table
cosmoV_pushString(state, "input");
@ -129,21 +132,119 @@ static bool runFile(const char* fileName) {
ret = interpret(state, script, fileName);
cosmoV_freeState(state);
free(script);
return ret; // let the caller know if the script failed
}
int main(int argc, const char *argv[]) {
if (argc == 1) {
repl();
} else if (argc >= 2) { // they passed a file (or more lol)
for (int i = 1; i < argc; i++) {
if (!runFile(argv[i])) {
int fileWriter(CState *state, const void *data, size_t size, const void *ud)
{
return !fwrite(data, size, 1, (FILE *)ud);
}
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);
}
}
isValid = true;
break;
case 'r':
repl(state);
isValid = true;
break;
}
}
if (!isValid) {
printUsage(argv[0]);
}
cosmoV_freeState(state);
return 0;
}

View File

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