Files

189 lines
4.6 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "wl.h"
typedef struct FileData FileData;
struct FileData {
FileData *next;
int size;
char data[];
};
FileData *load_file(WL_String path)
{
char buf[1<<10];
if (path.len >= (int) sizeof(buf))
return NULL;
memcpy(buf, path.ptr, path.len);
buf[path.len] = '\0';
FILE *f = fopen(buf, "rb");
if (f == NULL)
return NULL;
fseek(f, 0, SEEK_END);
long size = ftell(f);
fseek(f, 0, SEEK_SET);
FileData *data = malloc(sizeof(FileData) + size);
if (data == NULL) {
fclose(f);
return NULL;
}
data->size = size;
data->next = NULL;
fread(data->data, 1, size, f);
fclose(f);
return data;
}
int main(int argc, char **argv)
{
char *entry_file = NULL;
bool bc = false;
bool ast = false;
bool run = true;
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "--bc"))
bc = true;
else if (!strcmp(argv[i], "--ast"))
ast = true;
else if (!strcmp(argv[i], "--no-run"))
run = false;
else
entry_file = argv[i];
}
if (entry_file == NULL) {
fprintf(stderr, "Usage: %s file.wl\n", argv[0]);
return -1;
}
int cap = 1<<20;
char *mem = malloc(cap);
if (mem == NULL) {
fprintf(stderr, "Error: Allocation failure\n");
return -1;
}
WL_Arena arena = { mem, cap, 0 };
WL_Program program;
{
WL_Compiler *c = wl_compiler_init(&arena);
if (c == NULL) {
fprintf(stderr, "Error: Out of memory");
return -1;
}
FileData *file_head;
FileData **file_tail = &file_head;
WL_String path = { entry_file, strlen(entry_file) };
for (;;) {
FileData *file = load_file(path);
if (file == NULL) {
printf("Couldn't open '%.*s'\n", path.len, path.ptr);
return -1;
}
*file_tail = file;
file_tail = &file->next;
WL_AddResult res = wl_compiler_add(c, path, (WL_String) { file->data, file->size });
if (res.type == WL_ADD_ERROR) {
fprintf(stderr, "Error: %s\n", wl_compiler_error(c).ptr);
return -1;
}
if (res.type == WL_ADD_AGAIN) {
path = res.path;
continue;
}
assert(res.type == WL_ADD_LINK);
break;
}
*file_tail = NULL;
if (ast) {
char buf[1<<10];
int len = wl_dump_ast(c, buf, sizeof(buf));
if (len > sizeof(buf)-1)
len = sizeof(buf)-1;
buf[len] = '\0';
printf("%s\n", buf);
}
int ret = wl_compiler_link(c, &program);
if (ret < 0) {
WL_String err = wl_compiler_error(c);
fprintf(stderr, "Error: %s\n", err.ptr);
return -1;
}
if (bc)
wl_dump_program(program);
FileData *file = file_head;
while (file) {
FileData *next = file->next;
free(file);
file = next;
}
}
if (run) {
WL_Runtime *rt = wl_runtime_init(&arena, program);
if (rt == NULL) {
fprintf(stderr, "Error: Invalid program or out of memory\n");
return -1;
}
FILE *output = stdout;
for (bool done = false; !done; ) {
WL_EvalResult res = wl_runtime_eval(rt);
//wl_runtime_dump(rt);
switch (res.type) {
case WL_EVAL_NONE:
break;
case WL_EVAL_DONE:
done = true;
break;
case WL_EVAL_ERROR:
printf("Error: %s\n", wl_runtime_error(rt).ptr);
return -1;
case WL_EVAL_OUTPUT:
fwrite(res.str.ptr, 1, res.str.len, output);
break;
case WL_EVAL_SYSVAR:
if (wl_streq(res.str, "varA", -1)) wl_push_s64(rt, 1);
if (wl_streq(res.str, "varB", -1)) wl_push_s64(rt, 7);
if (wl_streq(res.str, "varC", -1)) wl_push_s64(rt, 13);
break;
case WL_EVAL_SYSCALL:
if (wl_streq(res.str, "testfn", -1)) {
for (int i = 0; i < wl_arg_count(rt); i++)
wl_push_arg(rt, i);
}
break;
}
}
}
return 0;
}