Browse Source

improved JSGenApi

Nicolas Cannasse 14 years ago
parent
commit
b6009f0adc
5 changed files with 69 additions and 27 deletions
  1. 10 0
      interp.ml
  2. 16 0
      std/haxe/macro/Context.hx
  3. 36 27
      std/haxe/macro/DefaultJSGenerator.hx
  4. 4 0
      std/haxe/macro/JSGenApi.hx
  5. 3 0
      typer.ml

+ 10 - 0
interp.ml

@@ -1655,6 +1655,16 @@ let macro_lib =
 				VNull
 				VNull
 			| _ -> error()
 			| _ -> error()
 		);
 		);
+		"get_pos_infos", Fun1 (fun p ->
+			match p with
+			| VAbstract (APos p) -> VObject (obj ["min",VInt p.Ast.pmin;"max",VInt p.Ast.pmax;"file",VString p.Ast.pfile])
+			| _ -> error()
+		);
+		"make_pos", Fun3 (fun min max file ->
+			match min, max, file with
+			| VInt min, VInt max, VString file -> VAbstract (APos { Ast.pmin = min; Ast.pmax = max; Ast.pfile = file })
+			| _ -> error()
+		);
 	]
 	]
 
 
 (* ---------------------------------------------------------------------- *)
 (* ---------------------------------------------------------------------- *)

+ 16 - 0
std/haxe/macro/Context.hx

@@ -119,6 +119,22 @@ class Context {
 		return load("typeof", 1)(e);
 		return load("typeof", 1)(e);
 	}
 	}
 
 
