diff --git a/wren/.gitignore b/wren/.gitignore new file mode 100644 index 0000000..5d2a44d --- /dev/null +++ b/wren/.gitignore @@ -0,0 +1,5 @@ +*.a +*.o +aoc.c +wren_aoc +wren.h \ No newline at end of file diff --git a/wren/Build.moon b/wren/Build.moon new file mode 100644 index 0000000..8040605 --- /dev/null +++ b/wren/Build.moon @@ -0,0 +1,24 @@ +var CC: 'gcc' +var CFLAGS: '-Wall', '-Wextra', '-Werror' +var LDFLAGS: '-lm' + +with public default target 'all' + \depends 'wren_aoc' + +with public target 'wren_aoc' + \depends 'main.o', 'aoc.o', 'libwren.a' + \produces '%' + \fn => _.cmd CC, CFLAGS, @infiles, '-o', @outfile, LDFLAGS + +with target {'main.o', 'aoc.o'}, pattern: '%.o' + \depends '%.c' + \produces '%.o' + \fn => _.cmd CC, CFLAGS, @infile, '-o', @outfile, '-c' + +with target 'aoc.c' + \depends 'aoc.wren' + \produces '%' + \fn => + code = _.readfile @infile + c_code = "extern const char* aoc_mod = \"#{code\gsub('"', '\\"')\gsub('\n', '\\n')}\";\n" + _.writefile @outfile, c_code \ No newline at end of file diff --git a/wren/aoc.wren b/wren/aoc.wren new file mode 100644 index 0000000..20b26cf --- /dev/null +++ b/wren/aoc.wren @@ -0,0 +1,3 @@ +class AoC { + foreign static input +} diff --git a/wren/main.c b/wren/main.c new file mode 100644 index 0000000..52e0fca --- /dev/null +++ b/wren/main.c @@ -0,0 +1,117 @@ +#include +#include +#include + +#include "wren.h" + +extern char* aoc_mod; + +char* read_file(const char* path) { + FILE* fp = fopen(path, "rb"); + if(fp == NULL) return NULL; + + fseek(fp, 0, SEEK_END); + size_t len = ftell(fp); + fseek(fp, 0, SEEK_SET); + + char* out = calloc(len + 1, 1); + if(out == NULL) { + fclose(fp); + return NULL; + } + + if(len != fread(out, 1, len, fp)) { + fclose(fp); + free(out); + return NULL; + } + + fclose(fp); + return out; +} + +void writeFn(WrenVM* vm, const char* text) { + (void)(vm); + printf("%s", text); +} + +void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) { + (void)(vm); + switch (errorType) { + case WREN_ERROR_COMPILE: + printf("[%s line %d] [Error] %s\n", module, line, msg); + break; + case WREN_ERROR_STACK_TRACE: + printf("[%s line %d] in %s\n", module, line, msg); + break; + case WREN_ERROR_RUNTIME: + printf("[Runtime Error] %s\n", msg); + break; + } +} + +void load_input(WrenVM* vm) { + char* data = read_file("input.txt"); + if(data != NULL) { + wrenSetSlotString(vm, 0, data); + free(data); + } else { + wrenSetSlotNull(vm, 0); + } +} + +WrenForeignMethodFn bindForeignMethodFn(WrenVM* vm, const char* module, const char* className, bool isStatic, const char* signature) { + (void)(vm); + if(!strcmp(module, "aoc") && !strcmp(className, "AoC") && isStatic && !strcmp(signature, "input")) { + return &load_input; + } + return NULL; +} + +WrenLoadModuleResult loadModuleFn(WrenVM* vm, const char* name) { + (void)(vm); + WrenLoadModuleResult result = {0}; + if(!strcmp(name, "aoc")) { + result.source = aoc_mod; + } + return result; +} + +int main(int argc, char** argv) { + (void)(argc); + int exit_code = 0; + + if(argv[1] == NULL) { + fprintf(stderr, "Syntax: %s \n", argv[0]); + return 1; + } + + char* code = read_file(argv[1]); + if(code == NULL) { + fprintf(stderr, "Couldn't load file\n"); + return 1; + } + + WrenConfiguration config; + wrenInitConfiguration(&config); + + config.writeFn = &writeFn; + config.errorFn = &errorFn; + config.loadModuleFn = &loadModuleFn; + config.bindForeignMethodFn = &bindForeignMethodFn; + + WrenVM* vm = wrenNewVM(&config); + WrenInterpretResult result = wrenInterpret(vm, "main", code); + free(code); + + if(result == WREN_RESULT_COMPILE_ERROR) { + fprintf(stderr, "Wren exited with compile error\n"); + exit_code = 1; + } else if(result == WREN_RESULT_RUNTIME_ERROR) { + fprintf(stderr, "Wren exited with runtime error\n"); + exit_code = 1; + } + + wrenFreeVM(vm); + return exit_code; +} \ No newline at end of file