diff --git a/src/compiler.c b/src/compiler.c new file mode 100644 index 0000000..6934c41 --- /dev/null +++ b/src/compiler.c @@ -0,0 +1,29 @@ +#include "compiler.h" +#include "types.h" +#include "include/estr.h" + +char* compileGroundProgram(GroundProgram* program) { + Estr start = CREATE_ESTR("global _start\nsection .text\n_start:\n"); + Estr data = CREATE_ESTR("section .rodata\n"); + + for (size_t i = 0; i < program->size; i++) { + switch (program->instructions[i].type) { + case END: { + APPEND_ESTR(start, " mov rax, 60\n"); + APPEND_ESTR(start, " mov rdi, 0\n"); + APPEND_ESTR(start, " syscall\n"); + break; + } + default: { + printf("no\n"); + exit(1); + } + } + } + + Estr complete = CREATE_ESTR(""); + APPEND_ESTR(complete, start.str); + APPEND_ESTR(complete, data.str) + + return complete.str; +} diff --git a/src/compiler.h b/src/compiler.h new file mode 100644 index 0000000..366671e --- /dev/null +++ b/src/compiler.h @@ -0,0 +1,3 @@ +#include "types.h" + +char* compileGroundProgram(GroundProgram* program); diff --git a/src/include/estr.h b/src/include/estr.h new file mode 100644 index 0000000..df5d172 --- /dev/null +++ b/src/include/estr.h @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +#ifndef ESTR_H +#define ESTR_H + +/* + + estr.h - Easy string manipulation + This library has macros to allow easier manipulation of strings. No longer shall + you have to malloc and realloc away to keep adding to your strings. + + Usage: + + Estr myString = CREATE_ESTR("my awesome string"); + APPEND_ESTR(myString, " is so cool"); + printf("%s\n", myString.str); + +*/ + +#define CREATE_ESTR(instr) \ + (Estr) { \ + .str = instr,\ + .size = strlen(instr),\ + .shouldBeFreed = 0, \ + .destroyed = 0 \ + } + +#define APPEND_ESTR(estr, instr) { \ + estr.size = estr.size + strlen(instr); \ + char* tmp_ptr = malloc(estr.size + 1); \ + if (tmp_ptr == NULL) printf("WARNING: Could not realloc estr " #estr "\n"); \ + else { \ + snprintf(tmp_ptr, estr.size + 1, "%s%s", estr.str, instr); \ + if (estr.shouldBeFreed > 0) free(estr.str); \ + estr.shouldBeFreed = 1; \ + estr.str = tmp_ptr; \ + } \ +} + +#define DESTROY_ESTR(estr) if (estr.shouldBeFreed > 0 && estr.destroyed < 1) free(estr.str); + +typedef struct Estr { + char* str; + size_t size; + int8_t shouldBeFreed; + int8_t destroyed; +} Estr; + +#endif // ESTR_H diff --git a/src/interpreter.c b/src/interpreter.c index 7516c75..0dbb3ca 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -352,7 +352,7 @@ GroundStruct parseStruct(GroundProgram* in, GroundScope* scope, size_t errorOffs GroundValue gv; - switch (stringToValueType(in->instructions[i].args.args[0].value.refName)) { + switch (stringToValueType(in->instructions[i].args.args[1].value.refName)) { case INT: { gv = createIntGroundValue(0); break; diff --git a/src/main.c b/src/main.c index 85ebc42..2bdd63e 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,6 @@ #include "parser.h" #include "interpreter.h" +#include "compiler.h" #include char* getFileContents(const char* filename) { @@ -39,6 +40,7 @@ char* getFileContents(const char* filename) { } int main(int argc, char** argv) { + /* if (argc < 2) { printf("Usage: ground [file]\n"); exit(1); @@ -46,5 +48,49 @@ int main(int argc, char** argv) { char* file = getFileContents(argv[1]); GroundProgram program = parseFile(file); free(file); + char* compiled = compileGroundProgram(&program); + printf("%s\n", compiled); interpretGroundProgram(&program, NULL); + */ + + if (argc < 2) { + printf("Usage: %s [-c] [--compile] [-h] [--help]\n", argv[0]); + exit(1); + } + + bool compile = false; + char* fileName = NULL; + + for (int i = 1; i < argc; i++) { + if (strcmp("--compile", argv[i]) == 0 || strcmp("-c", argv[i]) == 0) { + compile = true; + } + else if (strcmp("--help", argv[i]) == 0 || strcmp("-h", argv[i]) == 0) { + printf("GroundVM help\n"); + printf("Usage: %s [-c] [--compile] [-h] [--help]\n", argv[0]); + printf("Options:\n"); + printf(" -c or --compile: Outputs Linux x86_64 assembly instead of interpreting (WIP)\n"); + printf(" -h or --help: Shows this help message\n"); + exit(0); + } else { + fileName = argv[i]; + } + } + + if (fileName == NULL) { + printf("Usage: %s [-c] [--compile] [-h] [--help]\n", argv[0]); + printf("Error: No file name provided\n"); + exit(1); + } + + char* file = getFileContents(fileName); + GroundProgram program = parseFile(file); + free(file); + + if (compile) { + char* compiled = compileGroundProgram(&program); + printf("%s\n", compiled); + } else { + interpretGroundProgram(&program, NULL); + } }