+	/**
+		Get the informations stored into a given position.
+	**/
+	public static function getPosInfos( p : Position ) : { min : Int, max : Int, file : String } {
+		var i = load("get_pos_infos",1)(p);
+		i.file = new String(i.file);
+		return i;
+	}
+
+	/**
+		Build a position with the given informations.
+	**/
+	public static function makePosition( inf : { min : Int, max : Int, file : String } ) : Position {
+		return load("make_pos",3)(inf.min,inf.max,untyped inf.file.__s);
+	}
+
 	static function load( f, nargs ) : Dynamic {
 	static function load( f, nargs ) : Dynamic {
 		#if macro
 		#if macro
 		return neko.Lib.load("macro", f, nargs);
 		return neko.Lib.load("macro", f, nargs);

+ 36 - 27
std/haxe/macro/DefaultJSGenerator.hx

@@ -47,7 +47,7 @@ class DefaultJSGenerator {
 			forbidden.set(x, true);
 			forbidden.set(x, true);
 		api.setTypeAccessor(getType);
 		api.setTypeAccessor(getType);
 	}
 	}
-	
+
 	function getType( t : Type ) {
 	function getType( t : Type ) {
 		return switch(t) {
 		return switch(t) {
 			case TInst(c, _): getPath(c.get());
 			case TInst(c, _): getPath(c.get());
@@ -59,7 +59,7 @@ class DefaultJSGenerator {
 	inline function print(str) {
 	inline function print(str) {
 		buf.add(str);
 		buf.add(str);
 	}
 	}
-	
+
 	inline function newline() {
 	inline function newline() {
 		buf.add(";\n");
 		buf.add(";\n");
 	}
 	}
@@ -67,7 +67,7 @@ class DefaultJSGenerator {
 	inline function genExpr(e) {
 	inline function genExpr(e) {
 		print(api.generateExpr(e));
 		print(api.generateExpr(e));
 	}
 	}
-	
+
 	@:macro static function fprint( e : Expr ) {
 	@:macro static function fprint( e : Expr ) {
 		switch( e.expr ) {
 		switch( e.expr ) {
 		case EConst(c):
 		case EConst(c):
@@ -76,13 +76,23 @@ class DefaultJSGenerator {
 				var exprs = [];
 				var exprs = [];
 				var r = ~/%((\([^\)]+\))|([A-Za-z_][A-Za-z0-9_]*))/;
 				var r = ~/%((\([^\)]+\))|([A-Za-z_][A-Za-z0-9_]*))/;
 				var pos = e.pos;
 				var pos = e.pos;
+				var inf = Context.getPosInfos(pos);
+				inf.min++; // string quote
 				while( r.match(str) ) {
 				while( r.match(str) ) {
-					exprs.push({ expr : EConst(CString(r.matchedLeft())), pos : pos });
+					var left = r.matchedLeft();
+					if( left.length > 0 ) {
+						exprs.push( { expr : EConst(CString(left)), pos : pos } );
+						inf.min += left.length;
+					}
 					var v = r.matched(1);
 					var v = r.matched(1);
-					if( v.charCodeAt(0) == "(".code )
+					if( v.charCodeAt(0) == "(".code ) {
+						var pos = Context.makePosition( { min : inf.min + 2, max : inf.min + v.length, file : inf.file } );
 						exprs.push(Context.parse(v.substr(1, v.length-2), pos));
 						exprs.push(Context.parse(v.substr(1, v.length-2), pos));
-					else
-						exprs.push({ expr : EConst(CIdent(v)), pos : pos });
+					} else {
+						var pos = Context.makePosition( { min : inf.min + 1, max : inf.min + 1 + v.length, file : inf.file } );
+						exprs.push( { expr : EConst(CIdent(v)), pos : pos } );
+					}
+					inf.min += v.length + 1;
 					str = r.matchedRight();
 					str = r.matchedRight();
 				}
 				}
 				exprs.push({ expr : EConst(CString(str)), pos : pos });
 				exprs.push({ expr : EConst(CString(str)), pos : pos });
@@ -97,11 +107,11 @@ class DefaultJSGenerator {
 		Context.error("Expression should be a constant string", e.pos);
 		Context.error("Expression should be a constant string", e.pos);
 		return null;
 		return null;
 	}
 	}
-	
+
 	function field(p) {
 	function field(p) {
 		return api.isKeyword(p) ? '["' + p + '"]' : "." + p;
 		return api.isKeyword(p) ? '["' + p + '"]' : "." + p;
 	}
 	}
-	
+
 	function genPackage( p : Array<String> ) {
 	function genPackage( p : Array<String> ) {
 		var full = null;
 		var full = null;
 		for( x in p ) {
 		for( x in p ) {
@@ -119,16 +129,16 @@ class DefaultJSGenerator {
 			newline();
 			newline();
 		}
 		}
 	}
 	}
-	
+
 	function getPath( t : BaseType ) {
 	function getPath( t : BaseType ) {
 		return (t.pack.length == 0) ? t.name : t.pack.join(".") + "." + t.name;
 		return (t.pack.length == 0) ? t.name : t.pack.join(".") + "." + t.name;
 	}
 	}
-	
+
 	function checkFieldName( c : ClassType, f : ClassField ) {
 	function checkFieldName( c : ClassType, f : ClassField ) {
 		if( forbidden.exists(f.name) )
 		if( forbidden.exists(f.name) )
 			Context.error("The field " + f.name + " is not allowed in JS", c.pos);
 			Context.error("The field " + f.name + " is not allowed in JS", c.pos);
 	}
 	}
-	
+
 	function genClassField( c : ClassType, p : String, f : ClassField ) {
 	function genClassField( c : ClassType, p : String, f : ClassField ) {
 		checkFieldName(c, f);
 		checkFieldName(c, f);
 		var field = field(f.name);
 		var field = field(f.name);
@@ -158,14 +168,14 @@ class DefaultJSGenerator {
 			statics.add( { c : c, f : f } );
 			statics.add( { c : c, f : f } );
 		}
 		}
 	}
 	}
-	
+
 	function genClass( c : ClassType ) {
 	function genClass( c : ClassType ) {
 		genPackage(c.pack);
 		genPackage(c.pack);
 		var p = getPath(c);
 		var p = getPath(c);
 		fprint("%p = ");
 		fprint("%p = ");
 		api.setDebugInfos(c, "new", false);
 		api.setDebugInfos(c, "new", false);
 		if( c.constructor != null )
 		if( c.constructor != null )
-			api.generateConstructor(c.constructor.get().expr);
+			print(api.generateConstructor(c.constructor.get().expr));
 		else
 		else
 			print("function() { }");
 			print("function() { }");
 		newline();
 		newline();
@@ -177,6 +187,7 @@ class DefaultJSGenerator {
 			fprint("%p.__super__ = %psup");
 			fprint("%p.__super__ = %psup");
 			newline();
 			newline();
 			fprint("for(var k in %psup.prototype ) %p.prototype[k] = %psup.prototype[k]");
 			fprint("for(var k in %psup.prototype ) %p.prototype[k] = %psup.prototype[k]");
+			newline();
 		}
 		}
 		for( f in c.statics.get() )
 		for( f in c.statics.get() )
 			genStaticField(c, p, f);
 			genStaticField(c, p, f);
@@ -197,7 +208,7 @@ class DefaultJSGenerator {
 			newline();
 			newline();
 		}
 		}
 	}
 	}
-	
+
 	function genEnum( e : EnumType ) {
 	function genEnum( e : EnumType ) {
 		genPackage(e.pack);
 		genPackage(e.pack);
 		var p = getPath(e);
 		var p = getPath(e);
@@ -229,8 +240,8 @@ class DefaultJSGenerator {
 			newline();
 			newline();
 		}
 		}
 	}
 	}
-	
-	
+
+
 	function genStaticValue( c : ClassType, cf : ClassField ) {
 	function genStaticValue( c : ClassType, cf : ClassField ) {
 		var p = getPath(c);
 		var p = getPath(c);
 		var f = field(cf.name);
 		var f = field(cf.name);
@@ -238,7 +249,7 @@ class DefaultJSGenerator {
 		genExpr(cf.expr);
 		genExpr(cf.expr);
 		newline();
 		newline();
 	}
 	}
-	
+
 	function genType( t : Type ) {
 	function genType( t : Type ) {
 		switch( t ) {
 		switch( t ) {
 		case TInst(c, _):
 		case TInst(c, _):
@@ -269,14 +280,12 @@ class DefaultJSGenerator {
 		newline();
 		newline();
 		print("js.Boot.__res = {}");
 		print("js.Boot.__res = {}");
 		newline();
 		newline();
-		/*
-		if com.debug then begin
-			print ctx "%s = []" ctx.stack.Codegen.stack_var;
-			newline ctx;
-			print ctx "%s = []" ctx.stack.Codegen.stack_exc_var;
-			newline ctx;
-		end;
-		*/
+		if( Context.defined("debug") ) {
+			fprint("%(api.stackVar) = []");
+			newline();
+			fprint("%(api.excVar) = []");
+			newline();
+		}
 		print("js.Boot.__init()");
 		print("js.Boot.__init()");
 		newline();
 		newline();
 		for( e in inits ) {
 		for( e in inits ) {
@@ -295,7 +304,7 @@ class DefaultJSGenerator {
 		file.writeString(buf.toString());
 		file.writeString(buf.toString());
 		file.close();
 		file.close();
 	}
 	}
-	
+
 	#if macro
 	#if macro
 	public static function use() {
 	public static function use() {
 		Compiler.setCustomJSGenerator(function(api) new DefaultJSGenerator(api).generate());
 		Compiler.setCustomJSGenerator(function(api) new DefaultJSGenerator(api).generate());

+ 4 - 0
std/haxe/macro/JSGenApi.hx

@@ -35,6 +35,10 @@ typedef JSGenApi = {
 	var types : Array<Type>;
 	var types : Array<Type>;
 	/** the main call expression, if a -main class is defined **/
 	/** the main call expression, if a -main class is defined **/
 	var main : Null<TypedExpr>;
 	var main : Null<TypedExpr>;
+	/** the variable used to store the temporary stack in debug mode **/
+	var stackVar(default,null) : String;
+	/** the variable used to store the temporary exception in debug mode **/
+	var excVar(default,null) : String;
 	/** generate the JS code for a given typed expression **/
 	/** generate the JS code for a given typed expression **/
 	function generateExpr( e : TypedExpr ) : String;
 	function generateExpr( e : TypedExpr ) : String;
 	/** define the JS code that gets generated when a class or enum is accessed in a typed expression **/
 	/** define the JS code that gets generated when a class or enum is accessed in a typed expression **/

+ 3 - 0
typer.ml

@@ -1932,6 +1932,7 @@ let make_macro_api ctx p =
 				let ctx = Interp.enc_obj [
 				let ctx = Interp.enc_obj [
 					"outputFile", Interp.enc_string ctx.com.file;
 					"outputFile", Interp.enc_string ctx.com.file;
 					"types", Interp.enc_array (List.map (fun t -> Interp.encode_type (make_instance t)) ctx.com.types);
 					"types", Interp.enc_array (List.map (fun t -> Interp.encode_type (make_instance t)) ctx.com.types);
+					"main", (match ctx.com.main with None -> Interp.VNull | Some e -> Interp.encode_texpr e);
 					"generateExpr", Interp.VFunction (Interp.Fun1 (fun v ->
 					"generateExpr", Interp.VFunction (Interp.Fun1 (fun v ->
 						match v with
 						match v with
 						| Interp.VAbstract (Interp.ATExpr e) ->
 						| Interp.VAbstract (Interp.ATExpr e) ->
@@ -1969,6 +1970,8 @@ let make_macro_api ctx p =
 						);
 						);
 						Interp.VNull
 						Interp.VNull
 					));
 					));
+					"stackVar", Interp.enc_string (js_ctx.Genjs.stack.Codegen.stack_var);
+					"excVar", Interp.enc_string (js_ctx.Genjs.stack.Codegen.stack_exc_var);
 				] in
 				] in
 				gen ctx
 				gen ctx
 			);
 			);