Browse Source

fixed reference to dynamic functions in PHP
extern classes with __init__ are now generated and a reference is added in the calling files

Franco Ponticelli 17 years ago
parent
commit
ad45d3d54b
4 changed files with 97 additions and 46 deletions
  1. 11 9
      doc/CHANGES.txt
  2. 78 30
      genphp.ml
  3. 0 5
      std/haxe/Http.hx
  4. 8 2
      std/php/Boot.hx

+ 11 - 9
doc/CHANGES.txt

@@ -7,16 +7,16 @@ TODO inlining : allow inlined getter/setter
 TODO inlining : substitute class+function type parameters in order to have fully typed expressions
 TODO inlining : substitute class+function type parameters in order to have fully typed expressions
 
 
 2008-??-??: 2.01
 2008-??-??: 2.01
-	added runttime check for php.io.Socket.shutdown (uses fclose in php 5.1.x)
-	fixed php rethrow in catches and added the possibility to catch native exceptions
-	fixed php.Web.setCookie() for expire time
-	fixed php.net.Socket.setTimeout(), php.io.Process
-	fixed SPOD/MySql for PHP
-	fixed Type.enumParameters() and Type.typeOf() for PHP
-	fixed null references in class constructors for array arguments
-	fixed php.Boot.__string_rec() when invoked from toString
-	added neko.NativeString and neko.NativeArray
 	fixed php.Sys
 	fixed php.Sys
+	added neko.NativeString and neko.NativeArray
+	fixed php.Boot.__string_rec() when invoked from toString
+	fixed null references in class constructors for array arguments
+	fixed Type.enumParameters() and Type.typeOf() for PHP
+	fixed SPOD/MySql for PHP
+	fixed php.net.Socket.setTimeout(), php.io.Process
+	fixed php.Web.setCookie() for expire time
+	fixed php rethrow in catches and added the possibility to catch native exceptions
+	added runttime check for php.io.Socket.shutdown (uses fclose in php 5.1.x)
 	allowed optional Context in remoting connections
 	allowed optional Context in remoting connections
 	fixed extern classes for flash < 8
 	fixed extern classes for flash < 8
 	fixed inherited protected/private properties in as3 SWF library
 	fixed inherited protected/private properties in as3 SWF library
@@ -26,6 +26,8 @@ TODO inlining : substitute class+function type parameters in order to have fully
 	use "Dynamic" instead of Dynamic->Void for flash9 IEventDispatcher
 	use "Dynamic" instead of Dynamic->Void for flash9 IEventDispatcher
 	always use full classes paths for genAS3
 	always use full classes paths for genAS3
 	prevent different get/set property accesses when implementing an interface
 	prevent different get/set property accesses when implementing an interface
+	fixed assign of dynamicfunction references in PHP 
+	haXe/PHP now generates code for extern classes __init__
 
 
 2008-07-28: 2.0
 2008-07-28: 2.0
 	fixed current package bug in inherited constructor type
 	fixed current package bug in inherited constructor type

+ 78 - 30
genphp.ml

@@ -10,10 +10,9 @@ class A {
     trace(a()); // should trace "ab"
     trace(a()); // should trace "ab"
   }
   }
   dynamic function a() { return "a"; }
   dynamic function a() { return "a"; }
-  
 }
 }
-- add __toString() for classes that have toString
 - add __init__ for externs
 - add __init__ for externs
