/* 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 . */ /* NOTE: Structure of the toc compiler: tokenizer => parser => typing (types.c) => cgen (lexing) toc tries to continue even after the first error. It will not continue during cgen, but it will during tokenization, parsing, and typing. If one stage fails, the following ones do not start. toc's memory management works using an allocator which never frees anything. This is because most of toc's data is kept around until the end of the program anyways. Use the allocator for "permanent" allocations, and err_malloc/calloc/realloc for temporary allocations (to avoid having it take up space for a long time). Because of this, memory leaks can happen if the compilation fails at any point, but they should not happen if the compilation succeeds. Usually if there's an error which causes a memory leak, it will be very small. Functions which can fail (i.e. print an error message and stop) return a Status, which is a bool, but GCC warns about not using the return value. The fixed-width types U8/16/32/64 and I8/16/32/64 have been defined. data_structures.c contains a dynamic array implementation which is very useful. Many of the members of the types below are dynamic arrays. It is assumed that the number of identifiers in a declaration, or parameters to a function will fit in an int, since a function with (at least) 32768 parameters is ridiculous. */ /* Includes all of toc's files */ #include #include #include #include #include #include #include #include #include #include #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__ #include #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_block_location(Block *b); /* misc */ #define STRINGIFY2(x) #x #define STRINGIFY(x) STRINGIFY2(x) #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; } #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 "sdecls_cgen.c" #include "decls_cgen.c" #ifdef RUN_TESTS #include "tests.c" #endif #ifdef __cplusplus #undef new #undef this #elif __STDC_VERSION__ < 199901 #undef inline #endif