소스 검색

use native ocaml neko compilation instead of calling nekoc

Nicolas Cannasse 13 년 전
부모
커밋
057ae68016
3개의 변경된 파일68개의 추가작업 그리고 30개의 파일을 삭제
  1. 1 0
      doc/CHANGES.txt
  2. 61 30
      genneko.ml
  3. 6 0
      haxe.vcproj

+ 1 - 0
doc/CHANGES.txt

@@ -9,6 +9,7 @@
 	all : Std.random(x) when x <= 0 is now always 0
 	spod : added serialized data with SData<T>
 	all : Dispatcher will now throw DETooManyValues
+	all : speed up neko compilation by using native compiler
 
 2012-07-16: 2.10
 	java/cs : added two new targets (beta)

+ 61 - 30
genneko.ml

@@ -19,7 +19,6 @@
 open Ast
 open Type
 open Nast
-open Nxml
 open Common
 
 type context = {
@@ -702,21 +701,53 @@ let gen_name ctx acc t =
 		acc
 
 let generate_libs_init = function
-	| [] -> ""
+	| [] -> []
 	| libs ->
-		let boot =
-			"var @s = $loader.loadprim(\"std@sys_string\",0)();" ^
-			"var @env = $loader.loadprim(\"std@get_env\",1);" ^
-			"var @b = if( @s == \"Windows\" ) " ^
-				"@env(\"HAXEPATH\") + \"lib\\\\\"" ^
-				"else try $loader.loadprim(\"std@file_contents\",1)(@env(\"HOME\")+\"/.haxelib\") + \"/\"" ^
-				"catch e if( @s == \"Linux\" ) \"/usr/lib/haxe/lib/\" else \"/usr/local/lib/haxe/lib/\";" ^
-			"@s = @s + (if( $loader.loadprim(\"std@sys_is64\",0)() ) 64 else \"\") + \"/\";"
+		(*
+			var @s = $loader.loadprim("std@sys_string",0)();
+			var @env = $loader.loadprim("std@get_env",1);
+			var @b = if( @s == "Windows" )
+				@env("HAXEPATH") + "lib\\"
+				else try $loader.loadprim("std@file_contents",1)(@env("HOME")+"/.haxelib") + "/"
+				catch e if( @s == "Linux" ) "/usr/lib/haxe/lib/" else "/usr/local/lib/haxe/lib/";
+			if( $loader.loadprim("std@sys_is64",0)() ) @s = @s + 64;
+		*)
+		let p = null_pos in
+		let es = ident p "@s" in
+		let loadp n nargs =
+			call p (field p (builtin p "loader") "loadprim") [str p ("std@" ^ n); int p nargs]
 		in
-		List.fold_left (fun acc l ->
-			let full_path = l.[0] = '/' || l.[1] = ':' in
-			acc ^ "$loader.path = $array(" ^ (if full_path then "" else "@b + ") ^ "\"" ^ Nast.escape l ^ "\" + @s,$loader.path);"
-		) boot libs
+		let op o e1 e2 =
+			(EBinop (o,e1,e2),p)
+		in
+		let boot = [
+			(EVars [
+				"@s",Some (call p (loadp "sys_string" 0) []);
+				"@env",Some (loadp "get_env" 1);
+				"@b", Some (EIf (op "==" es (str p "Windows"),
+					op "+" (call p (ident p "@env") [str p "HAXEPATH"]) (str p "lib\\"),
+					Some (ETry (
+						op "+" (call p (loadp "file_contents" 1) [op "+" (call p (ident p "@env") [str p "HOME"]) (str p "./haxelib")]) (str p "/"),
+						"e",
+						(EIf (op "==" es (str p "Linux"),
+							str p "/usr/lib/haxe/lib/",
+							Some (str p "/usr/local/lib/haxe/lib/")
+						),p)
+					),p)
+				),p);
+			],p);
+			(EIf (call p (loadp "sys_is64" 0) [],op "=" es (op "+" es (int p 64)),None),p);
+		] in
+		let lpath = field p (builtin p "loader") "path" in
+		boot @ List.map (fun dir ->
+			let full_path = dir.[0] = '/' || dir.[1] = ':' in
+			let dstr = str p dir in
+			(*
+				// for each lib dir
+				$loader.path = $array($loader.path,dir+@s);
+			*)
+			op "=" lpath (call p (builtin p "array") [op "+" (if full_path then dstr else op "+" (ident p "@b") dstr) (ident p "@s"); lpath])
+		) libs
 
 let new_context com macros =
 	{
@@ -784,29 +815,29 @@ let build ctx types =
 let generate com =
 	let ctx = new_context com false in
 	let t = Common.timer "neko generation" in
-	let libs = (ENeko (generate_libs_init com.neko_libs) , { psource = "<header>"; pline = 1; }) in
+	let libs = (EBlock (generate_libs_init com.neko_libs) , { psource = "<header>"; pline = 1; }) in
 	let el = build ctx com.types in
 	let emain = (match com.main with None -> [] | Some e -> [gen_expr ctx e]) in
 	let e = (EBlock ((header()) @ libs :: el @ emain), null_pos) in
-	let neko_file = (try Filename.chop_extension com.file with _ -> com.file) ^ ".neko" in
-	let ch = IO.output_channel (open_out_bin neko_file) in
 	let source = Common.defined com "neko-source" in
-	if source then Nxml.write ch (Nxml.to_xml e) else Binast.write ch e;
-	IO.close_out ch;
-	t();
+	let use_nekoc = Common.defined com "use-nekoc" in
+	let version = if Common.defined com "neko_v2" then 2 else 1 in
+	if not use_nekoc then begin
+		let ch = IO.output_channel (open_out_bin com.file) in
+		Nbytecode.write ch (Ncompile.compile version e);
+		IO.close_out ch;
+	end;
 	let command cmd = try Sys.command cmd with _ -> -1 in
+	let neko_file = (try Filename.chop_extension com.file with _ -> com.file) ^ ".neko" in
+	if source || use_nekoc then begin
+		let ch = IO.output_channel (open_out_bin neko_file) in
+		Binast.write ch e;
+		IO.close_out ch;
+	end;
+	if use_nekoc && command ("nekoc" ^ (if version > 1 then " -version " ^ string_of_int version else "") ^ " \"" ^ neko_file ^ "\"") <> 0 then failwith "Neko compilation failure";
 	if source then begin
 		if command ("nekoc -p \"" ^ neko_file ^ "\"") <> 0 then failwith "Failed to print neko code";
 		Sys.remove neko_file;
 		Sys.rename ((try Filename.chop_extension com.file with _ -> com.file) ^ "2.neko") neko_file;
 	end;
-	let c = Common.timer "neko compilation" in
-	let version = if Common.defined com "neko_v2" then "-version 2 " else "" in
-	if command ("nekoc " ^ version ^ "\"" ^ neko_file ^ "\"") <> 0 then failwith "Neko compilation failure";
-	c();
-	let output = Filename.chop_extension neko_file ^ ".n" in
-	if output <> com.file then begin
-		(try Sys.remove com.file with _ -> ());
-		Sys.rename output com.file;
-	end;
-	if not source then Sys.remove neko_file
+	t()

+ 6 - 0
haxe.vcproj

@@ -47,6 +47,12 @@
 			<File
 				RelativePath=".\libs\neko\nast.ml">
 			</File>
+			<File
+				RelativePath=".\libs\neko\nbytecode.ml">
+			</File>
+			<File
+				RelativePath=".\libs\neko\ncompile.ml">
+			</File>
 			<File
 				RelativePath=".\libs\neko\nxml.ml">
 			</File>