Добавляем перегрузки функций в JavaScript
Во многих языках можно объявить несколько функций с одним именем, если у них разные сигнатуры. Это называется перегрузкой функций. Пример перегрузки в C# -
К сожалению (скорее к счастью), перегрузки не были добавлены в JS. Мне захотелось добавить их, чтобы попробовать написать что-то вроде следующего примера:
В примере random функции различаются только числом аргументов. Здесь начнём с перегрузок с явными аннотациями number и string. Как включать в такую группу функции без аннотаций или без параметров, пока оставим открытым.
Для эксперимента возьмём MuJS - небольшой интерпретатор JavaScript на C. Проследим, как он выполняет return a + b, а затем добавим аннотации параметров и выбор перегрузки.
Для разбора возьмем функцию суммирования двух переданных аргументов:
Лексер MuJS читает исходный текст программы и выдаёт токены по запросу парсера. При чтении следующего токена jsP_next() вызывает jsY_lex(J) и обновляет J->lookahead. Ниже - условная запись последовательности для sum(a, b); конец потока опущен:
Парсер MuJS написан методом рекурсивного спуска: он использует текущий токен и запрашивает следующий через jsP_next(). Так постепенно строится AST. Для наглядности представим дерево условной JSON-схемой:
MuJS хранит AST в C-структурах js_Ast. Утилита mujs-pp -s печатает его в виде S-выражений. Вот фрагмент вывода с объявлением sum:
Компилятор MuJS преобразует AST в байткод. Исполнитель jsR_run() читает инструкции байткода и выполняет их обработчики. Сам интерпретатор заранее скомпилирован из C в машинный код; отдельная машинная функция для sum в этом пути не создаётся.
Сокращённый дамп тела sum из mujs-pp -c без адресов и служебных строк: