~pixelherodev/c3lib

ref: 718f594cd11395d48f3c90b37f204d3d4599a8db c3lib/sema/scope.c -rw-r--r-- 3.6 KiB
718f594cNoam Preil tmp 3 months ago
                                                                                
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include "../util.h"
#include "../tags.h"
#include "../c3.h"
#include "../stb.h"
#include "../stb_ds.h"
#include "scope.h"


struct c3scope{
	struct c3scope_rc{
		// a value contained within the scope
		uint32_t key;
		// reference count - zero when first added
		uint32_t value;
	} *values;
	uint32_t parent;
	struct{
		uint32_t *decls;
		uint32_t *scopes;
	}subscopes;
};

static struct{
	c3ctx *c3;
	struct c3scope *scopes;
	struct{
		c3ctx *key;
		struct c3scope *value;
	}map;
} ctx;

// If ident is -1, there will be no way to look up this scope from the parent!
// If parent is -1, this is a top-level scope.
uint32_t
scope_new(uint32_t parent, uint32_t node)
{
	uint32_t index;
	if(!stb_sb_ensure_capacity(&ctx.scopes, 1, sizeof(struct c3scope))){
		ERROR("ICE: OOM", 0);
		return -1;
	}
	index = stb_sb_count(ctx.scopes);
	stb_sb_increment(ctx.scopes, 1);
	ctx.scopes[index].values = NULL;
	ctx.scopes[index].parent = parent;
	ctx.scopes[index].subscopes.decls = NULL;
	ctx.scopes[index].subscopes.scopes = NULL;
	if(parent != -1){
		if(!(stb_sb_push_u32(&ctx.scopes[parent].subscopes.scopes, index) && stb_sb_push_u32(&ctx.scopes[parent].subscopes.decls, node))){
			ERROR("ICE: OOM", 0);
			return -1;
		}
	}
	return index;
}

uint32_t
scope_parent(uint32_t scope)
{
	return ctx.scopes[scope].parent;
}

uint32_t
scope_find_decl(uint32_t scope_handle, uint32_t ident, uint32_t *parent, int only_analyzed)
{
	uint32_t i;
	struct c3scope *scope;
	uint32_t t_ident;
	if(c3nodechild(*ctx.c3, ident, 0) != -1){
		WARN("finding decl by ident %d: '%s' in scope %d", ident, h_c3str(*ctx.c3, c3nodechild(*ctx.c3, ident, 0)), scope_handle);
		}
	else
		FATAL("bad ident: %d", ident);
	c3tag tag;
	scope = &ctx.scopes[scope_handle];
	for(i = 0; i < stbds_hmlenu(scope->values); i += 1){
		tag = c3nodetag(*ctx.c3, scope->values[i].key);
		if(tag != C3_CONST && tag != C3_FN_PARAM && tag != C3_VAR)
			continue;
		if(scope->values[i].value == 0 && only_analyzed)
			continue;
		t_ident = c3nodechild(*ctx.c3, scope->values[i].key, 0);
		WARN("checking against %d", t_ident);
		WARN("str: '%s'", h_c3str(*ctx.c3, c3nodechild(*ctx.c3, t_ident, 0)));
		if(t_ident == ident){
			if(parent != NULL)
				*parent = scope_handle;
			WARN("Found tag: %s", c3tagstr(tag));
			return scope->values[i].key;
		}
	}
	if(scope->parent != -1)
		return scope_find_decl(scope->parent, ident, parent, only_analyzed);
	return -1;
}

uint32_t
scope_subscope(uint32_t scope_handle, uint32_t decl)
{
	uint32_t i;
	struct c3scope *scope;
	scope = &ctx.scopes[scope_handle];
	for(i = 0; i < stb_sb_count(scope->subscopes.decls); i += 1)
		if(scope->subscopes.decls[i] == decl)
			return scope->subscopes.scopes[i];
	return -1;
}

int
scope_mark_used(uint32_t handle, uint32_t value)
{
	struct c3scope *scope;
	uint32_t i;
	scope = &ctx.scopes[handle];
	i = stbds_hmgeti(scope->values, value);
	if(i == -1)
		return 0;
	scope->values[i].value += 1;
	return 1;
}

int
scope_insert(uint32_t scope, uint32_t value)
{
	uint32_t ident = c3nodechild(*ctx.c3, value, 0);
	if(ident != -1 && c3nodetag(*ctx.c3, ident) == C3_IDENT)
		ident = c3nodechild(*ctx.c3, ident, 0);
	if(ident != -1)
		WARN("inserting '%s' into scope %d", h_c3str(*ctx.c3, ident), scope);
	stbds_hmput(ctx.scopes[scope].values, value, 0);
	return 1;
}

void
scope_init(c3ctx *c3ctx)
{
	ctx.c3 = c3ctx;
}

void
scope_free(void)
{
	uint32_t i;
	struct c3scope scope;
	for(i = 0; i < stb_sb_count(ctx.scopes); i += 1){
		scope = ctx.scopes[i];
		stbds_hmfree(scope.values);
		stb_sb_free(scope.subscopes.scopes);
		stb_sb_free(scope.subscopes.decls);
	}
	stb_sb_free(ctx.scopes);
	ctx.scopes = NULL;
	ctx.c3 = NULL;
}