[metaas-dev] parse tree manipulation

Leo Meyerovich Leo_Meyerovich at brown.edu
Mon Jul 23 20:43:01 UTC 2007


Hiya,

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:

1. dupTree doesn't entirely duplicate a tree:

 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

java.lang.IllegalArgumentException: No startToken: IDENTIFIER
    at
uk.co.badgersinfoil.metaas.impl.antlr.BasicListUpdateDelegate.replacedChild(
BasicListUpdateDelegate.java:220)
    at
uk.co.badgersinfoil.metaas.impl.antlr.LinkedListTree.setChildWithTokens(
LinkedListTree.java:134)

Context:

//good, not dup'ing the source
((LinkedListTree) getterTemplate.getChild(5)).setChildWithTokens(
                        0, (LinkedListTree) typeSpec.getChild(0));
//bad, dup'ing the source
((LinkedListTree) getterTemplate.getChild(5)).setChildWithTokens(
                        0, (LinkedListTree) typeSpec.getChild(0).dupTree());

//context
print(getterTemplate): //trying to replace type annotation  :* on lines
13-14
:6::: |  METHOD_DEF
::[@-1,0:0='METHOD_DEF',<6>,0:-1]
:8:::  |  ANNOTATIONS
::[@-1,0:0='ANNOTATIONS',<8>,0:-1]
:9:::   |  ANNOTATION
::[@-1,0:0='ANNOTATION',<9>,0:-1]
:94::    |  Bindable
::[@-1,'Bindable',<94>,1:1]
:9:::   |  ANNOTATION
::[@-1,0:0='ANNOTATION',<9>,0:-1]
:94::    |  Bindable
::[@-1,'Bindable',<94>,5:6]
:12::  |  MODIFIERS
::[@-1,0:0='MODIFIERS',<12>,0:-1]
:95::   |  public                                 ::[@-1,'public',<95>,5:16]
:64::  |  function
::[@-1,'function',<64>,1:11]
:65::   |  get                                    ::[@-1,'get',<65>,1:20]
:94::  |  d                                       ::[@-1,'d',<94>,1:24]
:16::  |  PARAMS
::[@-1,0:0='PARAMS',<16>,0:-1]
:18::  |  :                                       ::[@-1,0:0=':',<18>,1:29]
:91::   |  *                                      ::[@-1,'*',<91>,1:31]
:19::  |  BLOCK
::[@-1,0:0='BLOCK',<19>,0:-1]
:69::   |  var                                    ::[@-1,'var',<69>,1:35]
:94::    |  b                                     ::[@-1,'b',<94>,1:39]
:18::     |  :                                    ::[@-1,0:0=':',<18>,1:41]
:48::      |  IDENTIFIER
::[@-1,0:0='IDENTIFIER',<48>,0:-1]
:94::       |  Behaviour
::[@-1,'Behaviour',<94>,1:43]
:71::     |  =                                    ::[@-1,'=',<71>,1:53]
:26::      |  METHOD_CALL
::[@-1,0:0='METHOD_CALL',<26>,0:-1]
:27::       |  PROPERTY_OR_IDENTIFIER
::[@-1,0:0='PROPERTY_OR_IDENTIFIER',<27>,0:-1]
:94::        |  SignalEngine
::[@-1,'SignalEngine',<94>,1:55]
:94::        |  binding
::[@-1,'binding',<94>,1:68]
:22::       |  ARGUMENTS
::[@-1,0:0='ARGUMENTS',<22>,0:-1]
:20::        |  ELIST
::[@-1,0:0='ELIST',<20>,0:-1]
:94::         |  this                             ::[@-1,'this',<94>,1:76]
:63::         |  'd'                              ::[@-1,''d'',<63>,1:82]
:75::   |  if                                     ::[@-1,'if',<75>,1:89]
:21::    |  CONDITION
::[@-1,0:0='CONDITION',<21>,0:-1]
:141:     |  !                                    ::[@-1,'!',<141>,1:93]
:94::      |  b                                   ::[@-1,'b',<94>,1:94]
:19::    |  BLOCK
::[@-1,0:0='BLOCK',<19>,0:-1]
:23::     |  EXPR_STMNT
::[@-1,0:0='EXPR_STMNT',<23>,0:-1]
:20::      |  ELIST
::[@-1,0:0='ELIST',<20>,0:-1]
:94::       |  b                                  ::[@-1,'b',<94>,1:101]
:71::       |  =                                  ::[@-1,'=',<71>,1:103]
:152:       |  new                                ::[@-1,'new',<152>,1:105]
:94::        |  EventStream
::[@-1,'EventStream',<94>,1:109]
:22::        |  ARGUMENTS
::[@-1,0:0='ARGUMENTS',<22>,0:-1]
:23::     |  EXPR_STMNT
::[@-1,0:0='EXPR_STMNT',<23>,0:-1]
:20::      |  ELIST
::[@-1,0:0='ELIST',<20>,0:-1]
:26::       |  METHOD_CALL
::[@-1,0:0='METHOD_CALL',<26>,0:-1]
:27::        |  PROPERTY_OR_IDENTIFIER
::[@-1,0:0='PROPERTY_OR_IDENTIFIER',<27>,0:-1]
:94::         |  SignalEngine
::[@-1,'SignalEngine',<94>,1:143]
:94::         |  bind                             ::[@-1,'bind',<94>,1:156]
:22::        |  ARGUMENTS
::[@-1,0:0='ARGUMENTS',<22>,0:-1]
:20::         |  ELIST
::[@-1,0:0='ELIST',<20>,0:-1]
:94::          |  this                            ::[@-1,'this',<94>,1:161]
:63::          |  'd'                             ::[@-1,''d'',<63>,1:167]
:94::          |  b                               ::[@-1,'b',<94>,1:172]
:77::   |  return
::[@-1,'return',<77>,1:180]
:27::    |  PROPERTY_OR_IDENTIFIER
::[@-1,0:0='PROPERTY_OR_IDENTIFIER',<27>,0:-1]
:94::     |  b                                    ::[@-1,'b',<94>,1:187]
:94::     |  currentValue
::[@-1,'currentValue',<94>,1:189]


