Archive

Archive for September 16th, 2010

asblocks & asbuilder update :: as3 code creation impl complete

September 16th, 2010 Michael Schmalle 3 comments

Hi,

Just thought I would pass along the example below to show where this project is at. I have worked really hard the last week to implement most of the actionscript 3 code creation.

I have also refactored the asdoc parser to use a linked list. This allows complete control over the ast after it is created and during creation with ast utilities.

I’m working on a little turnkey project that will show devs how to implement the libraries. The below code is included in this project;

GIT Repos

  • asblocks – AST and bloc read-write
  • asbuilder – AIR specific implementations (requires asblocks)

Code:

private var factory:ASFactory; 
 
protected function createProject():void
{
	factory = new ASBuilderFactory();
 
	var project:IASProject = factory.newEmptyASProject(
		File.desktopDirectory.resolvePath("test_src").nativePath);
 
	var classA:ICompilationUnit = project.newClass("my.domain.ClassA");
	var interfaceA:ICompilationUnit = project.newInterface("my.domain.IInterfaceA");
 
	var doc:IDocComment;
	var tag0:IDocTag;
	var tag1:IDocTag;
 
	var ctype:IClassType = IClassType(classA.typeNode);
	ctype.superClass = "ClassB";
	ctype.addImplementedInterface("IInterfaceA");
	ctype.addImplementedInterface("IInterfaceB");
 
	ctype.description = "A class documentation comment\nwith multiple lines.";
	doc = ctype.documentation;
	tag0 = doc.newDocTag("see", "my.other.Class");
	tag1 = doc.newDocTag("author", "Mike Schmalle <mschmalle@teotigraphix.com>");
 
	// add metadata
	var event:IMetaData = ctype.newMetaData("Event");
	event.description = "A class documentation comment\nwith multiple lines.";
 
	tag0 = event.documentation.newDocTag("see", "ClassB#event:myOtherEvent");
 
	event.addNamedStringParameter("name", "myEvent");
	event.addNamedStringParameter("type", "flash.events.Event");
 
	var defaultProperty:IMetaData = ctype.newMetaData("DefaultProperty");
	defaultProperty.addNamedStringParameter("defaultValue", "dataProvider");
 
	ctype.newMetaData("Bindable");
 
	createField(ctype);
	createStaticField(ctype);
	createStaticConstant(ctype);
 
	createMethod(ctype);
	createFinalMethod(ctype);
	createStaticMethod(ctype);
	createGetMethod(ctype);
	createSetMethod(ctype);
	createComplexMethod(ctype);
 
	walkUnit(classA);
 
	project.writeAll();
}
 
protected function walkUnit(unit:ICompilationUnit):void
{
	var visitor:IASVisitor = new TestVisitor();
	var walker:IASWalker = new ASWalker(visitor);
	walker.walkCompilationUnit(unit);
}
 
protected function createField(type:IClassType):void
{
	var f:IField = type.newField("field", Visibility.PUBLIC, "int");
	f.description = "An integer field.";
	var tag0:IDocTag = f.documentation.newDocTag("productversion", "1.0");
}
 
protected function createStaticField(type:IClassType):void
{
	var f:IField = type.newField("STATIC_FIELD", Visibility.PUBLIC, "int");
	f.isStatic = true;
	f.initializer = exp("42");
}
 
protected function createStaticConstant(type:IClassType):void
{
	var f:IField = type.newField("CONSTANT_FIELD", Visibility.PROTECTED, "int");
	// change field to static
	f.isStatic = true;
	// change field to a constant
	f.isConstant = true;
	// set the initializer
	f.initializer = exp("42");
}
 
protected function createMethod(type:IClassType):void
{
	var m:IMethod = type.newMethod("method", Visibility.PUBLIC, "void");
 
	// add parameters
	m.addParameter("arg0", "int");
	m.addParameter("arg1", "int", "42");
	m.addRestParam("rest");
 
	// change type 
	m.type = "String";
	m.addComment("TODO implement method");
	// add a return
	m.newReturn(factory.newExpression("null"));
}
 
