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.
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.
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;
const x: Number = Math.random();
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.
public class Foo()
public function Foo()
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?
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.
According to Erik T.,
Loose global statements like the example get executed whenever the VM decides to run the script init code for that script block. This is usually when a type defined in that script is first referenced. So, if you have global statements in multiple files they could execute in different order based on which code path is taken.
Specifically, for the example below, class inits get hoisted to the top of the script init, so the code will init all the classes, and then run the rest of the script init. The class initialization will run the static initializer for the class, so it shows up first because it got hoisted to the top.
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?
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.
One of the areas currently under development in the Asc Parser is the Node class and the shape of the AST built.
One of the existing Node visitor patterns is likely adaptable for your current purposes.
Again, the existing Node classes are subject to change in the very near future and I can almost guarantee that any work
based on the current intermediate representation will be incompatible with ongoing work
Thank you for your quick replies!
I know that the compiler was open sourced not long ago and was wondering if there was any plans to publish a roadmap for the compiler?
I was hoping for docs, future requirements or just a heads up of what is going on.
I think publishing these things would encourage more people to take part. I would love to get involved but feel like I need a little helping hand to get started and some idea of where the compiler is going? does this sound possible and in line with Adobe's plans?
It'd be fun to have a lot of people working on the compiler. First we need to get some basic components down to simpler representations.
The Node class and the way ast's get built and used can be much improved, we're working on that now. It's so fundamental it's hard to start parallel efforts until that is complete. We're hoping to start defining a clearer roadmap within the next few weeks.