Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 10 Next »

Metadata

Number:

GEP-2

Title:

AST Builder Support

Version:

2

Type:

Feature

Target:

1.7

Status:

Draft

Leader:

Hamlet D'Arcy

Created:

2009-04-01

Last modification:

2009-04-11

Abstract

Groovy 1.6 introduced the ability to perform local and global AST (Abstract Syntax Tree) transformations, allowing users to read and modify the AST of Groovy code as it is being compiled. Reading information in the AST is relatively easy in Groovy. The core library provides a strongly typed visitor called GroovyCodeVisitor. Nodes can be read and modified using the API provided through the subtypes of ASTNode. Writing new AST nodes is not as simple. The AST generated from source is not always obvious, and using constructor calls to generate trees of nodes can be verbose. This GEP proposes an ASTBuilder object that allows users to easily create AST.

The ASTBuilder object allows AST to be created from Strings containing Groovy source code, from a closure containing Groovy source, and from a closure containing an AST creation DSL.

Approach

ASTNode from String

 The simplest approach to an AST Builder is an API that takes a String and returns ASTNode.

  • phase property tells the builder from which phase to return AST
  • returnScriptBodyOnly property tells the builder to discard any generated top level ClassNode elements
  • source property is the String to use as input

The above example produces the following AST:

 Issues

  • Is there a logical default on which CompilePhase is used? Providing a default clean up the API for the common case.
  • Compiling a code snippet typically results in the meaningful AST being wrapped in 2 levels of BlockStatement. Should we provide a way to discard the top level BlockStatement? A way to discard both? Manually discarding the topmost BlockStatement would be repetitive but not unbearable.
  • Compiling a code snippet typically results in a Script subclass being generated. Should we provide a way to discard this? A "returnScriptBodyOnly" property on the builder could be used to discard the Script ClassNode. Supporting this property would mean that build() sometimes returns an ASTNode and sometimes returns a List<ASTNode>. Are covariant return types acceptable? 
  • Is some sort of AST Template needed? Consider the following example:

ASTNode from Code Block

ASTNode from psuedo-specification

  • Simply using the @Newify annotation does not sufficiently improve the syntax; therefore, this type of feature is needed
  • Building AST conditionally, such as inserting an if-statement or looping, is not easily accomplished in the String and code based builders. Consider this example:

Alternatives

Template Haskell and Boo provide a special syntax for AST building statements. Quasi-quote (or Oxford quotes) can be used to trigger an AST building operation:

 Those languages also supply a splice operator $(...) to turn AST back into code.

References

Mailing-list discussions

JIRA issues

  • Pending

Reference Implementation

http://code.assembla.com/AstBuilderPrototype

  • No labels