Latest Changes

Differences between version EMPTY and #14358

0a1,445
> <code haxe>
> /*
>  * Copyright (c) 2011, TouchMyPixel & contributors
>  * Original author : Tarwin Stroh-Spijer <tarwin@touchmypixel.com>
>  * Contributers: Tony Polinelli <tonyp@touchmypixel.com>
>  * All rights reserved.
>  * Redistribution and use in source and binary forms, with or without
>  * modification, are permitted provided that the following conditions are met:
>  *
>  *   - Redistributions of source code must retain the above copyright
>  *     notice, this list of conditions and the following disclaimer.
>  *   - Redistributions in binary form must reproduce the above copyright
>  *     notice, this list of conditions and the following disclaimer in the
>  *     documentation and/or other materials provided with the distribution.
>  *
>  * THIS SOFTWARE IS PROVIDED BY THE TOUCH MY PIXEL & CONTRIBUTERS "AS IS"
>  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
>  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
>  * ARE DISCLAIMED. IN NO EVENT SHALL THE TOUCH MY PIXEL & CONTRIBUTORS
>  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
>  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
>  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
>  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
>  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
>  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
>  * THE POSSIBILITY OF SUCH DAMAGE.
>  */
> 
> package;
> 
> import neko.FileSystem;
> import neko.Lib;
> import neko.Sys;
> 
> using StringTools;
> using As3ToHaxe;
> 
> /**
>  * Simple Program which iterates -from folder, finds .mtt templates and compiles them to the -to folder
>  */
> class As3ToHaxe
> {
> 	public static inline var keys = ["-from", "-to", "-remove"];
> 	
> 	var to:String;
> 	var from:String;
> 	var remove:String;
> 	var sysargs:Array<String>;
> 	
> 	var items:Array<String>;
> 	
> 	public static var basePackage:String = "away3d";
> 	
> 	private var nameSpaces:Hash<Ns>;
> 	private var maxLoop:Int;
> 	
> 	static function main() 
> 	{
> 		new As3ToHaxe();
> 	}
> 	
> 	public function new()
> 	{
> 		maxLoop = 1000;
> 		
> 		if (parseArgs())
> 		{
> 		
> 			// make sure that the to directory exists
> 			if (!FileSystem.exists(to)) FileSystem.createDirectory(to);
> 			
> 			// delete old files
> 			if (remove == "true")
> 				removeDirectory(to);
> 			
> 			items = [];
> 			// fill items
> 			recurse(from);
> 
> 			// to remember namespaces
> 			nameSpaces = new Hash();
> 			
> 			for (item in items)
> 			{
> 				// make sure we only work wtih AS fiels
> 				var ext = getExt(item);
> 				switch(ext)
> 				{
> 					case "as": 
> 						doConversion(item);
> 				}
> 			}
> 			
> 			// build namespace files
> 			buildNameSpaces();
> 		}
> 	}
> 	
> 	private function doConversion(file:String):Void
> 	{		
> 		var fromFile = file;
> 		var toFile = to + "/" + file.substr(from.length + 1, file.lastIndexOf(".") - (from.length)) + "hx";
> 		
> 		var rF = "";
> 		var rC = "";
> 		
> 		var b = 0;
> 		
> 		// create the folder if it doesn''t exist
> 		var dir = toFile.substr(0, toFile.lastIndexOf("/"));
> 		createFolder(dir);
> 		
> 		var s = neko.io.File.getContent(fromFile);
> 		
> 		// spacse to tabs
> 		s = quickRegR(s, "    ", "\t");
> 		// undent
> 		s = quickRegR(s, "\t\t", "\t");
> 		
> 		// some quick setup, finding what we''ve got
> 		var className = quickRegM(s, "public class([ ]*)([A-Z][a-zA-Z0-9_]*)", 2)[1];
> 		var hasVectors = (quickRegM(s, "Vector([ ]*)\\.([ ]*)<([ ]*)([^>]*)([ ]*)>").length != 0);
> 
> 		// package
> 		s = quickRegR(s, "package ([a-zA-Z\\.0-9-_]*)([ \n\r]*){", "package $1;\n", "gs");
> 		// remove last 
> 		s = quickRegR(s, "\\}([\n\r\t ]*)\\}([\n\r\t ]*)$", "}", "gs");
> 
> 		// extra indentation
> 		s = quickRegR(s, "\n\t", "\n");
> 		
> 		// class
> 		s = quickRegR(s, "public class", "class");
> 
> 		// constructor
> 		s = quickRegR(s, "function " + className, "function new");
> 			
> 		// simple typing
> 		s = quickRegR(s, ":([ ]*)void", ":$1Void");
> 		s = quickRegR(s, ":([ ]*)Boolean", ":$1Bool");
> 		s = quickRegR(s, ":([ ]*)int", ":$1Int");
> 		s = quickRegR(s, ":([ ]*)uint", ":$1UInt");
> 		s = quickRegR(s, ":([ ]*)Number", ":$1Float");
> 		s = quickRegR(s, ":([ ]*)\\*", ":$1Dynamic");
> 		
> 		s = quickRegR(s, "<Number>", "<Float>");
> 		s = quickRegR(s, "<int>", "<Int>");
> 		s = quickRegR(s, "<uint>", "<UInt>");
> 		s = quickRegR(s, "<Boolean>", "<Bool>");
> 		
> 		// vector
> 		// definition
> 		s = quickRegR(s, "Vector([ ]*)\\.([ ]*)<([ ]*)([^>]*)([ ]*)>", "Vector<$3$4$5>");
> 		// new (including removing stupid spaces)
> 		s = quickRegR(s, "new Vector([ ]*)([ ]*)<([ ]*)([^>]*)([ ]*)>([ ]*)\\(([ ]*)\\)([ ]*)", "new Vector()");
> 		// and import if we have to
> 		if (hasVectors) {
> 			s = quickRegR(s, "class([ ]*)(" + className + ")", "import flash.Vector;\n\nclass$1$2");
> 		}
> 		
> 		// array
> 		s = quickRegR(s, " Array([ ]*);", " Array<Dynamic>;");
> 		
> 		// remap protected -> private & internal -> private
> 		s = quickRegR(s, "protected var", "private var");
> 		s = quickRegR(s, "internal var", "private var");
> 		s = quickRegR(s, "protected function", "private function");
> 		s = quickRegR(s, "internal function", "private function");
> 
> 		/* -----------------------------------------------------------*/
> 		// namespaces
> 		// find which namespaces are used in this class
> 		var r = new EReg("([^#])use([ ]+)namespace([ ]+)([a-zA-Z-]+)([ ]*);", "g");
> 		b = 0;
> 		while (true) {
> 			b++; if (b > maxLoop) { logLoopError("namespaces find", file); break; }
> 			if (r.match(s)) {
> 				var ns:Ns = {
> 					name : r.matched(4),
> 					classDefs : new Hash()
> 				};
> 				nameSpaces.set(ns.name, ns);
> 				s = r.replace(s, "//" + r.matched(0).replace("use", "#use") + "\nusing " + basePackage + ".namespace." + ns.name.fUpper() +  ";");
> 			}else {
> 				break;
> 			}
> 		}
> 		
> 		// collect all namespace definitions
> 		// replace them with private
> 		for (k in nameSpaces.keys()) {
> 			var n = nameSpaces.get(k);
> 			b = 0;
> 			while (true) {
> 				b++; if (b > maxLoop) { logLoopError("namespaces collect/replace var", file); break; }
> 				// vars
> 				var r = new EReg(n.name + "([ ]+)var([ ]+)", "g");
> 				s = r.replace(s, "private$1var$2");
> 				if (!r.match(s)) break;
> 			}
> 			b = 0;
> 			while (true) {
> 				b++; if (b > maxLoop) { logLoopError("namespaces collect/replace func", file); break; }
> 				// funcs
> 				var matched:Bool = false;
> 				var r = new EReg(n.name + "([ ]+)function([ ]+)", "g");
> 				if (r.match(s)) matched = true;
> 				s = r.replace(s, "private$1function$2");
> 				r = new EReg(n.name + "([ ]+)function([ ]+)get([ ]+)", "g");
> 				if (r.match(s)) matched = true;
> 				s = r.replace(s, "private$1function$2get$3");
> 				r = new EReg(n.name + "([ ]+)function([ ]+)set([ ]+)", "g");
> 				if (r.match(s)) matched = true;
> 				s = r.replace(s, "private$1function$2$3set");
> 				if (!matched) break;
> 			}
> 		}
> 		
> 		/* -----------------------------------------------------------*/
> 		// change const to inline statics
> 		s = quickRegR(s, "([\n\t ]+)(public|private)([ ]*)const([ ]+)([a-zA-Z0-9_]+)([ ]*):", "$1$2$3static inline var$4$5$6:");
> 		s = quickRegR(s, "([\n\t ]+)(public|private)([ ]*)(static)*([ ]+)const([ ]+)([a-zA-Z0-9_]+)([ ]*):", "$1$2$3$4$5inline var$6$7$8:");
> 		
> 		/* -----------------------------------------------------------*/
> 		// move variables being set from var def to top of constructor
> 		// do NOT do this for const
> 		// if they're static, leave them there
> 		// TODO!
> 		
> 		/* -----------------------------------------------------------*/
> 		// Error > flash.Error
> 		// if " Error (" then add "import flash.Error" to head
> 		var r = new EReg("([ ]+)new([ ]+)Error([ ]*)\\(", "");
> 		if (r.match(s))
> 			s = quickRegR(s, "class([ ]*)(" + className + ")", "import flash.Error;\n\nclass$1$2");
> 		
> 		/* -----------------------------------------------------------*/
> 
> 		// create getters and setters
> 		b = 0;
> 		while (true) {
> 			b++;
> 			var d = { get: null, set: null, type: null, ppg: null, pps: null, name: null };
> 			
> 			// get
> 			var r = new EReg("([\n\t ]+)([a-z]+)([ ]*)function([ ]*)get([ ]+)([a-zA-Z_][a-zA-Z0-9_]+)([ ]*)\\(([ ]*)\\)([ ]*):([ ]*)([A-Z][a-zA-Z0-9_]*)", "");
> 			var m = r.match(s);
> 			if (m) {
> 				d.ppg = r.matched(2);
> 				if (d.ppg == "") d.ppg = "public";
> 				d.name = r.matched(6);
> 				d.get = "get" + d.name.substr(0, 1).toUpperCase() + d.name.substr(1);
> 				d.type = r.matched(11);
> 			}
> 			
> 			// set
> 			var r = new EReg("([\n\t ]+)([a-z]+)([ ]*)function([ ]*)set([ ]+)([a-zA-Z_][a-zA-Z0-9_]*)([ ]*)\\(([ ]*)([a-zA-Z][a-zA-Z0-9_]*)([ ]*):([ ]*)([a-zA-Z][a-zA-Z0-9_]*)", "");
> 			var m = r.match(s);
> 			if (m) {
> 				if (r.matched(6) == d.get || d.get == null)
> 					if (d.name == null) d.name = r.matched(6);
> 				d.pps = r.matched(2);
> 				if (d.pps == "") d.pps = "public";
> 				d.set = "set" + d.name.substr(0, 1).toUpperCase() + d.name.substr(1);
> 				if (d.type == null) d.type = r.matched(12);
> 			}
> 			
> 			// ERROR
> 			if (b > maxLoop) { logLoopError("getter/setter: " + d, file); break; }
> 
> 			// replace get
> 			if (d.get != null)
> 				s = quickRegR(s, d.ppg + "([ ]+)function([ ]+)get([ ]+)" + d.name, "private function " + d.get);
> 			
> 			// replace set
> 			if (d.set != null)
> 				s = quickRegR(s, d.pps + "([ ]+)function([ ]+)set([ ]+)" + d.name, "private function " + d.set);
> 			
> 			// make haxe getter/setter OR finish
> 			if (d.get != null || d.set != null) {
> 				var gs = (d.ppg != null ? d.ppg : d.pps) + " var " + d.name + "(" + d.get + ", " + d.set + "):" + d.type + ";";
> 				s = quickRegR(s, "private function " + (d.get != null ? d.get : d.set), gs + "\n \tprivate function " + (d.get != null ? d.get : d.set));
> 			}else {
> 				break;
> 			}
> 		}
> 
> 		/* -----------------------------------------------------------*/
> 		
> 		// for loops (?)
> 		// TODO!
> 		//s = quickRegR(s, "for([ ]*)\\(([ ]*)var([ ]*)([A-Z][a-zA-Z0-9_]*)([.^;]*);([.^;]*);([.^\\)]*)\\)", "");
> 		//var t = quickRegM(s, "for([ ]*)\\(([ ]*)var([ ]*)([a-zA-Z][a-zA-Z0-9_]*)([.^;]*)", 5);
> 		//trace(t);
> 		//for (var i : Int = 0; i < len; ++i)
> 		
> 		/* -----------------------------------------------------------*/
> 
> 		var o = neko.io.File.write(toFile, true);
> 		o.writeString(s);
> 		o.close();
> 		
> 		// use for testing on a single file
> 		//Sys.exit(1);
> 	}
> 	
> 	private function logLoopError(type:String, file:String)
> 	{
> 		trace("ERROR: " + type + " - " + file);
> 	}
> 	
> 	private function buildNameSpaces()
> 	{
> 		// build friend namespaces!
> 		trace(nameSpaces);
> 	}
> 	
> 	public static function quickRegR(str:String, reg:String, rep:String, ?regOpt:String = "g"):String
> 	{
> 		return new EReg(reg, regOpt).replace(str, rep);
> 	}
> 	
> 	public static function quickRegM(str:String, reg:String, ?numMatches:Int = 1, ?regOpt:String = "g"):Array<String>
> 	{
> 		var r = new EReg(reg, regOpt);
> 		var m = r.match(str);
> 		if (m) {
> 			var a = [];
> 			var i = 1;
> 			while (i <= numMatches) {
> 				a.push(r.matched(i));
> 				i++;
> 			}
> 			return a;
> 		}
> 		return [];
> 	}
> 	
> 	private function createFolder(path:String):Void
> 	{
> 		var parts = path.split("/");
> 		var folder = "";
> 		for (part in parts)
> 		{
> 			if (folder == "") folder += part;
> 			else folder += "/" + part;
> 			if (!FileSystem.exists(folder)) FileSystem.createDirectory(folder);
> 		}
> 	}
> 	
> 	private function parseArgs():Bool
> 	{
> 		// Parse args
> 		var args = Sys.args();
> 		for (i in 0...args.length)
> 			if (Lambda.has(keys, args[i]))
> 				Reflect.setField(this, args[i].substr(1), args[i + 1]);
> 			
> 		// Check to see if argument is missing
> 		if (to == null) { Lib.println("Missing argument '-to'"); return false; }
> 		if (from == null) { Lib.println("Missing argument '-from'"); return false; }
> 		
> 		return true;
> 	}
> 	
> 	public function recurse(path:String)
> 	{
> 		var dir = FileSystem.readDirectory(path);
> 		
> 		for (item in dir)
> 		{
> 			var s = path + "/" + item;
> 			if (FileSystem.isDirectory(s))
> 			{
> 				recurse(s);
> 			}
> 			else
> 			{
> 				var exts = ["as"];
> 				if(Lambda.has(exts, getExt(item)))
> 					items.push(s);
> 			}
> 		}
> 	}
> 	
> 	public function getExt(s:String)
> 	{
> 		return s.substr(s.lastIndexOf(".") + 1).toLowerCase();
> 	}
> 	
> 	public function removeDirectory(d, p = null)
> 	{
> 		if (p == null) p = d;
> 		var dir = FileSystem.readDirectory(d);
> 
> 		for (item in dir)
> 		{
> 			item = p + "/" + item;
> 			if (FileSystem.isDirectory(item)) {
> 				removeDirectory(item);
> 			}else{
> 				FileSystem.deleteFile(item);
> 			}
> 		}
> 		
> 		FileSystem.deleteDirectory(d);
> 	}
> 	
> 	public static function fUpper(s:String)
> 	{
> 		return s.charAt(0).toUpperCase() + s.substr(1);
> 	}
> }
> 
> typedef Ns = {
> 	var name:String;
> 	var classDefs:Hash<String>;
> }
> </code>
> 
> ==== It can be compiled with the following compile.hxml ====
> 
> <code>
> -main As3ToHaxe 
> -neko bin\As3ToHaxe.n
> </code>
> 
> It's still work in progress so developer notes:
>   * changes any 4x spaces to tabs (needed for later cleanup)
>   * fixes package, opening and closing braces as well
>   * fixes classes to be haxe-like
>   * replaces all the void, Boolean, Number, including
>   * fixes Vectors and adds imports
>   * fixes arrays, adding <Dynamic> (don't think there's an easy way to actually define these properly
>   * fixes protected and internet defs
>   * makes all namespaces private and adds a "using" for a friend class
>   * fixes "const" and creates static inline vars
>   * fixes Error class (simply imports flash.Error if it's used)
>   * creates proper haxe getter/setters
> 
>   * TODO: create "friend" class from namespaces info collected information
>   * TODO: move initial var setting from var definition to constructor (not for static inline of course)
>   * TODO: loops.
> 
> //If you have improvements please send them to the Haxe list for verification or post them on the Haxe forum.//
\ No newline at end of file

	
Ver Date Entry Lg User Action
#19364 2013-05-19 18:01:37 manual/haxe3 en orwellophile View | Diff
#19363 2013-05-19 17:58:20 manual/haxe3 en orwellophile View | Diff
#19362 2013-05-19 16:16:17 api/haxe/timer en vegetablesalad View | Diff
#19361 2013-05-19 16:14:40 api/haxe/timer en vegetablesalad View | Diff
#19360 2013-05-13 17:42:34 doc/libraries en Confidant View | Diff
#19359 2013-05-13 05:01:15 manual/macros/advanced en jason View | Diff
#19358 2013-05-12 02:55:03 com/ide en MarcWeber View | Diff
#19357 2013-05-11 05:26:13 ref/conditionals jp shohei909 View | Diff
#19356 2013-05-10 09:29:15 manual/completion en jason View | Diff
#19355 2013-05-09 00:24:39 download/manual_install/leopard en JLM View | Diff
#19354 2013-05-09 00:10:46 download/manual_install/leopard/justinsbuildnotes en JLM View | Diff
#19353 2013-05-08 18:42:04 com/news en ncannasse View | Diff
#19352 2013-05-08 18:12:08 manual/haxe3 en ncannasse View | Diff
#19351 2013-05-08 18:09:11 manual/haxe3 en Simn View | Diff
#19350 2013-05-08 18:04:19 manual/haxe3 en ncannasse View | Diff
#19349 2013-05-08 15:57:29 doc/haxelib/haxelib2 en jason View | Diff
#19348 2013-05-08 15:57:29 doc/haxelib/haxelib2 en jason Changed title from Haxelib 2 to Haxelib 3
#19347 2013-05-08 15:21:08 manual/haxe3/features jp shohei909 View | Diff
#19346 2013-05-08 15:15:14 manual/haxe3/features en shohei909 View | Diff
#19345 2013-05-08 11:51:53 doc/haxelib/haxelib2 en back2dos View | Diff

Previous | Next