Почему Swift не может определить тип контекстной базы в построителе результатов?

#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 операторы и. Таким образом, конструктор результатов будет гораздо полезнее, чем просто для создания остановок и остановок.