ox

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

sem.c (5355B)


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