2011-12-13 2 views
2

Я пишу DSL для выражения потока (оригинал, который я знаю) в groovy. Я хотел бы предоставить пользователю возможность писать функции, которые хранятся и оцениваются в определенных точках потока. Что-то вроде:Groovy DSL со встроенными строчными скриптами

states { 
    "checkedState" { 
     onEnter {state-> 
      //do some groovy things with state object 
     } 
    } 
} 

Теперь я уверен, что смогу окружать закрытие в кавычках и хранить это. Но я бы хотел, чтобы подсветка синтаксиса и контент помогали при редактировании этих DSL. Я понимаю, что замыкание COULD указывает артефакты из определения окружающего потока, которое больше не будет действительным при выполнении закрытия в другом контексте, и я в порядке с этим. На самом деле я хотел бы использовать синтаксис закрытия для определения функции, отличной от замыкания.

tl; dr; Мне нужно получить код закрытия при оценке DSL, чтобы он мог быть сохранен в базе данных и впоследствии запущен узлом сценария.

ответ

2

Я не думаю, что есть способ получить исходный код закрытия, поскольку эта информация отбрасывается во время компиляции. Возможно, вы могли бы попробовать написать файл AST transformation, который бы отображал дерево синтаксиса закрытия во время выполнения.

Если все, о чем вы заботитесь, хранит закрытие в базе данных, и вам не нужен более поздний доступ к исходному коду, вы можете попробовать сериализовать его и сохранить сериализованную форму.

Closure реализует Serializable, а после обнуления его owner, thisObjectdelegate и атрибуты, я был в состоянии сериализовать его, но я получаю ClassNotFoundException на десериализации.

def myClosure = {a, b -> a + b} 

Closure.metaClass.setAttribute(myClosure, "owner", null) 
Closure.metaClass.setAttribute(myClosure, "thisObject", null) 
myClosure.delegate = null 

def byteOS = new ByteArrayOutputStream() 
new ObjectOutputStream(byteOS).writeObject(myClosure) 
def serializedClosure = byteOS.toByteArray() 

def input = new ObjectInputStream(new ByteArrayInputStream(serializedClosure)) 
def deserializedClosure = input.readObject() // throws CNFE 

После некоторых поисков, я нашел Groovy Remote Control, библиотеку, созданную специально для того, чтобы сериализации закрытия и выполнения их позже, возможно, на удаленной машине. Попробуйте, может быть, это то, что вам нужно.

+0

Отличный ответ спасибо! Ответ на этот вопрос будет зависеть от готовой библиотеки рендеринга AST, но я дам ему немного больше времени, чтобы другие люди ответили. –

Смежные вопросы