Smart Java to ActionScript 3 translator in progress

I thought: Now I have programmed Java for many years, how about trying out this Flash and ActionScript thing? Expand my horizon, try new things is refreshing etc.

Full of hope I downloaded the newest Flash Builder. They use Eclipse! I guess they have implemented all that amazing refactoring and quick fix that I use everyday!?

Well, some of you know the answer: Flash Builder is just a weak, distorted shadow of what the Eclipse tools for Java is.

Long story short: Want to program in java and translate to Actionscript 3 (similar to the Google app engine).
Existing tool: j2as (broken link to source)
My approach: use japa Java parser. Add a lot of stubs for Actionscript classes. Create Actionscript classes to mimic ArrayList, HashMap, HashSet etc.

Here is a link to the current version (which also contains an applet):

http://www.springworldgames.com/javatoas3/

Here is the link to the current version of the source code:

http://www.springworldgames.com/javatoas3/

It is just a very simple quick and dirty translator at the moment without any ActionScript classes and Java stubs.
I guess that most of the translation will be easy since ActionScript is very similar to a subset of Java. Some decisions has to be made about the function references that are used all the time in ActionScript for handlers. I guess that a special Java-interface will do the trick but we’ll see…

There has been few heroic attempts at this in the past but most have failed. Does look as if you still have tons of work to do before its usable but do keep us updated.

I have coded a bit more and just want to show some of the progress.

The following is what you write in Java (and it compiles with the help from stub classes):


package com.springworldgames.javatoas3.testfiles;

import com.springworldgames.javatoas3.as3replacers.EventFunction;

import flash.display.BlendMode;
import flash.display.CapsStyle;
import flash.display.Graphics;
import flash.display.LineScaleMode;
import flash.display.Sprite;
import flash.events.Event;
import flash.ui.Mouse;

public class ch7ex1 extends Sprite {

	protected Sprite compass;
	protected Sprite crosshairs;

	public ch7ex1() {
		drawCompass();
		drawCrosshairs();
		addEventListener(Event.ENTER_FRAME, tick);
	}

	EventFunction tick = new EventFunction() {
		@Override
		public void eventFunction(Event event) {
			Mouse.hide();
			crosshairs.x = stage.mouseX;
			crosshairs.y = stage.mouseY;
			compass.rotation = Math.atan2(stage.mouseY - compass.y,
					stage.mouseX - compass.x)
					* 180 / Math.PI;
		}
	};
	
	protected void drawCompass() {
		double RADIUS = 30;
		compass = new Sprite();
		Graphics g = compass.graphics;
		g.lineStyle(4, 0xe03030);
		g.beginFill(0xd0d0d0);
		g.drawCircle(0, 0, RADIUS);
		g.endFill();
		g.moveTo(0, 0);
		g.lineTo(RADIUS, 0);
		addChild(compass);
		compass.x = stage.stageWidth / 2;
		compass.y = stage.stageHeight / 2;
	}

	protected void drawCrosshairs() {
		double SIZE = 10;
		crosshairs = new Sprite();
		Graphics g = crosshairs.graphics;
		g
				.lineStyle(8, 0x4040f0, 1, false, LineScaleMode.NONE,
						CapsStyle.SQUARE);
		g.moveTo(0, SIZE);
		g.lineTo(0, -SIZE);
		g.moveTo(SIZE, 0);
		g.lineTo(-SIZE, 0);
		crosshairs.blendMode = BlendMode.MULTIPLY;
		addChild(crosshairs);
	}
}



The following is the ActionScript 3 result:



package com.springworldgames.javatoas3.testfiles {
    import flash.display.BlendMode;
    import flash.display.CapsStyle;
    import flash.display.Graphics;
    import flash.display.LineScaleMode;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.ui.Mouse;

    public class ch7ex1 extends Sprite {

        protected var compass:Sprite;

        protected var crosshairs:Sprite;

        public function ch7ex1() {
            drawCompass();
            drawCrosshairs();
            addEventListener(Event.ENTER_FRAME, tick);
        }

        public function tick(event:Event):void {
            Mouse.hide();
            crosshairs.x = stage.mouseX;
            crosshairs.y = stage.mouseY;
            compass.rotation = Math.atan2(stage.mouseY - compass.y, stage.mouseX - compass.x) * 180 / Math.PI;
        }

        protected function drawCompass():void {
            var RADIUS:Number = 30;
            compass = new Sprite();
            var g:Graphics = compass.graphics;
            g.lineStyle(4, 0xe03030);
            g.beginFill(0xd0d0d0);
            g.drawCircle(0, 0, RADIUS);
            g.endFill();
            g.moveTo(0, 0);
            g.lineTo(RADIUS, 0);
            addChild(compass);
            compass.x = stage.stageWidth / 2;
            compass.y = stage.stageHeight / 2;
        }

        protected function drawCrosshairs():void {
            var SIZE:Number = 10;
            crosshairs = new Sprite();
            var g:Graphics = crosshairs.graphics;
            g.lineStyle(8, 0x4040f0, 1, false, LineScaleMode.NONE, CapsStyle.SQUARE);
            g.moveTo(0, SIZE);
            g.lineTo(0, -SIZE);
            g.moveTo(SIZE, 0);
            g.lineTo(-SIZE, 0);
            crosshairs.blendMode = BlendMode.MULTIPLY;
            addChild(crosshairs);
        }
    }
}


The example is from the ActionScript 3.0 Bible second edition. I think I will go through all the examples in that book and try to translate Java code into them.

I am aware that it will not become a general tool for all possible ways to work with ActionScript and Java, but hopefully it will transform into a fairly useful compromise.

There is now an applet available for the translator.

The translation is purely syntax-based at the moment so don’t expect to much :slight_smile:

The real power (if any) of this approach is when you use it together with Eclipse/Netbeans/Idea with all the stubs (see the source code).

The number of stubs has increased a lot since the last post.

You should do a static import of TopLevel, assuming that JavaParser supports that.

Also, setWithIndex(key, val) feels way too verbose, why not use put(key, val) ?

Static import is supported by the parser, so that is a good idea :slight_smile:

I use a similar trick for functions that aren’t part of any class (just a package) but then I also add an extra import.

I would love to use put() instead of the more verbose setWithIndex() but then I have to keep track of the type of all expressions and I haven’t implemented anything like that. The current version just knows whether it is a method name or not from the syntax tree and boldly and blindly replaces it if it matches. The “Smart” prefix of this thread just became a big fat lie :slight_smile:

I don’t know how difficult it is to perfom type analysis, but I’ll give it a try! This would really make the whole thing better and unlock possibilties.

Edit: You have to gather a lot of information from all imported classes, both from source and jar-files, to do type analysis in a general way. I might just apply the KISS principle, even if it is ugly.

Maybe use:

map.$put(key, val) list.$add(item)

or

map._put(key, val) list._add(item)

I know it looks a lot like PHP / C, but at least it’s short, and unique…? :persecutioncomplex:

Good idea Riven!

I think I will change it to put$(key, val) and get$(key) for Arrays, Objects and Dictionaries. For Vectors I will use set$(index, val) and get$(index).

BTW, I have also added the possibility for statically importing TopLevel and iteration over keys (in Object/Array/Dictionary) with a keySet$() function as a tribute to our beloved Collection framework :slight_smile:

I am also testing all this for real since I am writing a very simple ActionScript Midi synth to use for my generative music stuff.