Cosmo/src/main.c

137 lines
3.4 KiB
C
Raw Normal View History

2020-10-28 05:16:30 +00:00
#include "cosmo.h"
#include "cchunk.h"
#include "cdebug.h"
#include "cvm.h"
#include "cparse.h"
#include "cbaselib.h"
#include "cmem.h"
static bool _ACTIVE = false;
2020-10-28 23:38:50 +00:00
int cosmoB_quitRepl(CState *state, int nargs, CValue *args) {
2020-10-28 23:38:50 +00:00
_ACTIVE = false;
return 0; // we don't return anything
2020-10-28 23:38:50 +00:00
}
int cosmoB_input(CState *state, int nargs, CValue *args) {
2020-11-13 02:06:38 +00:00
// input() accepts the same params as print()!
for (int i = 0; i < nargs; i++) {
CObjString *str = cosmoV_toString(state, args[i]);
printf("%s", cosmoO_readCString(str));
}
// but, we return user input instead!
char line[1024];
fgets(line, sizeof(line), stdin);
cosmoV_pushValue(state, cosmoV_newObj(cosmoO_copyString(state, line, strlen(line)-1))); // -1 for the \n
return 1; // 1 return value
2020-11-13 02:06:38 +00:00
}
2020-12-09 18:23:16 +00:00
static void interpret(CState *state, const char *script, const char *mod) {
// cosmoP_compileString pushes the result onto the stack (NIL or COBJ_CLOSURE)
CObjFunction* func = cosmoP_compileString(state, script, mod);
2020-10-28 05:16:30 +00:00
if (func != NULL) {
2020-12-09 18:23:16 +00:00
disasmChunk(&func->chunk, func->name != NULL ? func->name->str : "_main", 0);
2020-10-28 05:16:30 +00:00
COSMOVMRESULT res = cosmoV_call(state, 0, 0); // 0 args being passed, 0 results expected
2020-10-28 05:16:30 +00:00
if (res == COSMOVM_RUNTIME_ERR)
state->panic = false; // so our repl isn't broken
2020-10-28 05:16:30 +00:00
}
}
static void repl() {
char line[1024];
2020-10-28 23:38:50 +00:00
_ACTIVE = true;
2020-10-28 05:16:30 +00:00
2020-10-28 23:38:50 +00:00
CState *state = cosmoV_newState();
2020-11-13 05:04:09 +00:00
cosmoB_loadLibrary(state);
cosmoB_loadDebug(state);
2020-10-28 23:38:50 +00:00
// add our custom REPL functions
cosmoV_pushString(state, "quit");
cosmoV_pushCFunction(state, cosmoB_quitRepl);
cosmoV_pushString(state, "input");
cosmoV_pushCFunction(state, cosmoB_input);
cosmoV_register(state, 2);
2020-10-28 23:38:50 +00:00
while (_ACTIVE) {
2020-10-28 05:16:30 +00:00
printf("> ");
if (!fgets(line, sizeof(line), stdin)) { // better than gets()
printf("\n> ");
break;
}
2020-12-09 18:23:16 +00:00
interpret(state, line, "REPL");
2020-10-28 05:16:30 +00:00
}
2020-10-28 23:38:50 +00:00
cosmoV_freeState(state);
2020-10-28 05:16:30 +00:00
}
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);
}
// first, we need to know how big our file is
fseek(file, 0L, SEEK_END);
size_t fileSize = ftell(file);
rewind(file);
char *buffer = (char*)malloc(fileSize + 1); // make room for the null byte
if (buffer == NULL) {
fprintf(stderr, "failed to allocate!");
exit(1);
}
size_t bytesRead = fread(buffer, sizeof(char), fileSize, file);
if (bytesRead < fileSize) {
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
fclose(file);
return buffer;
}
static void runFile(const char* fileName) {
char* script = readFile(fileName);
2020-10-28 23:38:50 +00:00
CState *state = cosmoV_newState();
2020-11-13 05:04:09 +00:00
cosmoB_loadLibrary(state);
2020-10-28 05:16:30 +00:00
// add our input() function to the global table
cosmoV_pushString(state, "input");
cosmoV_pushCFunction(state, cosmoB_input);
cosmoV_register(state, 1);
2020-12-09 18:23:16 +00:00
interpret(state, script, fileName);
2020-10-28 23:38:50 +00:00
cosmoV_freeState(state);
2020-10-28 05:16:30 +00:00
free(script);
}
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++) {
runFile(argv[i]);
}
}
return 0;
}