ox

The Ox programming language, compiler and tools (WIP)
Log | Files | Refs | README | LICENSE

sem.c (7119B)


      1 #include <assert.h>
      2 #include <stdio.h>
      3 #include <string.h>
      4 
      5 #include "sem.h"
      6 #include "parser.h"
      7 #include "utils.h"
      8 
      9 #define CALLOC_SZ 16
     10 #define BASE_DEPTH 1
     11 
     12 static int next_id = 100;
     13 
     14 Scope
     15 scope_init(Node* node)
     16 {
     17 	Scope s = (Scope) { .parent = NULL,
     18 		.symbols = (Symbol**)calloc(CALLOC_SZ, sizeof(Symbol*)),
     19 		.children = (Scope**)calloc(CALLOC_SZ, sizeof(Scope*)),
     20 		.cap = CALLOC_SZ,
     21 		.len = 0,
     22 		.ch_cap = CALLOC_SZ,
     23 		.ch_len = 0,
     24 		.depth = BASE_DEPTH,
     25 		.owner = node,
     26 		.id = next_id++ };
     27 
     28 	if (s.symbols == NULL) panic_at(node, "scope_init: could not alloc");
     29 	if (s.children == NULL) panic_at(node, "scope_init: could not alloc");
     30 	return s;
     31 }
     32 
     33 static Scope*
     34 new_scope_from_scope(Scope* parent_scope, Node* node)
     35 {
     36 	// new scope
     37 	Scope* scope = (Scope*)calloc(1, sizeof(Scope));
     38 	if (scope == NULL) panic_at(node, "new_scope_from_scope: could not alloc");
     39 
     40 	scope->id = next_id++;
     41 	scope->owner = node;
     42 	node->scope = scope;
     43 
     44 	// init symbols list
     45 	scope->symbols = (Symbol**)calloc(CALLOC_SZ, sizeof(Symbol*));
     46 	if (scope->symbols == NULL) panic_at(node, "new_scope_from_scope: symbols: could not alloc");
     47 	scope->cap = CALLOC_SZ;
     48 	scope->len = 0;
     49 
     50 	scope->children = (Scope**)calloc(CALLOC_SZ, sizeof(Scope*));
     51 	if (scope->children == NULL) panic_at(node, "new_scope_from_scope: children: could not alloc");
     52 	scope->ch_cap = CALLOC_SZ;
     53 	scope->ch_len = 0;
     54 
     55 	// init parent and depth
     56 	if (parent_scope != NULL) {
     57 		scope->parent = parent_scope;
     58 		scope->depth = parent_scope->depth + 1;
     59 		assert(parent_scope->children != NULL);
     60 		if (parent_scope->ch_len == parent_scope->ch_cap) {
     61 			parent_scope->ch_cap *= 2;
     62 			parent_scope->children = (Scope**)realloc(parent_scope->children, parent_scope->ch_cap * sizeof(Scope*));
     63 			assert(parent_scope->children != NULL && "realloc failed");
     64 		}
     65 		parent_scope->children[parent_scope->ch_len++] = scope;
     66 	} else {
     67 		scope->parent = NULL;
     68 		scope->depth = BASE_DEPTH;
     69 	}
     70 
     71 	return scope;
     72 }
     73 
     74 static void
     75 add_to_scope(Scope* scope, Symbol* sym)
     76 {
     77 	if (scope->len >= scope->cap) {
     78 		scope->cap *= 2;
     79 		scope->symbols = (Symbol**)realloc(scope->symbols, scope->cap * sizeof(Symbol*));
     80 	}
     81 	scope->symbols[scope->len++] = sym;
     82 }
     83 
     84 static void
     85 scope_var(Scope* scope, Ast* ast, Node* node)
     86 {
     87 	const char* var_name = span_str(ast->src, node->data.var_decl.name, (char[IDENTSZ]) { 0 });
     88 	const char* type_name = span_str(ast->src, node->data.var_decl.type->data.ident.name, (char[IDENTSZ]) { 0 });
     89 
     90 	Symbol* sym = (Symbol*)calloc(1, sizeof(Symbol));
     91 	if (sym == NULL) panic_at(node, "scope_var: symbol: could not alloc");
     92 
     93 	TypeInfo* type = (TypeInfo*)calloc(1, sizeof(TypeInfo));
     94 	if (type == NULL) panic_at(node, "scope_var: type: could not alloc");
     95 
     96 	if (strcmp(type_name, "float") == 0) {
     97 		type->type = SYMTYPE_FLOAT;
     98 	} else if (strcmp(type_name, "int") == 0) {
     99 		type->type = SYMTYPE_INT;
    100 	} else if (strcmp(type_name, "uint") == 0) {
    101 		type->type = SYMTYPE_UINT;
    102 
    103 	} else if (strcmp(type_name, "str") == 0) {
    104 		type->type = SYMTYPE_STR;
    105 	} else if (strcmp(type_name, "chr") == 0) {
    106 		type->type = SYMTYPE_CHR;
    107 	} else if (strcmp(type_name, "bool") == 0) {
    108 		type->type = SYMTYPE_BOOL;
    109 
    110 	} else if (strcmp(type_name, "struct") == 0) {
    111 		type->type = SYMTYPE_STRUCT;
    112 
    113 	} else if (strcmp(type_name, "i8") == 0) {
    114 		type->type = SYMTYPE_I8;
    115 	} else if (strcmp(type_name, "i16") == 0) {
    116 		type->type = SYMTYPE_I16;
    117 	} else if (strcmp(type_name, "i32") == 0) {
    118 		type->type = SYMTYPE_I32;
    119 	} else if (strcmp(type_name, "i64") == 0) {
    120 		type->type = SYMTYPE_I64;
    121 	} else if (strcmp(type_name, "i128") == 0) {
    122 		type->type = SYMTYPE_I128;
    123 
    124 	} else if (strcmp(type_name, "u8") == 0) {
    125 		type->type = SYMTYPE_U8;
    126 	} else if (strcmp(type_name, "u16") == 0) {
    127 		type->type = SYMTYPE_U16;
    128 	} else if (strcmp(type_name, "u32") == 0) {
    129 		type->type = SYMTYPE_U32;
    130 	} else if (strcmp(type_name, "u64") == 0) {
    131 		type->type = SYMTYPE_U64;
    132 	} else if (strcmp(type_name, "u128") == 0) {
    133 		type->type = SYMTYPE_U128;
    134 
    135 	} else if (strcmp(type_name, "f32") == 0) {
    136 		type->type = SYMTYPE_F32;
    137 	} else if (strcmp(type_name, "f64") == 0) {
    138 		type->type = SYMTYPE_F64;
    139 	} else if (strcmp(type_name, "f128") == 0) {
    140 		type->type = SYMTYPE_F128;
    141 
    142 	} else {
    143 		if (type_name[0] >= 'A' && type_name[0] <= 'Z') {
    144 			type->type = SYMTYPE_USER;
    145 		} else {
    146 			panic_at(node, "sem: not yet defined type '%s' for variable '%s'", type_name, var_name);
    147 		}
    148 	}
    149 
    150 	sym->name = node->data.var_decl.name;
    151 	sym->decl = node->data.var_decl.init;
    152 	sym->type = type;
    153 	printf("scope_var: adding to scope %s (%s)\n", var_name, type_name);
    154 	add_to_scope(scope, sym);
    155 }
    156 
    157 static void
    158 scope_func(Scope* parent_scope, Ast* ast, Node* node)
    159 {
    160 	Scope* scope = new_scope_from_scope(parent_scope, node);
    161 	node->scope = scope;
    162 
    163 	for (size_t i = 0; i < node->data.block.len; i++) {
    164 		Node* stmt = node->data.block.stmts[i];
    165 		stmt->scope = scope;
    166 		switch (stmt->type) {
    167 		case NODE_VAR_DECL: {
    168 			scope_var(scope, ast, stmt);
    169 			break;
    170 		}
    171 		default:
    172 			continue;
    173 		}
    174 	}
    175 }
    176 
    177 void
    178 scope_program(Scope* scope, Ast* ast)
    179 {
    180 	for (size_t i = 0; i < ast->node->data.program.len; i++) {
    181 		Node* node = ast->node->data.program.decl[i];
    182 		node->scope = scope;
    183 		switch (node->type) {
    184 		case NODE_VAR_DECL:
    185 			scope_var(scope, ast, node);
    186 			break;
    187 		case NODE_FUNCTION_DECL:
    188 			scope_func(/*parent_scope*/ scope, ast, node->data.function_decl.body);
    189 			break;
    190 		default:
    191 			printf("unknown definition at TODO\n");
    192 		}
    193 	}
    194 }
    195 
    196 void
    197 scope_print(Scope* scope, Ast* ast)
    198 {
    199 	if (scope == NULL || scope->symbols == NULL) return;
    200 
    201 	for (size_t i = 0; i < scope->len; i++) {
    202 		Symbol* sym = scope->symbols[i];
    203 		const char* name = span_str(ast->src, sym->name, (char[IDENTSZ]) { 0 });
    204 		int parent = -1;
    205 		if (scope->parent != NULL) parent = scope->parent->id;
    206 		bool has_owner_node = false;
    207 		if (scope->owner != NULL) has_owner_node = true;
    208 		printf("[depth %d] [id %d] Symbol name `%s` \t of type %s (parent %d, owner %s)\n",
    209 			scope->depth,
    210 			scope->id,
    211 			name,
    212 			type_kind_str(sym->type->type),
    213 			parent,
    214 			has_owner_node ? "yes" : "no");
    215 	}
    216 
    217 	if (scope->ch_len == 0) return;
    218 
    219 	for (size_t j = 0; j < scope->ch_len; j++) {
    220 		Scope* child_scope = scope->children[j];
    221 		scope_print(child_scope, ast);
    222 	}
    223 }
    224 
    225 const char*
    226 type_kind_str(SymbolType t)
    227 {
    228 	static const char* type_strings[] = {
    229 		[SYMTYPE_VOID] = "TYPE_VOID",
    230 		[SYMTYPE_INT] = "TYPE_INT",
    231 
    232 		[SYMTYPE_I8] = "TYPE_I8",
    233 		[SYMTYPE_I16] = "TYPE_I16",
    234 		[SYMTYPE_I32] = "TYPE_I32",
    235 		[SYMTYPE_I64] = "TYPE_I64",
    236 		[SYMTYPE_I128] = "TYPE_I128",
    237 		[SYMTYPE_UINT] = "TYPE_UINT",
    238 
    239 		[SYMTYPE_U8] = "TYPE_U8",
    240 		[SYMTYPE_U16] = "TYPE_U16",
    241 		[SYMTYPE_U32] = "TYPE_U32",
    242 		[SYMTYPE_U64] = "TYPE_U64",
    243 		[SYMTYPE_U128] = "TYPE_U128",
    244 
    245 		[SYMTYPE_F32] = "TYPE_F32",
    246 		[SYMTYPE_F64] = "TYPE_F64",
    247 		[SYMTYPE_F128] = "TYPE_F128",
    248 		[SYMTYPE_FLOAT] = "TYPE_FLOAT",
    249 
    250 		[SYMTYPE_STR] = "TYPE_STR",
    251 		[SYMTYPE_CHR] = "TYPE_CHR",
    252 		[SYMTYPE_BOOL] = "TYPE_BOOL",
    253 		[SYMTYPE_STRUCT] = "TYPE_STRUCT",
    254 		[SYMTYPE_USER] = "TYPE_USER",
    255 		[SYMTYPE_FUNC] = "TYPE_FUNC",
    256 		[SYMTYPE_TODO] = "TYPE_TODO",
    257 	};
    258 
    259 	return (t >= SYMTYPE_VOID && t <= SYMTYPE_TODO) ? type_strings[t] : "UNKNOWN_TYPE_KIND";
    260 }