package elide;

An Introduction to ELIDE Concepts

import download.elide;

class Documentation
{
       /** ELIDE Javadoc */	


   String introduction;
   String tutorial;
}
Lightweight Java Syntax Extensions
ELIDE provides a single, simple syntactic extension to the Java language: it permits a developer to introduce new, custom defined modifiers for classes, fields, and methods. These are used identically to the standard Java modifiers such as public, private, and synchronized, and can be freely intermixed with them.
class Introduction
  extends Documentation
{
   void syntax();
   void semantics();
   void ordering();
}
The effects of these modifiers can be essentially arbitrary generation and manipulation of code. A very simple use might be to mark a particular field as a JavaBeans property, and so generate the required accessor methods. Such a field declaration might look like
	private property<> String name;
Unlike the standard modifiers, user defined modifiers must be followed by a (possibly empty) parameter list enclosed in angle brackets. For example, a modifier might mark a class as participating in the visitor pattern, and identify which visitor class it interacts with:
	public visited<NodeVisitor> class ParseNode { ... }
A modifier can take any number of parameters, or a varying number. Parameters can be type names, string literals, or code snippets, which are enclosed in an extended string literal syntax introduced for ELIDE:
	precondition<"positive", %{ x > 0 }%>
	void someMethod(int x)
	{
		...
	}
The %{}% string literal syntax permits the use of any Java characters without requiring any special escaping.

Like the synchronized modifier, custom modifiers can also enclose arbitrary blocks of code. For instance, the following idiom

	try {
		...
	} catch(SomeException e) {
		logException(e);
		throw e;
	}
could be captured by
	logException<SomeException> {
		...
	}
Defining the Semantics
1. Complete transformation behavior is specified by Java classes

The semantics for ELIDE modifiers are specified with Java classes. For example, to add the modifier visited<SomeVisitor>, a developer would write:

public class Visited extends Transform
{
	// behavior
}
where Transform is the base class for all ELIDE transformations. This approach provides developers with all of the benefits of the OO paradigm: Transformations can inherit behavior from other transformations, and the behavior can be cleanly encapsulated. As well, this allows a degree of consistency among transformation specifications and the base code.

2. Individual 'atoms' of behavior for a given transform are specified by methods on these classes

A given transformation may involve a number of separate operations. For example, the visited<> modifier both adds an appropriate visit() method to the visitor and adds an accept() method to the visited class. These are represented by the methods addVisited() and addAccept(), giving us the following:

public class Visited extends Transform
{
	public void addVisited(ClassNode target, String visitorName) {...}

	public void addAccept(ClassNode target, String visitorName) {...}
}
Each of these methods takes as their first argument an object representing the "target" of the transformation, the entity in the source code to which the modifier was attached (in this case a class modified by visited<SomeVisitor>). The remaining arguments correspond to any parameters that appeared within the angle brackets of the modifier. The transformation methods can be overloaded both on target type and on number of arguments. For example, the modifier
	synchronized<> class MyClass { ... }
would try to invoke any methods of Synchronized that took a ClassNode and no other arguments, whereas
	synchronized<globalLock> void reset() { ... }
would try to invoke any methods of Synchronized that took a MethodNode and a single String.

3. Implementing transform behavior

ELIDE allows developers to implement transform behavior in several ways, all designed to provide as much convenience and familiarity as possible. The basic API builds on that provided by java.lang.reflect, providing accessor methods such as getDeclaringClass(), getModifiers(), getDeclaredFields(), etc. and adding mutator functionality such as add(someNode), makePublic(), ... This API can be quite useful for simple transformations (or as part of more complex ones). For example, a simple method on a transform that makes all fields of a class private could be written as:

	public void makeAllFieldsPrivate(ClassNode target)
	{
		FieldNode[] fields = target.getDeclaredFields();
		for(int i = 0; i < fields.length; i++)
			fields[i].makePrivate();
	}
For more complex transformation methods, such as those that add methods to classes, a more convenient representation is helpful. Using the extended string literal syntax, blocks of code, methods, or entire classes can be specified in a code template, which allows developers to write transformations in a more familiar way. For example, addAccept() could be written as:
	public void addAccept(ClassNode target, String visitorName)
	{
		target.extend(
		%{
			public void accept(#{visitorName}# visitor)
			{
				visitor.visit(this);
			}
		}%);

	}
The #{}# delimiters provide "holes" in the string literal where arbitrary code can be inserted. This can be used simply to insert the value of a variable, as we have done here, or to perform more complex computations.
Simple Dependency Management
When performing several transformations on the same piece of code, the order in which the transformations execute can have a large effect. As a simple example, consider two transformations: one, allAccessors<>, which adds accessor methods for every field in a class, and another, fullySynchronized<>, which adds the synchronized modifier to each of a type's methods. If fullySynchronized<> occurs before allAccessors<>, then the introduced accessor methods will be unsynchronized.

For this reason, ELIDE provides a simple dependency system for modifiers. Each transformation method is marked with a list of dependencies that it satisfies, and a list that it requires. The system ensures that, for every named dependency, every transformation method marked as satisfying it executes before any transformations marked as requiring it do. Note that the dependency graph is a partial ordering: if two transformation methods belong to the same set of dependencies, their order of evaluation is undefined.

Transformation methods are marked with the satisifies<> and requires<> modifiers built into ELIDE. The example above could be disambiguated by introducing a "methodDefinition" dependency:

//in FullySynchronized
public requires<methodDefinition> synchronizeAllMethods() { ... }

//in AllAccessors
public satisfies<methodDefinition> addAllAccessorMethods() { ... }
This would ensure that addAllAccessorMethods(), as well as any other transformation methods marked satisfies<methodDefinition>, executes before synchronizeAllMethods() does.