Skip to main content
Participant
May 16, 2009
Answered

ASC questions

  • May 16, 2009
  • 2 replies
  • 6567 views

Hey,

after some time of playing with the ASC classes I have got some questions regarding the Parser and how to put everything together.

- The Parser does not know about block statements. Is there a reason for that? In parseBlock you just generate a StatementListNode but it would be great to know if those statements have been wrapped wih braces. Especially when you are going to support the let statement. This would be more a feature request. In general: it would be great if one could override any method of Parser. Parser is currently not a final class and most of the methods are private.

- Is it correct that the Context is unique to a compilation unit while the ContextStatics are true for all units? If so, it seems like the global scope is built for each unit. Any reason for that or could I keep that static as well?

- When compiling a single class I need to include of course builtin.abc, playerglobal.abc and toplevel.abc. This leads always to a cyclic dependency when using also the FlowAnalyzer. What is the general strategy one has to follow in order to compile?

- The only thing I really want is the AST from a compilation unit. The OEM version does not offer this feature and I can not see any other class that wold simply return me the ProgramNode instead of emitting any byte code. That is why I try triggering the Parser manually. Is there another way to get to the AST? I mean, I do not want to touch any class or rewrite the code at any position because this would probably break with updates so right now I link only against the asc.jar. This works currently for me pretty good, but I do not have the LintEvaluator or FlowAnalyzer running because of the cyclic dependency problem.

Best,

Joa

This topic has been closed for replies.
Correct answer pmd12345

General disclaimer:

We’re considering restructuring this code in the near future and can’t guarantee that your work will be compatible with future versions.

1. The Parser does not know about block statements. Is there a reason for that?

     None that I'm aware of. I agree, a block node is a good idea. Even if the semantics of a statement-list are exactly the same, we can't recover the      original source once this simplification occurs.

2. let statement.

     I'm not sure about the future of the let statement given ECMA "Harmony".

3. Overriding Parser methods.

     I disagree. It would be better for reusability and stability if the Parser/Scanner module's sole function was to verify syntax

     and produce an AST. Given future requirements for compile performance, we may need several parsing solutions.

4. Multiple context classes and global scope confusion.

     I agree. I'm looking at some of this code now. It's unnecessarily complex.

5. What is the general strategy one has to follow in order to compile?

     Refer to CompilerAPI.java. There's a general workflow model defined there.

6. Is there another way to get to the AST?

     If you're interested in a single AST (per file) I think your approach is reasonable. By invoking an instance of the Asc parser directly, you've simplified significantly. However, you could pick up the AST form at later compile stages, which might have completed some transformations and semantic analysis that would be of some use to you. Most code referring to the AST uses some derivation of the Evaluator pattern.

2 replies

June 23, 2009

I think i want to do the same thing.  I was an AST in xml form.

I have a different approach though.

I am using the asdoc tool and am using the keep xml option.  I am then adding methods to the *Node classes that return sensible structures.  These are being called in the TopLevelGenerator class.

I am worried that i am adding code to classes that are likely to change with future versions.  Is there anything else i can do? Is this a good approach?

TIA

Eamonn

joa__Author
Participant
June 23, 2009

One Evaluator already outputs XML. I forgot the name and location but basically you can have a look at macromedia.asc.parser.NodePrinter to figure out how it works.

I think the XML evaluator was located somewhere in the compiler package (not asc) but maybe I am mistaken.

Best,

Joa

pmd12345Correct answer
Participating Frequently
May 17, 2009

General disclaimer:

We’re considering restructuring this code in the near future and can’t guarantee that your work will be compatible with future versions.

1. The Parser does not know about block statements. Is there a reason for that?

     None that I'm aware of. I agree, a block node is a good idea. Even if the semantics of a statement-list are exactly the same, we can't recover the      original source once this simplification occurs.

2. let statement.

     I'm not sure about the future of the let statement given ECMA "Harmony".

3. Overriding Parser methods.

     I disagree. It would be better for reusability and stability if the Parser/Scanner module's sole function was to verify syntax

     and produce an AST. Given future requirements for compile performance, we may need several parsing solutions.

4. Multiple context classes and global scope confusion.

     I agree. I'm looking at some of this code now. It's unnecessarily complex.

5. What is the general strategy one has to follow in order to compile?

     Refer to CompilerAPI.java. There's a general workflow model defined there.

6. Is there another way to get to the AST?

     If you're interested in a single AST (per file) I think your approach is reasonable. By invoking an instance of the Asc parser directly, you've simplified significantly. However, you could pick up the AST form at later compile stages, which might have completed some transformations and semantic analysis that would be of some use to you. Most code referring to the AST uses some derivation of the Evaluator pattern.

joa__Author
Participant
May 18, 2009

Thank you for the quick answer.

If overriding methods of the Parser is not an option that is okay with me.  I was just thinking about block statements and the possibility to insert that functionality for myself.

I have also another question. How are you going to handle this case in the near future?

var i: int = 0;

var n: int = 0xff;


for(;i<n;++i)

{

  const x: Number = Math.random();

  trace(x);

}

This will result in an RTE since x has been declared const and is changed inside the loop. Regarding the lack of scopes in ECMAScript this is of course correct since x is redefined for every iteration of i. But it is very confusing and should be checked at compile time.

Another question I have is about the package scope.

package

{

  trace("static ctor0");


  public class Foo()

  {

    trace("static ctor1");


    public function Foo()

    {

      trace("instance ctor");

    }

  }

}

This will output for new Foo() "static ctor1", "static ctor0", "instance ctor". Why is the package level statement sitting inside the static initializer of the class and why is it executed after the "ctor1" trace?

Best,

Joa

Participating Frequently
May 18, 2009

Having Asc parser internal methods private allows us to improve it more safely. The existing node form may be simplified as well, which is a major overhaul.  If you're considering a feature of general usefulness we might be able to incorporate it as part of ongoing development, else your probably better off branching, since it'll break anyway.

Detection of const declarations within loop constructs:

I'd add the warning at a lint level, since without some dynamic programming (or known tripcount) even flow analysis wont tell you that the loop is intended to execute only once (which would be legal).

Class constructor invocation order:

I think the real question is, "When do package global statements get executed?".

--I'll get back to you on this one.