ox

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

sem.c (5387B)


      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("scope_init: could not alloc");
     29 	if (s.children == NULL) panic("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("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("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("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("scope_var: symbol: could not alloc");
     92 
     93 	TypeInfo* type = (TypeInfo*)calloc(1, sizeof(TypeInfo));
     94 	if (type == NULL) panic("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, "string") == 0) {
    101 		type->type = SYMTYPE_STRING;
    102 	} else if (strcmp(type_name, "uint") == 0) {
    103 		type->type = SYMTYPE_UINT;
    104 	} else {
    105 		if (type_name[0] >= 'A' && type_name[0] <= 'Z') {
    106 			type->type = SYMTYPE_USER;
    107 		} else {
    108 			panic("sem: not yet defined type '%s' for variable '%s'", type_name, var_name);
    109 		}
    110 	}
    111 
    112 	sym->name = node->data.var_decl.name;
    113 	sym->decl = node->data.var_decl.init;
    114 	sym->type = type;
    115 	printf("scope_var: adding to scope %s (%s)\n", var_name, type_name);
    116 	add_to_scope(scope, sym);
    117 }
    118 
    119 static void
    120 scope_func(Scope* parent_scope, Ast* ast, Node* node)
    121 {
    122 	Scope* scope = new_scope_from_scope(parent_scope, node);
    123 	node->scope = scope;
    124 
    125 	for (size_t i = 0; i < node->data.block.len; i++) {
    126 		Node* stmt = node->data.block.stmts[i];
    127 		stmt->scope = scope;
    128 		switch (stmt->type) {
    129 		case NODE_VAR_DECL: {
    130 			scope_var(scope, ast, stmt);
    131 			break;
    132 		}
    133 		default:
    134 			continue;
    135 		}
    136 	}
    137 }
    138 
    139 void
    140 scope_program(Scope* scope, Ast* ast)
    141 {
    142 	for (size_t i = 0; i < ast->node->data.program.len; i++) {
    143 		Node* node = ast->node->data.program.decl[i];
    144 		node->scope = scope;
    145 		switch (node->type) {
    146 		case NODE_VAR_DECL:
    147 			scope_var(scope, ast, node);
    148 			break;
    149 		case NODE_FUNCTION_DECL:
    150 			scope_func(/*parent_scope*/ scope, ast, node->data.function_decl.body);
    151 			break;
    152 		default:
    153 			printf("unknown definition at TODO\n");
    154 		}
    155 	}
    156 }
    157 
    158 void
    159 scope_print(Scope* scope, Ast* ast)
    160 {
    161 	if (scope == NULL || scope->symbols == NULL) return;
    162 
    163 	for (size_t i = 0; i < scope->len; i++) {
    164 		Symbol* sym = scope->symbols[i];
    165 		const char* name = span_str(ast->src, sym->name, (char[IDENTSZ]) { 0 });
    166 		int parent = -1;
    167 		if (scope->parent != NULL) parent = scope->parent->id;
    168 		bool has_owner_node = false;
    169 		if (scope->owner != NULL) has_owner_node = true;
    170 		printf("[depth %d] [id %d] Symbol name `%s` \t of type %s (parent %d, owner %s)\n",
    171 			scope->depth,
    172 			scope->id,
    173 			name,
    174 			type_kind_str(sym->type->type),
    175 			parent,
    176 			has_owner_node ? "yes" : "no");
    177 	}
    178 
    179 	if (scope->ch_len == 0) return;
    180 
    181 	for (size_t j = 0; j < scope->ch_len; j++) {
    182 		Scope* child_scope = scope->children[j];
    183 		scope_print(child_scope, ast);
    184 	}
    185 }
    186 
    187 const char*
    188 type_kind_str(SymbolType t)
    189 {
    190 	static const char* type_strings[] = {
    191 		[SYMTYPE_VOID] = "TYPE_VOID",
    192 		[SYMTYPE_INT] = "TYPE_INT",
    193 		[SYMTYPE_UINT] = "TYPE_UINT",
    194 		[SYMTYPE_FLOAT] = "TYPE_FLOAT",
    195 		[SYMTYPE_STRING] = "TYPE_STRING",
    196 		[SYMTYPE_USER] = "TYPE_USER",
    197 		[SYMTYPE_FUNC] = "TYPE_FUNC",
    198 		[SYMTYPE_TODO] = "TYPE_TODO",
    199 	};
    200 
    201 	return (t >= SYMTYPE_VOID && t <= SYMTYPE_TODO) ? type_strings[t] : "UNKNOWN_TYPE_KIND";
    202 }