#swift #dsl
#быстрый #цифровая абонентская линия
Вопрос:
Предыстория: Я пишу компилятор для игрушечного языка в Swift, и мне нужен элегантный способ создания AST для моего языка. Тип AST для оператора на моем языке игрушек выглядит следующим образом:
indirect enum Statement { case assignment(variable: String, expression: Expression) case conditional(`if`: Expression, then: Statement, `else`: Statement) case loop(`while`: Expression, `do`: Statement) case sequence(Statement, Statement) case noop case halt }
Прямо сейчас, если я хочу написать AST для серии заявлений, мне придется написать:
// let's say I want to represent a series of 4 no-ops: .sequence(.noop, .sequence(.noop, .sequence(.noop, .noop)))
Это выглядит очень многословно. Я подумал, что было бы неплохо, если бы я мог использовать эту @resultBuilder
функцию, чтобы я мог писать:
Statement { .noop .noop .noop .noop }
Это моя попытка:
@resultBuilder struct StatementBuilder { static func buildBlock(_ components: Statement...) -gt; Statement { if components.isEmpty { return .noop } else { return components.dropFirst().reduce(components.first!) { x, y in .sequence(x, y) } } } } extension Statement { init(@StatementBuilder block: () -gt; Statement) { self = block() } }
Однако это приводит меня к ошибке:
Не удается вывести контекстуальную базу в отношении элемента «noop»
в Statement { ... }
квартале.
Что неясно в контекстуальной базе? Что это может быть за тип, кроме Statement
? Я мог бы исправить это , добавив ко всему префикс Statement.
, но это слишком многословно. Что еще я могу сделать?
Обратите внимание, что я также планирую перегрузить операторы , чтобы я мог легко создавать назначения и выражения, соответствующие типам синтаксического дерева ExpressibleXXXLiteral
, а также добавлять If
и While
выполнять функции StatementBuilder
, которые создают .conditional
.loop
операторы и. Таким образом, конструктор результатов будет гораздо полезнее, чем просто для создания остановок и остановок.