summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/headers/abstract.h129
-rw-r--r--src/headers/codegen.h13
-rw-r--r--src/headers/freeast.h70
-rw-r--r--src/headers/kat.h175
-rw-r--r--src/rbc.c118
5 files changed, 505 insertions, 0 deletions
diff --git a/src/headers/abstract.h b/src/headers/abstract.h
new file mode 100644
index 0000000..efecaa0
--- /dev/null
+++ b/src/headers/abstract.h
@@ -0,0 +1,129 @@
+#ifndef CRBC_ABSTR
+#define CRBC_ABSTR
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+// ===== EXPRESSIONS =====
+enum ExprKind {
+ EXPR_INT, EXPR_BOOL,
+ EXPR_CHAR, EXPR_STRING,
+ EXPR_IDENT
+};
+
+typedef struct Expr {
+ enum ExprKind kind;
+ void *as;
+} Expr;
+
+typedef struct ExprInt {
+ int value;
+} ExprInt;
+//
+typedef struct ExprChar {
+ char value;
+} ExprChar;
+//
+typedef struct ExprBool {
+ bool value;
+} ExprBool;
+//
+typedef struct ExprString {
+ char *value;
+} ExprString;
+//
+typedef struct ExprIdent {
+ char *name;
+} ExprIdent;
+
+// ===== STATEMENTS =====
+typedef struct Stmt {
+ int _dummy;
+} Stmt;
+
+typedef struct Block {
+ int _dummy;
+} Block;
+
+// ===== DECLARATIONS =====
+enum DeclKind {
+ DECL_VAR,
+ DECL_FUNC,
+ DECL_TYPE_STRUCT,
+ DECL_TYPE_ENUM,
+ DECL_TYPE_UNION
+};
+
+typedef struct Decl {
+ enum DeclKind kind;
+ void *as;
+} Decl;
+
+// variable declaration
+typedef struct DeclVar {
+ char *ident;
+ char *type; // TODO: replace with Type*
+ Expr *init; // NULL => declaration only
+} DeclVar;
+
+// function declaration
+typedef struct DeclFunc {
+ char *ident;
+ char *return_type; // NULL => inferred
+ char *params; // TODO: param list
+ Block *body; // NULL => forward declaration
+} DeclFunc;
+
+// struct type declaration
+typedef struct DeclTypeStruct {
+ char *ident;
+ char *members; // TODO: member list
+} DeclTypeStruct;
+
+// enum type declaration
+typedef struct EnumMember {
+ char *name;
+ char *value; // NULL => implicit
+} EnumMember;
+
+typedef struct DeclTypeEnum {
+ char *ident;
+ EnumMember *members;
+} DeclTypeEnum;
+
+// union type declaration
+typedef struct DeclTypeUnion {
+ char *ident;
+ char *members; // TODO: member list
+} DeclTypeUnion;
+
+// ===== FUNCTIONS =====
+static inline Decl *DeclareVariable(const char *ident, const char *type, Expr *init) {
+ Decl *decl = malloc(sizeof *decl);
+ DeclVar *var = malloc(sizeof *var);
+
+ var->ident = strdup(ident);
+ var->type = type ? strdup(type) : NULL;
+ var->init = init;
+
+ decl->kind = DECL_VAR;
+ decl->as = var;
+
+ return decl;
+}
+
+static inline Expr *ExprIntLiteral(int value) {
+ Expr *expr = malloc(sizeof *expr);
+ ExprInt *lit = malloc(sizeof *lit);
+
+ lit->value = value;
+
+ expr->kind = EXPR_INT;
+ expr->as = lit;
+
+ return expr;
+}
+
+#endif
+
diff --git a/src/headers/codegen.h b/src/headers/codegen.h
new file mode 100644
index 0000000..d629caf
--- /dev/null
+++ b/src/headers/codegen.h
@@ -0,0 +1,13 @@
+#ifndef CRBC_CODEGEN
+#define CRBC_CODEGEN
+
+// Header file for CReborn's Codegen API
+
+#include <stdlib.h>
+#include <string.h>
+
+static inline int fb(int x) {
+ return x;
+}
+
+#endif
diff --git a/src/headers/freeast.h b/src/headers/freeast.h
new file mode 100644
index 0000000..544d183
--- /dev/null
+++ b/src/headers/freeast.h
@@ -0,0 +1,70 @@
+#ifndef CRBC_FREEAST
+#define CRBC_FREEAST
+
+// Free memory functions, utilize after having used the AST
+
+#include <stdlib.h>
+
+void FreeExpr(Expr *expr)
+{
+ if (!expr) return;
+
+ switch (expr->kind) {
+ case EXPR_INT:
+ free(expr->as);
+ break;
+ case EXPR_BOOL:
+ break;
+ case EXPR_CHAR:
+ break;
+ case EXPR_STRING:
+ break;
+ case EXPR_IDENT:
+ break;
+ default:
+ break;
+ }
+
+ free(expr);
+}
+
+static inline void FreeDeclVar(DeclVar *var)
+{
+ if (!var) return;
+
+ free(var->ident);
+ free(var->type);
+
+ free(var);
+}
+
+void FreeDecl(Decl *decl)
+{
+ if (!decl) return;
+
+ switch (decl->kind) {
+ case DECL_VAR:
+ FreeDeclVar((DeclVar *)decl->as);
+ break;
+
+ case DECL_FUNC:
+ /* FreeDeclFunc(...) later */
+ break;
+
+ case DECL_TYPE_STRUCT:
+ /* FreeDeclTypeStruct(...) later */
+ break;
+
+ case DECL_TYPE_ENUM:
+ /* ... */
+ break;
+
+ case DECL_TYPE_UNION:
+ /* ... */
+ break;
+ }
+
+ free(decl);
+}
+
+#endif
diff --git a/src/headers/kat.h b/src/headers/kat.h
new file mode 100644
index 0000000..f5a3a00
--- /dev/null
+++ b/src/headers/kat.h
@@ -0,0 +1,175 @@
+// kat.cfg (kat.h)
+// with love by czjstmax <jstmaxlol@disroot.org>
+// header version 2
+
+#pragma once
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef KAT
+#define KAT
+
+struct kat_api {
+ int (*create)(const char*);
+ int (*add)(const char*, const char*, const char*);
+ int (*read)(const char*, const char*, char*, size_t);
+ int (*del)(const char*, const char*);
+ int (*edit)(const char*, const char*, const char*);
+ int (*addComment)(const char*, const char*);
+};
+
+// Creates a file
+static inline int katcreate(const char *path) {
+ FILE *f = fopen(path, "w");
+ if (!f) return 1;
+ fclose(f);
+ return 0; // success
+}
+
+// Appends a key=val to file
+static inline int katadd(const char *key, const char *val, const char *path) {
+ FILE *f = fopen(path, "a");
+ if (f) {
+ fprintf(f, "%s=%s\n", key, val);
+ fclose(f);
+ return 0;
+ }
+ return 1;
+}
+
+// Appends a comment to file
+static inline int kataddcomment(const char *str, const char *path) {
+ FILE *f = fopen(path, "a");
+ if (f) {
+ fprintf(f, "#%s\n", str);
+ fclose(f);
+ return 0;
+ }
+ return 1;
+}
+
+// Reads a key from file
+static inline int katreadkey(const char *key, const char *path, char *buffer, size_t bufsize) {
+ FILE *f = fopen(path, "r");
+ if (!f) return 1;
+
+ char line[1024];
+ size_t key_len = strlen(key);
+
+ while (fgets(line, sizeof(line), f)) {
+ // TODO: skip leading whitespace maybe?
+ // check if line starts with key and '=' right after
+ if (strncmp(line, key, key_len) == 0 && line[key_len] == '=') {
+ if (line[0] == '#' || line[0] == ';' || line[0] == '\n') continue;
+ // copy everything after '=' until newline or buffer full (aka bad)
+ char *val_start = line + key_len + 1;
+ size_t len = strcspn(val_start, "\r\n"); // length until newline
+ if (len >= bufsize) len = bufsize - 1;
+ strncpy(buffer, val_start, len);
+ buffer[len] = '\0';
+ fclose(f);
+ return 0; // success
+ }
+ }
+
+ fclose(f);
+ return 1;
+}
+
+// Deletes a key from file
+static inline int katdelkey(const char *key, const char *path) {
+ FILE *f = fopen(path, "r");
+ if (!f) return 1;
+
+ char temp_path[1024];
+ snprintf(temp_path, sizeof(temp_path), "%s.tmp", path);
+ FILE *temp = fopen(temp_path, "w");
+ if (!temp) {
+ fclose(f);
+ return 1;
+ }
+
+ char line[1024];
+ size_t key_len = strlen(key);
+ int deleted = 0;
+
+ while (fgets(line, sizeof(line), f)) {
+ // skip line if it matches 'key='
+ if (strncmp(line, key, key_len) == 0 && line[key_len] == '=') {
+ deleted = 1;
+ continue;
+ }
+ fputs(line, temp);
+ }
+
+ fclose(f);
+ fclose(temp);
+
+ if (deleted) {
+ // replace original file with temp
+ if (remove(path) != 0) return 1;
+ if (rename(temp_path, path) != 0) return 1;
+ } else {
+ remove(temp_path);
+ }
+
+ return deleted ? 0 : 1; // 0 if deleted, 1 if not found
+}
+
+// Edits a key's value from file
+static inline int kateditkey(const char *key, const char *new_val, const char *path) {
+ FILE *f = fopen(path, "r");
+ if (!f) return 1;
+
+ char temp_path[1024];
+ snprintf(temp_path, sizeof(temp_path), "%s.tmp", path);
+ FILE *temp = fopen(temp_path, "w");
+ if (!temp) {
+ fclose(f);
+ return 1;
+ }
+
+ char line[1024];
+ size_t key_len = strlen(key);
+ int found = 0;
+
+ while (fgets(line, sizeof(line), f)) {
+ // skip leading whitespace for accurate matching
+ char *start = line;
+ while (*start == ' ' || *start == '\t') start++;
+
+ if (strncmp(start, key, key_len) == 0 && start[key_len] == '=') {
+ // replace line with new key=val
+ fprintf(temp, "%s=%s\n", key, new_val);
+ found = 1;
+ } else {
+ fputs(line, temp);
+ }
+ }
+
+ if (!found) {
+ // key not found, add it at the end
+ fprintf(temp, "%s=%s\n", key, new_val);
+ }
+
+ fclose(f);
+ fclose(temp);
+
+ if (remove(path) != 0) return 1;
+ if (rename(temp_path, path) != 0) return 1;
+
+ return 0;
+}
+
+struct kat_api kat = {
+ .create = katcreate,
+ .add = katadd,
+ .read = katreadkey,
+ .del = katdelkey,
+ .edit = kateditkey,
+ .addComment = kataddcomment,
+};
+
+#endif
diff --git a/src/rbc.c b/src/rbc.c
new file mode 100644
index 0000000..5316cda
--- /dev/null
+++ b/src/rbc.c
@@ -0,0 +1,118 @@
+#ifndef CRBC
+#define CRBC
+/*================================================================================================*
+ * CReborn - The first "official" C implementation of the Reborn programming language
+ * based on the Reborn Standard (reborn-lang.github.io/documents/standard)
+ *
+ * The name CReborn (C/Reborn, CREBORN or whatever) has been chosen because
+ * this implementation works by using C as its IR, or in much simpler terms,
+ * this compiler works by compiling Reborn code to C, and then using the GNU C
+ * Compiler (GNU Compiler Collection, gcc) to compile the output C program to
+ * an executable. This decision was made to both simplify the development and also
+ * to be able to focus more on the frontend of the compiler instead of focusing on
+ * optimization and platform-specific instructions.
+ *================================================================================================*
+ *#* STYLE GUIDELINES FOR CODE CONTRIBUTORS (AND MAINTAINERS):
+ * - Use camelCase for variables.
+ * - Use PascalCase for functions.
+ * - 4 spaces indentation (not tabs but spaces.)
+ * - Don't exceed 100 characters on a single line unless you *really* must, it's mostly
+ * for readability since we think that it is better for code to extend vertically, rather
+ * than horizontally. (Also given some developers might use 3:2 or other less-wide formats.)
+ *================================================================================================*
+ *#* NOTES FOR VIM USERS
+ * - For Vim users that don't know how to set a limit to the coloumn size, you just:
+ * :set textwidth=100
+ * :set formatoptions+=t
+ * You can also obviously also set this in your .vimrc.
+ *
+ * - For Vim users that want to (a)llow the local .exrc for commodity, you can just do:
+ * :set exrc secure
+ * and reopen any file in the repo, then you will be asked to (a)llow, meaning to trust this
+ * repo's .exrc, after (a)llowing it you will already have the 4 spaces indentation, the 100
+ * characters limit (textwidth limit) and the format options set automatically. This only applies
+ * when editing files from this repo, but if you want them in your global .vimrc or neovim config
+ * you can also copy them, again, from the local .exrc file.
+ *
+ * - Note: If you use vim/nvim and you loaded (allowed) the .exrc from this repo you can also use
+ * these commands that will automatically compile for either release / normal mode testing or for
+ * debugging mode.
+ *
+ * :Cn / :Compn - Compiles with 'Normal compile'
+ * :Cd / :Compd - Compiles with 'Debug compile'
+ *
+ *#* COMPILE COMMANDS
+ * Normal compile = 'cc rbc.c -o crbc -O2 -Wall -Wextra -pedantic'
+ * Debug compile = 'cc rbc.c -o crbc -g -O0 -Wall -Wextra -pedantic -fsanitize=address,undefined'
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// git@github.com:jstmaxlol/kat
+#include "headers/kat.h"
+
+// CReborn headers (CReborn APIs)
+#include "headers/codegen.h"
+#include "headers/abstract.h"
+#include "headers/freeast.h"
+
+// ASTs in abstract.h
+//
+
+// Functions (fwd. declars. and externs)
+//
+// headers/abstract.h
+// headers/freeast.h
+// headers/codegen.h
+//
+// local / helpers
+static inline int Eval(int x);
+
+// main
+int main(int argc, char **argv) {
+ printf(":> Checking for arguments...\n");
+ if (argc >= 2) {
+ for (int i = 1; i < argc; i++) {
+ printf("argv[%d] = %s\n", i, argv[i]);
+ }
+ } else {
+ printf(":> No arguments were found. (%d)\n\n", argc-1);
+ }
+
+ const char *ident_buff = "number";
+ const char *type_buff = "int";
+
+ int value_buff = 2;
+
+ if (argc == 3) {
+ if (strlen(argv[1]) >= 1)
+ ident_buff = argv[1];
+ //if (strlen(argv[2]) >= 1)
+ // type_buff = argv[2];
+ if (strlen(argv[2]) >= 1)
+ value_buff = atoi(argv[2]);
+ }
+
+ Expr *e = ExprIntLiteral(value_buff);
+ Decl *decl = DeclareVariable(ident_buff, type_buff, e);
+
+ if (decl->kind == DECL_VAR) {
+ DeclVar *v = decl->as;
+ printf("v->ident=%s, v->type=%s\nlet %s: %s = %d;", v->ident, v->type, v->ident, v->type, value_buff);
+ }
+
+ FreeExpr(e);
+ FreeDecl(decl);
+
+ return 0;
+}
+
+// Functions (definitions)
+//
+static inline int Eval(int x) {
+ return x;
+}
+
+#endif