aboutsummaryrefslogtreecommitdiff
path: root/src/sema/sema.c
blob: 99ec4f14d4e473a907102ce799d6bca1600442ee (plain)
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sema/sema.h"

static bool names_equal(struct Token a, struct Token b)
{
	return a.length == b.length && memcmp(a.start, b.start, a.length) == 0;
}

static bool check_duplicate_names(struct Program* program)
{
	size_t count = program->const_count + program->data_count + program->proc_count;
	if (count == 0)
		return true;

	struct Token* names = malloc(count * sizeof(struct Token));
	size_t n = 0;
	for (size_t i = 0; i < program->const_count; i += 1)
	{
		names[n] = program->consts[i].name;
		n += 1;
	}
	for (size_t i = 0; i < program->data_count; i += 1)
	{
		names[n] = program->data_decls[i].name;
		n += 1;
	}
	for (size_t i = 0; i < program->proc_count; i += 1)
	{
		names[n] = program->procs[i].name;
		n += 1;
	}

	bool ok = true;
	for (size_t i = 0; i < count; i += 1)
		for (size_t j = 0; j < i; j += 1)
			if (names_equal(names[i], names[j]))
			{
				fprintf(stderr, "error: line %u: '%.*s' is already defined\n",
					names[i].line, (int)names[i].length, names[i].start);
				ok = false;
			}

	free(names);
	return ok;
}

static bool check_entry_point(struct Program* program)
{
	for (size_t i = 0; i < program->proc_count; i += 1)
	{
		struct Token name = program->procs[i].name;
		if (name.length == 4 && memcmp(name.start, "main", 4) == 0)
			return true;
	}

	fprintf(stderr, "error: no 'main' procedure defined\n");
	return false;
}

bool analyze_program(struct Program* program)
{
	bool ok = true;

	if (!check_duplicate_names(program))
		ok = false;
	if (!check_entry_point(program))
		ok = false;

	return ok;
}