+- add __toString() for classes that have toString
 - debug version
 - debug version
 *)
 *)
 (*
 (*
@@ -55,6 +54,8 @@ type context = {
 	mutable in_loop : bool;
 	mutable in_loop : bool;
 	mutable handle_break : bool;
 	mutable handle_break : bool;
 	mutable imports : (string,string list list) Hashtbl.t;
 	mutable imports : (string,string list list) Hashtbl.t;
+	mutable extern_required_paths : (string list * string) list;
+	mutable extern_classes_with_init : path list;
 	mutable locals : (string,string) PMap.t;
 	mutable locals : (string,string) PMap.t;
 	mutable inv_locals : (string,string) PMap.t;
 	mutable inv_locals : (string,string) PMap.t;
 	mutable local_types : t list;
 	mutable local_types : t list;
@@ -70,17 +71,10 @@ type context = {
 let rec escphp n =
 let rec escphp n =
 	if n = 0 then "" else if n = 1 then "\\" else ("\\\\" ^ escphp (n-1))
 	if n = 0 then "" else if n = 1 then "\\" else ("\\\\" ^ escphp (n-1))
 
 
-let inc_path ctx path =
-	let rec slashes n =
-		if n = 0 then "" else ("../" ^ slashes (n-1))
-	in
-	let pre = if ctx.cwd = "" then "lib/" else "" in
-	match path with
-		| ([],name) ->
-		pre ^ (slashes (List.length (fst ctx.path))) ^ name ^ ".php"
-		| (pack,name) ->
-		pre ^ (slashes (List.length (fst ctx.path))) ^ String.concat "/" pack ^ "/" ^ name ^ ".php"
-
+let rec register_extern_required_path ctx path = 
+	if (List.exists(fun p -> p = path) ctx.extern_classes_with_init) && not (List.exists(fun p -> p = path) ctx.extern_required_paths) then
+		ctx.extern_required_paths <- path :: ctx.extern_required_paths
+		
 let s_expr_expr e =
 let s_expr_expr e =
 	match e.eexpr with
 	match e.eexpr with
 	| TConst _ -> "TConst"
 	| TConst _ -> "TConst"
@@ -196,10 +190,26 @@ let is_string_expr e = is_string_type e.etype
 let spr ctx s = Buffer.add_string ctx.buf s
 let spr ctx s = Buffer.add_string ctx.buf s
 let print ctx = Printf.kprintf (fun s -> Buffer.add_string ctx.buf s)
 let print ctx = Printf.kprintf (fun s -> Buffer.add_string ctx.buf s)
 
 
+(*
+let is_extern_with_init ctx path =
+	let found = ref false in
+	List.iter (fun t ->
+		match t with
+		| TClassDecl c ->
+			(match c.cl_path with 
+			| path -> 
+				match c.cl_init with
+				| Some _ -> found := true
+				| _ -> ());
+		| _ -> ()
+	) ctx.com.types;
+	!found
+*)
 let s_path ctx path isextern p =
 let s_path ctx path isextern p =
-	if isextern then
+	if isextern then begin
+		register_extern_required_path ctx path;
 		snd path
 		snd path
-	else begin
+	end else begin
 		(match path with
 		(match path with
 		| ([],"List")			-> "HList"
 		| ([],"List")			-> "HList"
 		| ([],name)				-> name
 		| ([],name)				-> name
@@ -268,7 +278,7 @@ let init com cwd path def_type =
 		(match snd path with
 		(match snd path with
 		| "List" -> "HList";
 		| "List" -> "HList";
 		| s -> s) in
 		| s -> s) in
-	let ch = open_out (String.concat "/" dir ^ "/" ^ (filename path) ^ (if def_type = 0 then ".class" else if def_type = 1 then ".enum" else ".interface") ^ ".php") in
+	let ch = open_out (String.concat "/" dir ^ "/" ^ (filename path) ^ (if def_type = 0 then ".class" else if def_type = 1 then ".enum"  else if def_type = 2 then ".interface" else ".extern") ^ ".php") in
 	let imports = Hashtbl.create 0 in
 	let imports = Hashtbl.create 0 in
 	Hashtbl.add imports (snd path) [fst path];
 	Hashtbl.add imports (snd path) [fst path];
 	{
 	{
@@ -281,6 +291,8 @@ let init com cwd path def_type =
 		in_loop = false;
 		in_loop = false;
 		handle_break = false;
 		handle_break = false;
 		imports = imports;
 		imports = imports;
+		extern_required_paths = [];
+		extern_classes_with_init = [];
 		curclass = null_class;
 		curclass = null_class;
 		locals = PMap.empty;
 		locals = PMap.empty;
 		inv_locals = PMap.empty;
 		inv_locals = PMap.empty;
@@ -320,8 +332,22 @@ let parent e =
 	| TParenthesis _ -> e
 	| TParenthesis _ -> e
 	| _ -> mk (TParenthesis e) e.etype e.epos
 	| _ -> mk (TParenthesis e) e.etype e.epos
 
 
+let inc_extern_path ctx path =
+	let rec slashes n =
+		if n = 0 then "" else ("../" ^ slashes (n-1))
+	in
+	let pre = if ctx.cwd = "" then "lib/" else "" in
+	match path with
+		| ([],name) ->
+		pre ^ (slashes (List.length (fst ctx.path))) ^ name ^ ".extern.php"
+		| (pack,name) ->
+		pre ^ (slashes (List.length (fst ctx.path))) ^ String.concat "/" pack ^ "/" ^ name ^ ".extern.php"
+	
 let close ctx =
 let close ctx =
 	output_string ctx.ch "<?php\n";
 	output_string ctx.ch "<?php\n";
+	List.iter (fun path ->
+		if path <> ctx.path then output_string ctx.ch ("require_once dirname(__FILE__).'/" ^ inc_extern_path ctx path ^ "';\n");
+	) (List.rev ctx.extern_required_paths);
 	output_string ctx.ch "\n";
 	output_string ctx.ch "\n";
 	output_string ctx.ch (Buffer.contents ctx.buf);
 	output_string ctx.ch (Buffer.contents ctx.buf);
 	close_out ctx.ch
 	close_out ctx.ch
@@ -1136,13 +1162,19 @@ and gen_expr ctx e =
 	  		else if is_in_dynamic_methods ctx e1 s then
 	  		else if is_in_dynamic_methods ctx e1 s then
 	  			gen_field_access ctx true e1 s
 	  			gen_field_access ctx true e1 s
 	  		else begin
 	  		else begin
-				spr ctx "array(";
-				(match e1.eexpr with
-				| TTypeExpr t ->
-					print ctx "%s\"" p;
-					spr ctx (s_path ctx (t_path t) false e1.epos);
-					print ctx "%s\"" p
-				| _ -> gen_expr ctx e1);
+				let ob ex = (match ex with
+					| TTypeExpr t ->
+						print ctx "%s\"" p;
+						spr ctx (s_path ctx (t_path t) false e1.epos);
+						print ctx "%s\"" p
+					| _ -> gen_expr ctx e1) in
+				spr ctx "isset(";
+				ob e1.eexpr;
+				print ctx "->%s) ? " s;
+				ob e1.eexpr;
+				print ctx "->%s " s;
+				spr ctx ": array(";
+				ob e1.eexpr;
 				print ctx ", %s\"%s%s\")" p s p;
 				print ctx ", %s\"%s%s\")" p s p;
 			end)
 			end)
 		| TMono _ ->
 		| TMono _ ->
@@ -1719,10 +1751,9 @@ let rec super_has_dynamic c =
 		| Some _ -> true
 		| Some _ -> true
 		| _ -> super_has_dynamic csup)
 		| _ -> super_has_dynamic csup)
 
 
-let generate_class ctx all_dynamic_methods c =
+let generate_class ctx c =
 	let requires_constructor = ref true in
 	let requires_constructor = ref true in
 	ctx.curclass <- c;
 	ctx.curclass <- c;
-	ctx.all_dynamic_methods <- all_dynamic_methods;
 	List.iter (define_getset ctx false) c.cl_ordered_fields;
 	List.iter (define_getset ctx false) c.cl_ordered_fields;
 	List.iter (define_getset ctx true) c.cl_ordered_statics;
 	List.iter (define_getset ctx true) c.cl_ordered_statics;
 	ctx.local_types <- List.map snd c.cl_types;
 	ctx.local_types <- List.map snd c.cl_types;
@@ -1793,6 +1824,8 @@ let createmain com c =
 		in_loop = false;
 		in_loop = false;
 		handle_break = false;
 		handle_break = false;
 		imports = Hashtbl.create 0;
 		imports = Hashtbl.create 0;
+		extern_required_paths = [];
+		extern_classes_with_init = [];
 		curclass = null_class;
 		curclass = null_class;
 		locals = PMap.empty;
 		locals = PMap.empty;
 		inv_locals = PMap.empty;
 		inv_locals = PMap.empty;
@@ -1869,6 +1902,7 @@ let generate_enum ctx e =
 
 
 let generate com =
 let generate com =
 	let all_dynamic_methods = ref [] in
 	let all_dynamic_methods = ref [] in
+	let extern_classes_with_init = ref [] in
 	List.iter (fun t ->
 	List.iter (fun t ->
 		(match t with
 		(match t with
 		| TClassDecl c ->
 		| TClassDecl c ->
@@ -1879,7 +1913,13 @@ let generate com =
 				}) (List.filter is_dynamic_method lst)
 				}) (List.filter is_dynamic_method lst)
 			in
 			in
 			all_dynamic_methods := dynamic_methods_names c.cl_ordered_fields @ !all_dynamic_methods;
 			all_dynamic_methods := dynamic_methods_names c.cl_ordered_fields @ !all_dynamic_methods;
-			all_dynamic_methods := dynamic_methods_names c.cl_ordered_statics @ !all_dynamic_methods
+			all_dynamic_methods := dynamic_methods_names c.cl_ordered_statics @ !all_dynamic_methods;
+			if c.cl_extern then
+				(match c.cl_init with
+				| Some _ ->
+					extern_classes_with_init := c.cl_path :: !extern_classes_with_init;
+				| _ -> 
+					())
 		| _ -> ())
 		| _ -> ())
 	) com.types;
 	) com.types;
 	List.iter (fun t ->
 	List.iter (fun t ->
@@ -1891,15 +1931,23 @@ let generate com =
 				| ["php"],"PhpMath__"   -> { c with cl_path = [],"Math" }
 				| ["php"],"PhpMath__"   -> { c with cl_path = [],"Math" }
 				| _ -> c
 				| _ -> c
 			) in
 			) in
