2013-05-14 44 views
0

在我的實驗中,看起來當跨多個XExpression塊存在一系列依賴關係時,XText無法解析變量類型。類型推斷中的XText鏈式依賴關係

一個簡單的例子,說明。我有一個語法:

grammar eg.types.inference.TypeInferenceExample with org.eclipse.xtext.xbase.Xbase 

generate typeInferenceExample "example.org/types/inference/TypeInferenceExample" 

Model: 
    blocks += Block* 
; 

Block: 
    '{' 
     'name' ':' name=QualifiedName 
     'from' ':' ('none' | from=[Block|QualifiedName]) 
     'block' ':' expression=XBlockExpression 
    '}' 
; 

接口:

package eg.lib; 

public interface IModelBlock { 
    public void push(org.eclipse.xtext.xbase.lib.Pair<String, ?> toPush); 
} 

並有JvmModelInferrer:

package eg.types.inference.jvmmodel 

import com.google.inject.Inject 
import eg.lib.IModelBlock 
import eg.types.inference.typeInferenceExample.Block 
import eg.types.inference.typeInferenceExample.Model 
import org.eclipse.xtext.xbase.XBinaryOperation 
import org.eclipse.xtext.xbase.XExpression 
import org.eclipse.xtext.xbase.XFeatureCall 
import org.eclipse.xtext.xbase.XStringLiteral 
import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer 
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor 
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder 

class TypeInferenceExampleJvmModelInferrer extends AbstractModelInferrer { 

    @Inject extension JvmTypesBuilder 

    def dispatch void infer(Model model, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) { 
     model.blocks.forEach [block | 
      acceptor.accept(block.toClass(block.name)).initializeLater [ 
       superTypes += block.newTypeRef(typeof(IModelBlock)) 
       members += block.toMethod("invoke", newTypeRef(Void::TYPE)) [ 
        if (block.from != null) { 
         block.from.pushType.forEach [p | 
          parameters += block.toParameter(p.key, p.value) 
         ] 
        } 
        body = block.expression 
       ] 
      ] 
     ] 
    } 

    def private pushType(Block block) { 
     return block.eAllContents.filter[ // List of push calls in this Block 
      it instanceof XFeatureCall && (it as XFeatureCall).concreteSyntaxFeatureName.equals("push") 
     ].map [ 
      val call = it as XFeatureCall 
      // Add entry for push call as an OutputDeclaration 
      return call.featureCallArguments.map[ 
       if (!(it instanceof XBinaryOperation)) { 
        throw new RuntimeException("Must push using -> operator") 
       } 
       val key = (it as XBinaryOperation).leftOperand 
       val value = (it as XBinaryOperation).rightOperand 
       return key.name -> value.inferredType 
      ] 
     ].head 
    } 

    def private String name(XExpression literal) { 
     if (!(literal instanceof XStringLiteral)) { 
      throw new UnsupportedOperationException("Literal was not a string literal") 
     } 
     return (literal as XStringLiteral).value 
    } 

} 

當我創建一個簡單的例子,這種DSL,如:

{ 
    name : BlockOne 
    from : none 
    block : { 
     val i = 42 * 3.6 
     push("index" -> i) 
    } 
} 

{ 
    name : BlockTwo 
    from : BlockOne 
    block : { 
     val res = "Another Value from " + index 
     push("result" -> res) 
    } 
} 

代碼生成得很好(type inferenc e成功地生成了輸出Java中的indexres的類型)。我正在使用調用中的對來推斷調用方法中的接口BlockTwo。這push方法來自上面的IModelBlock接口。如果我的第三塊添加到本實施例中,因此:

{ 
    name : BlockThree 
    from : BlockTwo 
    block : { 
     val out = "This one came from: " + result 
     push("out" -> out) 
    } 
} 

推理失敗,與UnsupportedOperationException: TODO: import a functional handle on the type resolution that delegates to the best available (current, but evolving) result(從OnChangeEvictingCache.execWithoutCacheClearCachingBatchTypeResolver.resolveTypes)。

是否有一些其他技術我應該用來派生變量類型的鏈接依賴像這樣在XText中?

感謝您的幫助!

回答

-1

這似乎是您使用的版本中的錯誤。嘗試最新的一個。

+0

我剛剛嘗試使用XText 2.5.0(根據文檔R201312110906),它拋出了相同的異常。我是否缺少更新網站? – 2013-12-27 15:50:17