Add compiler #14

Merged
max merged 13 commits from unstable into master 2026-01-21 15:53:20 +11:00
5 changed files with 131 additions and 1 deletions
Showing only changes of commit d3c03b4987 - Show all commits

29
src/compiler.c Normal file
View File

@@ -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;
}

3
src/compiler.h Normal file
View File

@@ -0,0 +1,3 @@
#include "types.h"
char* compileGroundProgram(GroundProgram* program);

52
src/include/estr.h Normal file
View File

@@ -0,0 +1,52 @@
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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

View File

@@ -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;

View File

@@ -1,5 +1,6 @@
#include "parser.h"
#include "interpreter.h"
#include "compiler.h"
#include <stdio.h>
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 <file> [-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 <file> [-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 <file> [-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);
}
}