summaryrefslogtreecommitdiff
path: root/toc.c
blob: 5536dd8db5aebe034e5e8eb07a4f446bfe8c5c66 (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
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
/*
  Copyright (C) 2019, 2020 Leo Tenenbaum.
  This file is part of toc. toc is distributed under version 3 of the GNU General Public License, without any warranty whatsoever.
  You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>.
*/

/* Includes all of toc's files */
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <limits.h>
#include <float.h>
#include <inttypes.h>

#ifndef COMPILE_TIME_FOREIGN_FN_SUPPORT
#define COMPILE_TIME_FOREIGN_FN_SUPPORT 0
#endif


#ifdef __cplusplus
#define new new_
#define this this_
#define export export_
#elif __STDC_VERSION__ < 199901
#ifndef inline
#define inline
#endif
#endif


/* use toc_alignof only for non-structs. it may be incorrect for pre-C(++)11. */
#if (__STDC_VERSION__ >= 201112 || __cplusplus >= 201103L) && !defined __TINYC__ && !defined __OpenBSD__ && !defined __FreeBSD__
#include <stdalign.h>
#define toc_alignof alignof

#ifdef __GNUC__
/* GCC supports non-string literals as the message for a static assertion */
#define possibly_static_assert(cond) static_assert(cond, "Assertion " #cond " failed.")
#else
#define possibly_static_assert(cond) static_assert(cond, "Assertion failed")
#endif


#else

#define toc_alignof sizeof

#define possibly_static_assert(cond) assert(cond)
#endif


#include "types.h"

/* forward declarations for debugging */
static void print_val(Value v, Type *t);
static void print_token(Token *t);
static void print_type(Type *t);
static void print_block(Block *b);
static void print_decl(Declaration *d);
static void print_stmt(Statement *s);
static void print_block_location(Block *b);


/* misc */
#define join3(a,b) a##b
#define join2(a,b) join3(a,b)
#define join(a,b) join2(a,b)

static void fprint_char_literal(FILE *f, char c) {
	if (isprint(c))
		fprintf(f, "'%c'", c);
	else
		fprintf(f, "'\\x%02x'", c);
}


static inline bool type_is_builtin(Type *t, BuiltinType b) {
	return t->kind == TYPE_BUILTIN && t->builtin == b;
}

static inline bool type_is_slicechar(Type *t) {
	return t->kind == TYPE_SLICE && type_is_builtin(t->slice, BUILTIN_CHAR);
}

/* utilities */
#include "allocator.c"
#include "misc.c"
#include "data_structures.c"
#include "err.c"
static size_t compiler_alignof(Type *t);
static size_t compiler_sizeof(Type *t);
#include "instance_table.c"

/* returns NULL on error */
static char *read_file_contents(Allocator *a, const char *filename, Location where) {
	FILE *in = fopen(filename, "r");
	
	if (!in) {
		err_print(where, "Could not open file: %s.", filename);
		return NULL;
	}
	char *contents = allocr_malloc(a, 4096);
	contents[0] = 0; /* put 0 byte at the start of the file. see err.c:err_print_location_text to find out why */
	contents[1] = 0; /* if fgets fails the first time */
	long contents_cap = 4095;
	long contents_len = 1;
	while (fgets(contents + contents_len, (int)(contents_cap - contents_len), in)) {
		contents_len += (long)strlen(contents + contents_len);
		
		if (contents_len >= (long)contents_cap - 1024) {
			size_t prev = (size_t)contents_cap + 1;
			contents_cap *= 2;
			contents = allocr_realloc(a, contents, prev, (size_t)contents_cap + 1);
		}
	}
	++contents;
	fclose(in);
	return contents;
}
	

static Location token_location(File *file, Token *t);

#include "identifiers.c"
#include "copy.c"
#include "tokenizer.c"
#include "parse.c"
#include "foreign.c"
#include "eval.c"
#include "infer.c"
#include "types.c"
static void cgen_decls_file(CGenerator *g, ParsedFile *f);
static void cgen_sdecls_file(CGenerator *g, ParsedFile *f);
#include "cgen.c"
#include "decls_cgen.c"

#if RUN_TESTS
#include "tests.c"
#endif



#ifdef __cplusplus
#undef new
#undef this
#elif __STDC_VERSION__ < 199901
#undef inline
#endif