Fucking add scope file oh my god how could I miss this

This commit is contained in:
Mid 2025-07-16 11:00:45 +03:00
parent a39bf40755
commit b204860b2e
2 changed files with 223 additions and 0 deletions

112
src/scope.c Normal file
View File

@ -0,0 +1,112 @@
#include"scope.h"
#include"utils.h"
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<stdio.h>
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;
}

111
src/scope.h Normal file
View File

@ -0,0 +1,111 @@
#ifndef NCTREF_VARTABLE_H
#define NCTREF_VARTABLE_H
#include"types.h"
#include<stdbool.h>
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