dsl - XText Chained Dependencies in Type Inference -
in experiments, appears xtext cannot resolve variable types when there chain of dependencies across multiple xexpression blocks.
a minimal example, illustrate. have grammar:
grammar eg.types.inference.typeinferenceexample 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 '}' ;
an interface:
package eg.lib; public interface imodelblock { public void push(org.eclipse.xtext.xbase.lib.pair<string, ?> topush); }
and 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 block instanceof xfeaturecall && (it xfeaturecall).concretesyntaxfeaturename.equals("push") ].map [ val call = xfeaturecall // add entry push call outputdeclaration return call.featurecallarguments.map[ if (!(it instanceof xbinaryoperation)) { throw new runtimeexception("must push using -> operator") } val key = (it xbinaryoperation).leftoperand val value = (it xbinaryoperation).rightoperand return key.name -> value.inferredtype ] ].head } def private string name(xexpression literal) { if (!(literal instanceof xstringliteral)) { throw new unsupportedoperationexception("literal not string literal") } return (literal xstringliteral).value } }
when create simple example dsl, such as:
{ name : blockone : none block : { val = 42 * 3.6 push("index" -> i) } } { name : blocktwo : blockone block : { val res = "another value " + index push("result" -> res) } }
code generated fine (type inference works out types of index
, res
in generating output java). using pairs in call push
on blockone
infer interface on invoke method blocktwo
. push
method comes imodelblock
interface above. if add third block example, thus:
{ name : blockthree : blocktwo block : { val out = "this 1 came from: " + result push("out" -> out) } }
inference fails, unsupportedoperationexception: todo: import functional handle on type resolution delegates best available (current, evolving) result
(from onchangeevictingcache.execwithoutcacheclear
, cachingbatchtyperesolver.resolvetypes
).
is there other technique should use derive types of variables have chained dependencies in xtext?
thanks help!
this seem have been bug in version use. try latest one.
Comments
Post a Comment