print(typeSpec) //getChild from a VAR_DEF node
:18:: |  :                                        ::[@-1,0:0=':',<18>,5:31]
:48::  |  IDENTIFIER
::[@-1,0:0='IDENTIFIER',<48>,0:-1]
:94::   |  int                                    ::[@-1,'int',<94>,5:33]




2. Sometimes, setting over a child doesn't work, but removing the child and
putting in another does.

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:

.setChildWithTokens throws

java.lang.IllegalArgumentException: No startToken: +
    at
uk.co.badgersinfoil.metaas.impl.antlr.BasicListUpdateDelegate.replacedChild(
BasicListUpdateDelegate.java:220)
    at
uk.co.badgersinfoil.metaas.impl.antlr.LinkedListTree.setChildWithTokens(
LinkedListTree.java:134)

//bad
((LinkedListTree)getterTemplate.getChild(6).getChild(1).getChild(1)
                    .getChild(0).getChild(0))
                    .setChildWithTokens(2,
(LinkedListTree)varAssign.getChild(0).dupTree());

but removing the old rhs and then adding the new seems to work:

//good
LinkedListTree elist =
                    (LinkedListTree) getterTemplate.getChild
(6).getChild(1).getChild(1)
                        .getChild(0).getChild(0);
                elist.deleteChild(2);
 elist.addChildWithTokens(2, (LinkedListTree) varAssign.getChild(0));

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?

Anyways, very useful project :)

Thanks,

- Leo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.badgers-in-foil.co.uk/pipermail/metaas-dev/attachments/20070723/f519639b/attachment.htm 


More information about the metaas-dev mailing list