mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-05 08:10:05 +00:00
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:
parent
93a09698a9
commit
8c6ba18848
4
Makefile
4
Makefile
@ -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=\
|
||||||
|
169
main.c
169
main.c
@ -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,16 +34,18 @@ 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)
|
||||||
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
|
COSMOVMRESULT res = cosmoV_call(state, 0, 0); // 0 args being passed, 0 results expected
|
||||||
|
|
||||||
if (res == COSMOVM_RUNTIME_ERR)
|
if (res == COSMOVM_RUNTIME_ERR)
|
||||||
@ -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);
|
||||||
@ -106,7 +111,7 @@ static char *readFile(const char* path) {
|
|||||||
printf("failed to read file \"%s\"!\n", path);
|
printf("failed to read file \"%s\"!\n", path);
|
||||||
exit(74);
|
exit(74);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[bytesRead] = '\0'; // place our null terminator
|
buffer[bytesRead] = '\0'; // place our null terminator
|
||||||
|
|
||||||
// close the file handler and return the script buffer
|
// close the file handler and return the script buffer
|
||||||
@ -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);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -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");
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user