rusi/руси.з

474 lines
20 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ============================================================
// Заголовочный файл компилятора 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