From 1c11d915a68e60bd191d43e348d56b9eab71b107 Mon Sep 17 00:00:00 2001 From: czjstmax Date: Fri, 19 Dec 2025 23:32:31 +0100 Subject: Created `src` dir for code, added Makefile --- Makefile | 58 ++++++++++++++++ headers/abstract.h | 129 ------------------------------------ headers/codegen.h | 13 ---- headers/freeast.h | 70 -------------------- headers/kat.h | 175 ------------------------------------------------- rbc.c | 118 --------------------------------- src/headers/abstract.h | 129 ++++++++++++++++++++++++++++++++++++ src/headers/codegen.h | 13 ++++ src/headers/freeast.h | 70 ++++++++++++++++++++ src/headers/kat.h | 175 +++++++++++++++++++++++++++++++++++++++++++++++++ src/rbc.c | 118 +++++++++++++++++++++++++++++++++ 11 files changed, 563 insertions(+), 505 deletions(-) create mode 100644 Makefile delete mode 100644 headers/abstract.h delete mode 100644 headers/codegen.h delete mode 100644 headers/freeast.h delete mode 100644 headers/kat.h delete mode 100644 rbc.c create mode 100644 src/headers/abstract.h create mode 100644 src/headers/codegen.h create mode 100644 src/headers/freeast.h create mode 100644 src/headers/kat.h create mode 100644 src/rbc.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6243fb3 --- /dev/null +++ b/Makefile @@ -0,0 +1,58 @@ +CC = cc +# Release options +CFLAGS = -Wall -Wextra -pedantic -O2 +TARGET = build/crbc +# Debug options +DEBUG_CFLAGS = -Wall -Wextra -pedantic -O0 -fsanitize=address,undefined -g +DEBUG_TARGET = debug/crbc +# Source +SRC = src/rbc.c +# Install targets +PREFIX ?= /usr/local +BINDIR = $(PREFIX)/bin +INSTALL_TARGET = crbc +INSTALL_DEBUG_TARGET = $(INSTALL_TARGET)_debug + +# Compile all +All: + $(CC) $(CFLAGS) $(SRC) -o $(TARGET) + $(CC) $(DEBUG_CFLAGS) $(SRC) -o $(DEBUG_TARGET) + +# Compile release (same as 'make') +Release: + $(CC) $(CFLAGS) $(SRC) -o $(TARGET) + +# Compile debug +Debug: + $(CC) $(DEBUG_CFLAGS) $(SRC) -o $(DEBUG_TARGET) + +# Clean all (release + debug) +cleanall: + rm -f $(TARGET) + rm -f $(DEBUG_TARGET) + +# Clean release +CleanRelease: + rm -f $(TARGET) + +# Clean debug +CleanDebug: + rm -f $(DEBUG_TARGET) + +# Install all (release + debug) +Install: + install -Dm755 $(INSTALL_TARGET) $(BINDIR)/crbc + install -Dm755 $(INSTALL_DEBUG_TARGET) $(BINDIR)/crbc + +# Install release +InstallRelease: + install -Dm755 $(INSTALL_TARGET) $(BINDIR)/crbc + +# Install debug +InstallDebug: + install -Dm755 $(INSTALL_DEBUG_TARGET) $(BINDIR)/crbc + +# Uninstall all +Uninstall: + rm -f $(BINDIR)/$(INSTALL_TARGET) + rm -f $(BINDIR)/$(INSTALL_DEBUG_TARGET) diff --git a/headers/abstract.h b/headers/abstract.h deleted file mode 100644 index efecaa0..0000000 --- a/headers/abstract.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef CRBC_ABSTR -#define CRBC_ABSTR - -#include -#include -#include - -// ===== 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/headers/codegen.h b/headers/codegen.h deleted file mode 100644 index d629caf..0000000 --- a/headers/codegen.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef CRBC_CODEGEN -#define CRBC_CODEGEN - -// Header file for CReborn's Codegen API - -#include -#include - -static inline int fb(int x) { - return x; -} - -#endif diff --git a/headers/freeast.h b/headers/freeast.h deleted file mode 100644 index 544d183..0000000 --- a/headers/freeast.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef CRBC_FREEAST -#define CRBC_FREEAST - -// Free memory functions, utilize after having used the AST - -#include - -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/headers/kat.h b/headers/kat.h deleted file mode 100644 index f5a3a00..0000000 --- a/headers/kat.h +++ /dev/null @@ -1,175 +0,0 @@ -// kat.cfg (kat.h) -// with love by czjstmax -// header version 2 - -#pragma once - -#include -#include -#include - -#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/rbc.c b/rbc.c deleted file mode 100644 index 5316cda..0000000 --- a/rbc.c +++ /dev/null @@ -1,118 +0,0 @@ -#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 -#include -#include - -// 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 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 +#include +#include + +// ===== 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 +#include + +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 + +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 +// header version 2 + +#pragma once + +#include +#include +#include + +#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 +#include +#include + +// 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 -- cgit v1.3.1