-			if c.cl_extern then
-				()
-			else (match c.cl_path with
+			if c.cl_extern then begin
+				(match c.cl_init with
+				| None -> ()
+				| Some e ->
+					let ctx = init com "lib" c.cl_path 3 in
+					gen_expr ctx e;
+					close ctx;
+					);
+			end else (match c.cl_path with
 			| [], "@Main" ->
 			| [], "@Main" ->
 				createmain com c;
 				createmain com c;
 			| _ ->
 			| _ ->
 				let ctx = init com "lib" c.cl_path (if c.cl_interface then 2 else 0) in
 				let ctx = init com "lib" c.cl_path (if c.cl_interface then 2 else 0) in
+				ctx.extern_classes_with_init <- !extern_classes_with_init;
+				ctx.all_dynamic_methods <- !all_dynamic_methods;
 				(*let cp = s_path ctx c.cl_path c.cl_extern c.cl_pos in*)
 				(*let cp = s_path ctx c.cl_path c.cl_extern c.cl_pos in*)
-				generate_class ctx !all_dynamic_methods c;
+				generate_class ctx c;
 				(match c.cl_init with
 				(match c.cl_init with
 				| None -> ()
 				| None -> ()
 				| Some e ->
 				| Some e ->

+ 0 - 5
std/haxe/Http.hx

@@ -235,12 +235,7 @@ class Http {
 	#elseif (neko || php)
 	#elseif (neko || php)
 		var me = this;
 		var me = this;
 		var output = new haxe.io.BytesOutput();
 		var output = new haxe.io.BytesOutput();
-#if php
-// there is a bug in the PHP compiler passing references of dynamic functions
-		var old = untyped __php__("$this->onError");
-#else
 		var old = onError;
 		var old = onError;
-#end
 		var err = false;
 		var err = false;
 		onError = function(e) {
 		onError = function(e) {
 			err = true;
 			err = true;

+ 8 - 2
std/php/Boot.hx

@@ -555,6 +555,9 @@ if(!file_exists($_autload_cache_file)) {
 				} else if(substr($bn, -10) == '.interface') {
 				} else if(substr($bn, -10) == '.interface') {
 					$bn = substr($bn, 0, -10);
 					$bn = substr($bn, 0, -10);
 					$t = 2;
 					$t = 2;
+				} else if(substr($bn, -7) == '.extern') {
+					$bn = substr($bn, 0, -7);
+					$t = 3;
 				} else
 				} else
 					continue;
 					continue;
 				$qname = ($bn == 'HList' && empty($pack)) ? 'List' : join(array_merge($pack, array($bn)), '.');
 				$qname = ($bn == 'HList' && empty($pack)) ? 'List' : join(array_merge($pack, array($bn)), '.');
@@ -585,12 +588,15 @@ if(!file_exists($_autload_cache_file)) {
 		} else if($a[$i]['type'] == 1) {
 		} else if($a[$i]['type'] == 1) {
 			$t = new __enumtype__($a[$i]['phpname'], $a[$i]['qname'], $a[$i]['path']);
 			$t = new __enumtype__($a[$i]['phpname'], $a[$i]['qname'], $a[$i]['path']);
 			$content .= '__enumtype__';
 			$content .= '__enumtype__';
-		} else {
+		} else if($a[$i]['type'] == 2) {
 			$t = new __interfacetype__($a[$i]['phpname'], $a[$i]['qname'], $a[$i]['path']);
 			$t = new __interfacetype__($a[$i]['phpname'], $a[$i]['qname'], $a[$i]['path']);
 			$content .= '__interfacetype__';
 			$content .= '__interfacetype__';
+		} else if($a[$i]['type'] == 3) {
+			$t = new __classtype__($a[$i]['name'], $a[$i]['qname'], $a[$i]['path']);
+			$content .= '__classtype__';
 		}
 		}
 		php_Boot::__register_type($t);
 		php_Boot::__register_type($t);
-		$content .= '(\\''.$a[$i]['phpname'].'\\', \\''.$a[$i]['qname'].'\\', \\''.$a[$i]['path'].'\\'));\n';
+		$content .= '(\\''.($a[$i]['type'] == 3 ? $a[$i]['name'] : $a[$i]['phpname']).'\\', \\''.$a[$i]['qname'].'\\', \\''.$a[$i]['path'].'\\'));\n';
 	}
 	}
 	try {
 	try {
 		file_put_contents($_autload_cache_file, $content);
 		file_put_contents($_autload_cache_file, $content);