From b204860b2e52d6108134cca8bb7b9f3380da4a90 Mon Sep 17 00:00:00 2001 From: Mid <> Date: Wed, 16 Jul 2025 11:00:45 +0300 Subject: [PATCH] Fucking add scope file oh my god how could I miss this --- src/scope.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/scope.h | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 src/scope.c create mode 100644 src/scope.h diff --git a/src/scope.c b/src/scope.c new file mode 100644 index 0000000..75d2a3f --- /dev/null +++ b/src/scope.c @@ -0,0 +1,112 @@ +#include"scope.h" + +#include"utils.h" +#include +#include +#include +#include + +struct ReachingDefs *reachingdefs_push(struct ReachingDefs *this) { + struct ReachingDefs *ret = calloc(1, sizeof(*ret)); + ret->parent = this; + return ret; +} + +struct ReachingDefs *reachingdefs_coalesce(struct ReachingDefs *this) { + struct ReachingDefs *parent = this->parent; + if(parent) { + parent->defs = realloc(parent->defs, sizeof(*parent->defs) * (parent->defCount + this->defCount)); + memcpy(&parent->defs[parent->defCount], this->defs, sizeof(*this->defs) * this->defCount); + parent->defCount += this->defCount; + } + free(this->defs); + free(this); + return parent; +} + +void reachingdefs_set(struct ReachingDefs *this, union AST *def) { + this->defCount = 1; + this->defs = realloc(this->defs, sizeof(*this->defs) * this->defCount); + this->defs[0] = def; + this->excludeParent = 1; +} + +Scope *scope_new(Scope *parent) { + Scope *ret = calloc(1, sizeof(*ret)); + ret->parent = parent; + ret->count = 0; + ret->names = NULL; + ret->data = NULL; + + return ret; +} + +ScopeItem *scope_get(Scope *this, const char *name) { + for(size_t v = 0; v < this->count; v++) { + if(!strcmp(name, this->names[v])) return this->data[v]; + } + return NULL; +} + +ScopeItem *scope_find(Scope *this, const char *name) { + Scope *tbl = this; + while(tbl) { + ScopeItem *entry = scope_get(tbl, name); + if(entry) { + return entry; + } + tbl = tbl->parent; + } + return NULL; +} + +ScopeItem *scope_set(Scope *this, const char *name, ScopeItem *e) { + name = strdup(name); + + this->names = realloc(this->names, sizeof(*this->names) * (this->count + 1)); + this->data = realloc(this->data, sizeof(*this->data) * (this->count + 1)); + this->names[this->count] = name; + this->data[this->count] = e; + this->count++; + if(e->kind == SCOPEITEM_VAR) e->data.var.name = name; + e->owner = this; + return e; +} + +ScopeItem *scope_find_int(Scope *scope, intmax_t val, const char *suffix) { + char buf[64]; + snprintf(buf, sizeof(buf), "%li%s", val, suffix ? suffix : ""); + + return scope_find(scope, buf); +} + +Scope *scope_merge(Scope *child) { + Scope *parent = child->parent; + + parent->names = realloc(parent->names, sizeof(*parent->names) * (parent->count + child->count)); + parent->data = realloc(parent->data, sizeof(*parent->data) * (parent->count + child->count)); + + for(size_t i = 0; i < child->count; i++) { + child->data[i]->owner = parent; + + parent->names[parent->count] = child->names[i]; + parent->data[parent->count] = child->data[i]; + + parent->count++; + } + + //free(child->names); + //free(child->data); + //free(child); + + return parent; +} + +void vte_precolor(ScopeItem *vte, int class, int color) { + assert(vte->kind == SCOPEITEM_VAR && "vte must be var"); + assert(!vte->data.var.precolored && "already precolored"); + + vte->data.var.precolored = true; + vte->data.var.registerClass = class; + vte->data.var.color = color; +} diff --git a/src/scope.h b/src/scope.h new file mode 100644 index 0000000..60313b5 --- /dev/null +++ b/src/scope.h @@ -0,0 +1,111 @@ +#ifndef NCTREF_VARTABLE_H +#define NCTREF_VARTABLE_H + +#include"types.h" +#include + +struct Token; +union AST; + +typedef enum { + SCOPEITEM_SYMBOL, SCOPEITEM_VAR, SCOPEITEM_TYPE, SCOPEITEM_CEXPR +} ScopeItemKind; + +union AST; +typedef struct UseDef { + union AST *def; // assign stmt + union AST *use; // corresponding AST_EXPR_VAR + union AST *stmt; // whole using stmt + struct UseDef *next; +} UseDef; + +// Stack, necessary for "possible reaching defs" such as from if statements +typedef struct ReachingDefs { + size_t defCount; + union AST **defs; + + int excludeParent; + struct ReachingDefs *parent; +} ReachingDefs; +struct ReachingDefs *reachingdefs_push(struct ReachingDefs*); +struct ReachingDefs *reachingdefs_coalesce(struct ReachingDefs*); +void reachingdefs_set(struct ReachingDefs*, union AST*); + +struct Scope; +typedef struct ScopeItem { + Type *type; + + struct Scope *owner; + + ScopeItemKind kind; + union { + struct { + char isLocal; + char isExternal; + const char *name; + + struct { + struct Scope *scope; + struct Token *rangeTokens; + size_t startTokI; + size_t endTokI; + } genfunc; + } symbol; + struct { + // For debugging + + const char *name; + + // Register allocation + + // vars in loops have higher priority + // a more advanced approach would be to use weights for different colors (e.g. multipliers "should" be in eax) + uint8_t priority; + int16_t color, degree; + bool precolored, preclassed; + int registerClass; + + // Used during parsing + + ReachingDefs *reachingDefs; + + // Optimizations + + UseDef *usedefFirst; + UseDef *usedefLast; + } var; + struct { + Type *ptr; + } type; + struct { + // cexpr is used for expression parametization as opposed to type parametrization + // I don't like the idea of having a special ScopeItem kind for these, but all other places were worse + const char *paramName; + size_t paramIdx; + + // If the cexpr has been parametrized (as opposed to just being a symbol), this field will be non-NULL + union AST *concrete; + } cexpr; + } data; +} ScopeItem; + +typedef struct Scope { + struct Scope *parent; + + size_t count; + const char **names; + ScopeItem **data; +} Scope; + +Scope *scope_new(Scope*); +ScopeItem *scope_get(Scope*, const char*); +ScopeItem *scope_find(Scope*, const char*); +ScopeItem *scope_set(Scope*, const char*, ScopeItem*); + +ScopeItem *scope_find_int(Scope*, intmax_t, const char*); + +Scope *scope_merge(Scope *child); + +void vte_precolor(ScopeItem *vte, int resclass, int color); + +#endif