2014-09-24 2 views
3

Я знаю, что можно построить типы внутри сгенерированной функции, но можно ли вернуть их снаружи?Можно ли использовать макрос scala для создания типов?

Мне нужен макрос, который генерирует Parser [T] - где и синтаксический анализатор, и T строятся из внешней грамматики, написанной на упрощенном языке описания грамматики для пользователей библиотеки. T анализируется AST, который содержит взаимно вложенные классы случаев. Эти классы должны быть сгенерированы и видны снаружи.

Грамматика:

RootType { 
    member1: { 
    member11: TypeB 
    member12: String 
    member13: TypeB 
    } 
    member2: String 
    TypeB { 
    member3: String 
    } 
} 

Использование:

//Somewhere in my library: 
trait ASTNode 
def parser: Parser[ASTNode] = macro ... //interpret types from grammar-file 

//On the client side: 
val input = ... //reads unparsed string from some script-file 
val parsed = parse(parser, input) 
parsed.member1.member11.member3 //so ASTNode should be replaced with RootType 
//case class TypeB and synthetic case class for member1 should be also generated 

Я думаю о решениях:

  • BlackBox макро (как определить тип, который может быть использован вне генерируемая функция?)
  • обходной путь: макро-аннотированные типы whit Члены ч, полученные от моей грамматики (я не знаю, сколько видов у меня есть, так что мне нужно для создания подклассов с помощью аннотаций, возможно ли это?) плагин компилятора
  • записи или отдельного SBT-задачи или посмотреть на macroparadise
  • генерировать класс во время выполнения не является вариантом, потому что мне нужно проверить типы

ответ

2

Да, это возможно. Вы можете генерировать АСТ, включая ClassDef, ModuleDef и т. Д. Без проблем, и если вы используете макрокоманды (из макро-рая), они будут видны внешнему коду (в обычном def макросе вроде parser в вашем желаемом коде они локальны) , См. «Поставщики публичного типа» в http://docs.scala-lang.org/overviews/macros/typeproviders.html и https://github.com/travisbrown/type-provider-examples. Код вашей библиотеки выглядит несколько иначе:

@Grammar("path/to/file") trait ASTNode // reads grammar, and generates subclasses, parser, etc. 
+0

Уже пробовал. Спасибо за ссылку, чтобы ввести поставщиков! – dk14