protected function createFinalMethod(type:IClassType):void
{
	var m:IMethod = type.newMethod("methodFinal", Visibility.PUBLIC, "void");
}
 
protected function createStaticMethod(type:IClassType):void
{
	var m:IMethod = type.newMethod("methodStatic", Visibility.PUBLIC, "void");
	m.isStatic = true;
}
 
protected function createGetMethod(type:IClassType):void
{
	var m:IMethod = type.newMethod("property", Visibility.PUBLIC, "int");
	m.accessorRole = AccessorRole.GETTER;
	m.newReturn(factory.newNumberLiteral(-1));
}
 
protected function createSetMethod(type:IClassType):void
{
	var m:IMethod = type.newMethod("property", Visibility.PUBLIC, "void");
	m.addParameter("value", "int");
	m.accessorRole = AccessorRole.SETTER;
}
 
protected function createComplexMethod(type:IClassType):void
{
	var m:IMethod = type.newMethod("complex", Visibility.PRIVATE, "void");
	// add an if() statement
	var ifstmt:IIfStatement = m.newIf(exp("i < len && hasNext()"));
	// add a var declaration
	var dc:IDeclarationStatement = ifstmt.parseNewDeclaration("len:int = 2");
	// make it a constant
	dc.isConstant = true;
	// add a for() statement
	var forstmt:IForStatement = ifstmt.parseNewFor("var i:int = 0", "i < len", "i++");
	// add a switch() statement
	var swstmt:ISwitchStatement = forstmt.newSwitch(exp("name"));
	// add a case to the switch
	var cs1:ISwitchCase = swstmt.newCase("\"one\"");
	cs1.newBreak();
	// add a case to the switch
	var cs2:ISwitchCase = swstmt.newCase("\"two\"");
	var ifstmt2:IIfStatement = cs2.newIf(exp("i == 2"));
	// add a single lin comment
	ifstmt2.addComment("Trace the result");
	ifstmt2.addStatement("trace('Hello Two')");
	cs2.newBreak();
	// add a default to the switch
	var dfstmt:ISwitchDefault = swstmt.newDefault();
	dfstmt.newThrow(exp("new Error('Error here')"));
}
 
private function exp(expression:String):IExpression
{
	return factory.newExpression(expression);
}

Output:

package my.domain {
	/**
	 * A class documentation comment
	 * with multiple lines.
	 * @see ClassB#event:myOtherEvent
	 */
	[Event(name="myEvent",type="flash.events.Event")]
	[DefaultProperty(defaultValue="dataProvider")]
	[Bindable]
	/**
	 * A class documentation comment
	 * with multiple lines.
	 * @see my.other.Class
	 * @author Mike Schmalle <mschmalle@teotigraphix.com>
	 */
	public class ClassA extends ClassB implements IInterfaceA, IInterfaceB {
		/**
		 * An integer field.
		 * @productversion 1.0
		 */
		public var field:int;
		public static var STATIC_FIELD:int = 42;
		protected static const CONSTANT_FIELD:int = 42;
		public function method(arg0:int, arg1:int = 42):String {
			//TODO implement method
			return null;
		}
		public function methodFinal():void {
		}
		public static function methodStatic():void {
		}
		public get function property():int {
			return -1;
		}
		public set function property(value:int):void {
		}
		private function complex():void {
			if (i < len && hasNext()) {
				const len:int = 2;
				for (var i:int = 0; i < len; i++) {
					switch (name) {
						case "one":
							break;
						case "two":
							if (i == 2) {
								//Trace the result
								trace('Hello Two');
							}
							break;
						default:
							throw new Error('Error here');
					}
				}
			}
		}
	}
}

Mike

Categories: Uncategorized Tags: