Hiya,<br><br>I'm trying to prototype some compiler optimizations and linguistic extensions to AS3 and feeling the framework out. I'm running into some behaviour I didn't quite expect and think it is because I don't understand the appropriate way to manipulate tokens :) I would have loved to used the metaas statement manipulators etc., but they don't seem to be very fine grained (particularly, statements instead of ast's mean no cps etc transforms). It's nice enough having all the antlr-overhead done, though :) Anyways, maybe somebody has thoughts on how I'm doing the following incorrectly:
<br><br>1. dupTree doesn't entirely duplicate a tree:<br><br> For example, let's say I wanted to copy the type annotation from a var_def identifier on to a method_def. Using setChildWithToken, I can move one to the other, but copying (by using
node.dupTree()) throws <br><br>java.lang.IllegalArgumentException: No startToken: IDENTIFIER<br> at uk.co.badgersinfoil.metaas.impl.antlr.BasicListUpdateDelegate.replacedChild(BasicListUpdateDelegate.java:220)<br> at
uk.co.badgersinfoil.metaas.impl.antlr.LinkedListTree.setChildWithTokens(LinkedListTree.java:134)<br><br>Context:<br><br>//good, not dup'ing the source<br>((LinkedListTree) getterTemplate.getChild(5)).setChildWithTokens(
<br> 0, (LinkedListTree) typeSpec.getChild(0));<br>//bad, dup'ing the source<br>((LinkedListTree) getterTemplate.getChild(5)).setChildWithTokens(<br> 0, (LinkedListTree) typeSpec.getChild
(0).dupTree());<br><br>//context<br>print(getterTemplate): //trying to replace type annotation :* on lines 13-14<br>:6::: | METHOD_DEF ::[@-1,0:0='METHOD_DEF',<6>,0:-1]<br>:8::: | ANNOTATIONS ::[@-1,0:0='ANNOTATIONS',<8>,0:-1]
<br>:9::: | ANNOTATION ::[@-1,0:0='ANNOTATION',<9>,0:-1]<br>:94:: | Bindable ::[@-1,'Bindable',<94>,1:1]<br>:9::: | ANNOTATION ::[@-1,0:0='ANNOTATION',<9>,0:-1]
<br>:94:: | Bindable ::[@-1,'Bindable',<94>,5:6]<br>:12:: | MODIFIERS ::[@-1,0:0='MODIFIERS',<12>,0:-1]<br>:95:: | public ::[@-1,'public',<95>,5:16]
<br>:64:: | function ::[@-1,'function',<64>,1:11]<br>:65:: | get ::[@-1,'get',<65>,1:20]<br>:94:: | d ::[@-1,'d',<94>,1:24]
<br>:16:: | PARAMS ::[@-1,0:0='PARAMS',<16>,0:-1]<br>:18:: | : ::[@-1,0:0=':',<18>,1:29]<br>:91:: | * ::[@-1,'*',<91>,1:31]
<br>:19:: | BLOCK ::[@-1,0:0='BLOCK',<19>,0:-1]<br>:69:: | var ::[@-1,'var',<69>,1:35]<br>:94:: | b ::[@-1,'b',<94>,1:39]
<br>:18:: | : ::[@-1,0:0=':',<18>,1:41]<br>:48:: | IDENTIFIER ::[@-1,0:0='IDENTIFIER',<48>,0:-1]<br>:94:: | Behaviour ::[@-1,'Behaviour',<94>,1:43]
<br>:71:: | = ::[@-1,'=',<71>,1:53]<br>:26:: | METHOD_CALL ::[@-1,0:0='METHOD_CALL',<26>,0:-1]<br>:27:: | PROPERTY_OR_IDENTIFIER ::[@-1,0:0='PROPERTY_OR_IDENTIFIER',<27>,0:-1]
<br>:94:: | SignalEngine ::[@-1,'SignalEngine',<94>,1:55]<br>:94:: | binding ::[@-1,'binding',<94>,1:68]<br>:22:: | ARGUMENTS ::[@-1,0:0='ARGUMENTS',<22>,0:-1]
<br>:20:: | ELIST ::[@-1,0:0='ELIST',<20>,0:-1]<br>:94:: | this ::[@-1,'this',<94>,1:76]<br>:63:: | 'd' ::[@-1,''d'',<63>,1:82]
<br>:75:: | if ::[@-1,'if',<75>,1:89]<br>:21:: | CONDITION ::[@-1,0:0='CONDITION',<21>,0:-1]<br>:141: | ! ::[@-1,'!',<141>,1:93]
<br>:94:: | b ::[@-1,'b',<94>,1:94]<br>:19:: | BLOCK ::[@-1,0:0='BLOCK',<19>,0:-1]<br>:23:: | EXPR_STMNT ::[@-1,0:0='EXPR_STMNT',<23>,0:-1]
<br>:20:: | ELIST ::[@-1,0:0='ELIST',<20>,0:-1]<br>:94:: | b ::[@-1,'b',<94>,1:101]<br>:71:: | = ::[@-1,'=',<71>,1:103]
<br>:152: | new ::[@-1,'new',<152>,1:105]<br>:94:: | EventStream ::[@-1,'EventStream',<94>,1:109]<br>:22:: | ARGUMENTS ::[@-1,0:0='ARGUMENTS',<22>,0:-1]
<br>:23:: | EXPR_STMNT ::[@-1,0:0='EXPR_STMNT',<23>,0:-1]<br>:20:: | ELIST ::[@-1,0:0='ELIST',<20>,0:-1]<br>:26:: | METHOD_CALL ::[@-1,0:0='METHOD_CALL',<26>,0:-1]
<br>:27:: | PROPERTY_OR_IDENTIFIER ::[@-1,0:0='PROPERTY_OR_IDENTIFIER',<27>,0:-1]<br>:94:: | SignalEngine ::[@-1,'SignalEngine',<94>,1:143]<br>:94:: | bind ::[@-1,'bind',<94>,1:156]
<br>:22:: | ARGUMENTS ::[@-1,0:0='ARGUMENTS',<22>,0:-1]<br>:20:: | ELIST ::[@-1,0:0='ELIST',<20>,0:-1]<br>:94:: | this ::[@-1,'this',<94>,1:161]
<br>:63:: | 'd' ::[@-1,''d'',<63>,1:167]<br>:94:: | b ::[@-1,'b',<94>,1:172]<br>:77:: | return ::[@-1,'return',<77>,1:180]
<br>:27:: | PROPERTY_OR_IDENTIFIER ::[@-1,0:0='PROPERTY_OR_IDENTIFIER',<27>,0:-1]<br>:94:: | b ::[@-1,'b',<94>,1:187]<br>:94:: | currentValue ::[@-1,'currentValue',<94>,1:189]
<br><br><br>print(typeSpec) //getChild from a VAR_DEF node<br>:18:: | : ::[@-1,0:0=':',<18>,5:31]<br>:48:: | IDENTIFIER ::[@-1,0:0='IDENTIFIER',<48>,0:-1]
<br>:94:: | int ::[@-1,'int',<94>,5:33]<br><br><br><br><br>2. Sometimes, setting over a child doesn't work, but removing the child and putting in another does.<br><br>
For example, when assigning to a var in a function, let's say I want to replace the rhs (new eventStream()) of one of the getterTemplate variables above:<br><br>.setChildWithTokens throws <br><br>java.lang.IllegalArgumentException
: No startToken: +<br> at uk.co.badgersinfoil.metaas.impl.antlr.BasicListUpdateDelegate.replacedChild(BasicListUpdateDelegate.java:220)<br> at uk.co.badgersinfoil.metaas.impl.antlr.LinkedListTree.setChildWithTokens(
LinkedListTree.java:134)<br><br>//bad<br>((LinkedListTree)getterTemplate.getChild(6).getChild(1).getChild(1)<br> .getChild(0).getChild(0))<br> .setChildWithTokens(2, (LinkedListTree)varAssign.getChild(0).dupTree());
<br><br>but removing the old rhs and then adding the new seems to work:<br><br>//good<br>LinkedListTree elist = <br> (LinkedListTree) getterTemplate.getChild(6).getChild(1).getChild(1)<br> .getChild(0).getChild(0);
<br> elist.deleteChild(2);<br> elist.addChildWithTokens(2, (LinkedListTree) varAssign.getChild(0));<br><br>Hopefully there's some magic refresh call I should be calling after these transforms and I don't have to do any character munging. I'm still stuck on copying nodes (problem 1) but randomly permuting code (2) has eventually worked so far. Thoughts?
<br><br>Anyways, very useful project :)<br><br>Thanks,<br><br>- Leo<br>