summaryrefslogtreecommitdiffstats
path: root/src/symbol-table.c
blob: 09c84a30c01291b8e3ed42814b4637bc3bce02f3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "common.h"
#include "symbol-table.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static int hash(const char *str)
{
    int idx = 0;
    for (; *str; str++) {
        idx = idx << 1;
        idx += *str;
    }
    return (idx & (CCMMC_SYMBOL_SCOPE_HASH_TABLE_SIZE - 1));
}

void ccmmc_symbol_table_init(CcmmcSymbolTable *table)
{
    table->all = NULL;
    table->all_last = NULL;
    table->this_scope = NULL;
    table->current = NULL;
}

// push a scope on the stack
void ccmmc_symbol_table_open_scope(CcmmcSymbolTable *table)
{
    CcmmcSymbolScope *scope = malloc(sizeof(CcmmcSymbolScope));
    ERR_FATAL_CHECK(scope, malloc);
    for (int i = 0; i < CCMMC_SYMBOL_SCOPE_HASH_TABLE_SIZE; i++)
        scope->hash_table[i] = NULL;
    if (table->all == NULL) {
        table->all = scope;
        table->all_last = scope;
    } else {
        table->all_last->all_next = scope;
        table->all_last = scope;
    }
    scope->all_next = NULL;
    scope->current_next = table->current;
    table->current = scope;
}

// used by code-generation phase
void ccmmc_symbol_table_reopen_scope(CcmmcSymbolTable *table)
{
    if (table->this_scope == NULL)
        table->this_scope = table->all;
    else
        table->this_scope = table->this_scope->all_next;
    table->current = table->this_scope;
}

// pop a scope from the stack
void ccmmc_symbol_table_close_scope(CcmmcSymbolTable *table)
{
    CcmmcSymbolScope *closing = table->current;
    table->current = closing->current_next;
}

void ccmmc_symbol_table_insert(CcmmcSymbolTable *table,
    const char *name, CcmmcSymbolKind kind, CcmmcSymbolType type)
{
    int key = hash(name);
    CcmmcSymbol *symbol = malloc(sizeof(CcmmcSymbol));
    ERR_FATAL_CHECK(symbol, malloc);
    symbol->kind = kind;
    symbol->type = type;
    symbol->attr.addr = 0;
    symbol->name = name;
    symbol->next = table->current->hash_table[key];
    table->current->hash_table[key] = symbol;
}

CcmmcSymbol *ccmmc_symbol_table_retrieve (
    CcmmcSymbolTable *table, const char *name)
{
    if (name == NULL)
        return NULL;

    int key = hash(name);
    for (CcmmcSymbolScope *scope = table->current; scope; scope = scope->current_next) {
        for (CcmmcSymbol *symbol = scope->hash_table[key]; symbol; symbol = symbol->next) {
            if (strcmp(name, symbol->name) == 0)
                return symbol;
        }
    }
    return NULL;
}

bool ccmmc_symbol_scope_exist(CcmmcSymbolScope *scope, const char *name)
{
    int key = hash(name);
    for (CcmmcSymbol *symbol = scope->hash_table[key];
         symbol != NULL; symbol = symbol->next) {
        if (strcmp(name, symbol->name) == 0)
            return true;
    }
    return false;
}

// vim: set sw=4 ts=4 sts=4 et: