rusi/руси.з

474 lines
20 KiB
Plaintext
Raw Normal View History

// ============================================================
// Заголовочный файл компилятора RUSI
// ============================================================
#еслинеопр RUSI_H
#определить RUSI_H
#определить _POSIX_C_SOURCE 200809L
#включить <assert.h> // стандартная библиотека
#включить <ctype.h> // стандартная библиотека
#включить <errno.h> // стандартная библиотека
#включить <glob.h> // стандартная библиотека
#включить <libgen.h> // стандартная библиотека
#включить <stdarg.h> // стандартная библиотека
#включить <stdbool.h> // стандартная библиотека
#включить <stdint.h> // стандартная библиотека
#включить <stdio.h> // стандартная библиотека
#включить <stdlib.h> // стандартная библиотека
#включить <stdnoreturn.h> // стандартная библиотека
#включить <string.h> // стандартная библиотека
#включить <strings.h> // стандартная библиотека
#включить <sys/stat.h> // стандартная библиотека
#включить <sys/types.h> // стандартная библиотека
#включить <sys/wait.h> // стандартная библиотека
#включить <time.h> // стандартная библиотека
#включить <unistd.h> // стандартная библиотека
пусто free_all_types(пусто);
пусто free_all_tokens(пусто);
пусто free_all_preprocess(пусто);
// ============================================================
// Общие макросы
// ============================================================
#определить MAX(a, b) ((a) < (b) ? (b) : (a))
#определить MIN(a, b) ((a) < (b) ? (a) : (b))
#еслинеопр __GNUC__
#определить __attribute__(x)
#конецесли
// ============================================================
// Предварительные объявления структур
// ============================================================
типдеф структ Type Type;
типдеф структ Node Node;
типдеф структ Member Member;
типдеф структ Relocation Relocation;
типдеф структ Hideset Hideset;
// ============================================================
// Модуль strings.c - Работа со строками
// ============================================================
типдеф структ {
символ **data; // Массив строк
цел capacity; // Вместимость
цел len; // Текущее количество
} МассивСтрок;
пусто массив_строк_добавить(МассивСтрок *массив, символ *строка);
символ *формат(символ *строкаормата, ...) __attribute__((format(printf, 1, 2)));
пусто массив_строк_освободить(МассивСтрок *массив);
пусто массив_строк_очистить(МассивСтрок *массив);
символ *массив_строк_получить(конст МассивСтрок *массив, size_t инд);
бул массив_строк_установить(МассивСтрок *массив, size_t инд, символ *строка);
бул массив_строк_вставить(МассивСтрок *массив, size_t поз, символ *строка);
бул массив_строк_удалить(МассивСтрок *массив, size_t инд);
ssize_t массив_строк_найти(конст МассивСтрок *массив, конст символ *строка);
бул массив_строк_содержит(конст МассивСтрок *массив, конст символ *строка);
// ============================================================
// Модуль tokenize.c - Лексический анализ
// ============================================================
типдеф переч {
TK_IDENT, // Идентификаторы
TK_PUNCT, // Пунктуаторы
TK_KEYWORD, // Ключевые слова
TK_STR, // Строковые литералы
TK_NUM, // Числовые литералы
TK_PP_NUM, // Препроцессорные числа
TK_EOF, // Маркер конца файла
} TokenKind;
типдеф структ {
символ *name; // Имя файла
цел file_no; // Номер файла
символ *contents; // Содержимое файла
символ *display_name; // Отображаемое имя (для #строка)
цел line_delta; // Смещение строк
} File;
типдеф структ Token Token;
структ Token {
TokenKind kind; // Тип токена
Token *next; // Следующий токен
int64_t val; // Значение для TK_NUM
длин двойн fval; // Значение с плавающей точкой для TK_NUM
символ *loc; // Позиция в исходном коде
цел len; // Длина токена
Type *ty; // Тип (для TK_NUM или TK_STR)
символ *str; // Содержимое строкового литерала (с \0)
File *file; // Файл источника
символ *filename; // Имя файла
цел line_no; // Номер строки
цел line_delta; // Смещение строки
бул at_bol; // В начале строки
бул has_space; // Есть пробел перед токеном
Hideset *hideset; // Для раскрытия макросов
Token *origin; // Исходный токен (если раскрыт из макроса)
};
// Ошибки и предупреждения
noreturn пусто error(символ *format, ...) __attribute__((format(printf, 1, 2)));
noreturn пусто error_at(символ *location, символ *format, ...) __attribute__((format(printf, 2, 3)));
noreturn пусто error_tok(Token *token, символ *format, ...) __attribute__((format(printf, 2, 3)));
пусто warn_tok(Token *token, символ *format, ...) __attribute__((format(printf, 2, 3)));
// Работа с токенами
бул equal(Token *token, символ *operator);
Token *skip(Token *token, символ *operator);
бул consume(Token **rest, Token *token, символ *str);
пусто convert_pp_tokens(Token *tokens);
// Работа с файлами
File **get_input_files(пусто);
File *new_file(символ *name, цел file_no, символ *contents);
// Токенизация
Token *tokenize_string_literal(Token *token, Type *base_type);
Token *tokenize(File *file);
Token *tokenize_file(символ *filename);
#определить unreachable() error("internal error at %s:%d", __ФАЙЛ__, __ЛИНИЯ__)
// ============================================================
// Модуль preprocess.c - Препроцессинг
// ============================================================
символ *search_include_paths(символ *filename);
пусто init_macros(пусто);
пусто define_macro(символ *name, символ *value);
пусто undef_macro(символ *name);
Token *preprocess(Token *tokens);
// ============================================================
// Модуль parse.c - Синтаксический анализ
// ============================================================
типдеф структ Obj Obj;
структ Obj {
Obj *next;
символ *name; // Имя переменной
Type *ty; // Тип
Token *tok; // Представительный токен
бул is_local; // Локальная или глобальная
цел align; // Выравнивание
// Локальные переменные
цел offset; // Смещение в стеке
// Глобальные переменные или функции
бул is_function; // Это функция
бул is_definition; // Это определение
бул is_static; // Статическая
// Глобальные переменные
бул is_tentative; // Предварительное объявление
бул is_tls; // TLS переменная
символ *init_data; // Данные инициализации
Relocation *rel; // Релокации
// Функции
бул is_inline; // Inline функция
Obj *params; // Параметры
Node *body; // Тело функции
Obj *locals; // Локальные переменные
Obj *va_area; // Область для va_list
Obj *alloca_bottom; // Нижняя граница alloca
цел stack_size; // Размер стека
// Статические inline функции
бул is_live; // Используется
бул is_root; // Корневая
МассивСтрок refs; // Ссылки (было StringArray)
};
типдеф структ Relocation Relocation;
структ Relocation {
Relocation *next;
цел offset; // Смещение
символ **label; // Метка
длин addend; // Добавка
};
типдеф переч {
ND_NULL_EXPR, // Пустое выражение
ND_ADD, // Сложение
ND_SUB, // Вычитание
ND_MUL, // Умножение
ND_DIV, // Деление
ND_NEG, // Унарный минус
ND_MOD, // Остаток от деления
ND_BITAND, // Побитовое И
ND_BITOR, // Побитовое ИЛИ
ND_BITXOR, // Побитовое исключающее ИЛИ
ND_SHL, // Сдвиг влево
ND_SHR, // Сдвиг вправо
ND_EQ, // Равно
ND_NE, // Не равно
ND_LT, // Меньше
ND_LE, // Меньше или равно
ND_ASSIGN, // Присваивание
ND_COND, // Условный оператор ?:
ND_COMMA, // Оператор запятая
ND_MEMBER, // Доступ к члену структуры
ND_ADDR, // Взятие адреса
ND_DEREF, // Разыменование
ND_NOT, // Логическое НЕ
ND_BITNOT, // Побитовое НЕ
ND_LOGAND, // Логическое И
ND_LOGOR, // Логическое ИЛИ
ND_RETURN, // возврат
ND_IF, // если
ND_FOR, // для или пока
ND_DO, // делай-пока
ND_SWITCH, // выбор
ND_CASE, // случай
ND_BLOCK, // Блок { ... }
ND_GOTO, // перейти
ND_GOTO_EXPR, // перейти с выражением (GNU)
ND_LABEL, // Метка
ND_LABEL_VAL, // Метка как значение (GNU)
ND_FUNCALL, // Вызов функции
ND_EXPR_STMT, // Выражение-инструкция
ND_STMT_EXPR, // Инструкция-выражение (GNU)
ND_VAR, // Переменная
ND_VLA_PTR, // VLA дескриптор
ND_NUM, // Число
ND_CAST, // Приведение типа
ND_MEMZERO, // Обнуление стековой переменной
ND_ASM, // асм
ND_CAS, // Атомарная compare-and-swap
ND_EXCH, // Атомарный обмен
} NodeKind;
структ Node {
NodeKind kind; // Тип узла
Node *next; // Следующий узел
Type *ty; // Тип
Token *tok; // Представительный токен
Node *lhs; // Левый операнд
Node *rhs; // Правый операнд
// Условные и циклические конструкции
Node *cond; // Условие
Node *then; // Ветвь then
Node *els; // Ветвь else
Node *init; // Инициализация
Node *inc; // Инкремент
// Метки для прерви и продолжи
символ *brk_label;
символ *cont_label;
// Блок или выражение-инструкция
Node *body;
// Доступ к члену структуры
Member *member;
// Вызов функции
Type *func_ty; // Тип функции
Node *args; // Аргументы
бул pass_by_stack; // Передача через стек
Obj *ret_buffer; // Буфер для возврата
// перейти, метки и метки как значения
символ *label;
символ *unique_label;
Node *goto_next;
// выбор
Node *case_next;
Node *default_case;
// случай
длин begin;
длин end;
// асм
символ *asm_str;
// Атомарные операции
Node *cas_addr;
Node *cas_old;
Node *cas_new;
Obj *atomic_addr;
Node *atomic_expr;
// Переменная
Obj *var;
// Числовой литерал
int64_t val;
длин двойн fval;
};
Node *new_cast(Node *expression, Type *type);
int64_t const_expr(Token **rest, Token *token);
Obj *parse(Token *tokens);
// ============================================================
// Модуль type.c - Система типов
// ============================================================
типдеф переч {
TY_VOID, // пусто
TY_BOOL, // _Bool
TY_CHAR, // символ
TY_SHORT, // корот
TY_INT, // цел
TY_LONG, // длин
TY_FLOAT, // плав
TY_DOUBLE, // двойн
TY_LDOUBLE, // длин двойн
TY_ENUM, // переч
TY_PTR, // указатель
TY_FUNC, // функция
TY_ARRAY, // массив
TY_VLA, // массив переменной длины
TY_STRUCT, // структ
TY_UNION, // объед
} TypeKind;
структ Type {
TypeKind kind; // Тип
цел size; // Размер в байтах
цел align; // Выравнивание
бул is_unsigned; // Беззнаковый
бул is_atomic; // _Atomic
Type *origin; // Исходный тип (для типдеф)
// Для указателей и массивов
Type *base;
// Имя (для объявлений)
Token *name;
Token *name_pos;
// Для массивов
цел array_len; // Длина массива
Node *vla_len; // Длина VLA (выражение)
Obj *vla_size; // Размер VLA
// Для структур/объединений
Member *members;
бул is_flexible; // Гибкий массив
бул is_packed; // Упакованный
// Для функций
Type *return_ty; // Возвращаемый тип
Type *params; // Параметры
бул is_variadic; // Функция с переменным числом аргументов
Type *next; // Следующий параметр
};
структ Member {
Member *next;
Type *ty;
Token *tok; // Для сообщений об ошибках
Token *name;
цел idx; // Индекс
цел align; // Выравнивание
цел offset; // Смещение
// Битовые поля
бул is_bitfield;
цел bit_offset;
цел bit_width;
};
// Базовые типы
внеш Type *ty_void;
внеш Type *ty_bool;
внеш Type *ty_char;
внеш Type *ty_short;
внеш Type *ty_int;
внеш Type *ty_long;
внеш Type *ty_uchar;
внеш Type *ty_ushort;
внеш Type *ty_uint;
внеш Type *ty_ulong;
внеш Type *ty_float;
внеш Type *ty_double;
внеш Type *ty_ldouble;
// Проверка типов
бул is_integer(Type *type);
бул is_flonum(Type *type);
бул is_numeric(Type *type);
бул is_compatible(Type *first, Type *second);
// Создание типов
Type *copy_type(Type *original);
Type *pointer_to(Type *base_type);
Type *func_type(Type *return_type);
Type *array_of(Type *base_type, цел size);
Type *vla_of(Type *base_type, Node *expr);
Type *enum_type(пусто);
Type *struct_type(пусто);
// Вывод типов
пусто add_type(Node *node);
// ============================================================
// Модуль codegen.c - Генерация кода
// ============================================================
пусто codegen(Obj *program, FILE *output);
цел align_to(цел value, цел alignment);
// ============================================================
// Модуль unicode.c - Поддержка Unicode
// ============================================================
цел encode_utf8(символ *buffer, uint32_t code_point);
uint32_t decode_utf8(символ **new_position, символ *input);
бул is_ident1(uint32_t code_point);
бул is_ident2(uint32_t code_point);
цел display_width(символ *text, цел length);
// ============================================================
// Модуль hashmap.c - Хеш-таблица
// ============================================================
типдеф структ {
символ *ключ; // Ключ
цел длина_ключа; // Длина ключа
пусто *значение; // Значение
} ЗаписьХеша;
типдеф структ {
ЗаписьХеша *корзины; // Массив корзин
цел вместимость; // Вместимость
цел использовано; // Использовано
} ХешТаблица;
пусто *хеш_получить(ХешТаблица *таблица, символ *ключ);
пусто *хеш_получить2(ХешТаблица *таблица, символ *ключ, цел длина_ключа);
пусто хеш_вставить(ХешТаблица *таблица, символ *ключ, пусто *значение);
пусто хеш_вставить2(ХешТаблица *таблица, символ *ключ, цел длина_ключа, пусто *значение);
пусто хеш_удалить(ХешТаблица *таблица, символ *ключ);
пусто хеш_удалить2(ХешТаблица *таблица, символ *ключ, цел длина_ключа);
пусто хеш_тест(пусто);
// ============================================================
// Модуль main.c - Основная программа
// ============================================================
бул file_exists(символ *path);
внеш МассивСтрок include_paths; // было StringArray
внеш бул opt_fpic;
внеш бул opt_fcommon;
внеш символ *base_file;
#конецесли // RUSI_H