Kaynağa Gözat

- added core_types for php

Franco Ponticelli 15 yıl önce
ebeveyn
işleme
80dd4476fa

+ 13 - 19
genphp.ml

@@ -1495,32 +1495,26 @@ and gen_value ctx e =
 			e
 		)) e.etype e.epos
 	in
-	let value bl =
+	let value _ =
 		let old = ctx.in_value, ctx.in_loop in
 		let locs = save_locals ctx in
 		let tmp = define_local ctx "»r" in
 		ctx.in_value <- Some tmp;
 		ctx.in_loop <- false;
 		let b =
-		if bl then begin
 			print ctx "eval(%s\"" (escphp ctx.quotes);
 			ctx.quotes <- (ctx.quotes + 1);
 			let p = (escphp ctx.quotes) in
 			print ctx "if(isset(%s$this)) %s$»this =& %s$this;" p p p;
-			let b = open_block ctx in
-			b
-		end else
-			(fun() -> ())
+			open_block ctx
 		in
 		(fun() ->
-			if bl then begin
-				newline ctx;
-				print ctx "return %s$%s" (escphp ctx.quotes) tmp;
-				b();
-				newline ctx;
-				ctx.quotes <- (ctx.quotes - 1);
-				print ctx "%s\")" (escphp ctx.quotes);
-			end;
+			newline ctx;
+			print ctx "return %s$%s" (escphp ctx.quotes) tmp;
+			b();
+			newline ctx;
+			ctx.quotes <- (ctx.quotes - 1);
+			print ctx "%s\")" (escphp ctx.quotes);
 			ctx.in_value <- fst old;
 			ctx.in_loop <- snd old;
 			locs();
@@ -1551,13 +1545,13 @@ and gen_value ctx e =
 	| TFor _
 	| TWhile _
 	| TThrow _ ->
-		let v = value true in
+		let v = value false in
 		gen_expr ctx e;
 		v()
 	| TBlock [e] ->
 		gen_value ctx e
 	| TBlock el ->
-		let v = value true in
+		let v = value false in
 		let rec loop = function
 		| [] ->
 			spr ctx "return null";
@@ -1581,21 +1575,21 @@ and gen_value ctx e =
 		| Some e -> gen_value ctx e);
 		spr ctx ")"
 	| TSwitch (cond,cases,def) ->
-		let v = value true in
+		let v = value false in
 		gen_expr ctx (mk (TSwitch (cond,
 			List.map (fun (e1,e2) -> (e1,assign e2)) cases,
 			match def with None -> None | Some e -> Some (assign e)
 		)) e.etype e.epos);
 		v()
 	| TMatch (cond,enum,cases,def) ->
-		let v = value true in
+		let v = value false in
 		gen_expr ctx (mk (TMatch (cond,enum,
 		List.map (fun (constr,params,e) -> (constr,params,assign e)) cases,
 			match def with None -> None | Some e -> Some (assign e)
 		)) e.etype e.epos);
 		v()
 	| TTry (b,catchs) ->
-		let v = value true in
+		let v = value false in
 		gen_expr ctx (mk (TTry (assign b,
 			List.map (fun (v,t,e) -> v, t , assign e) catchs
 		)) e.etype e.epos);

+ 96 - 0
std/php/_std/Date.hx

@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2005, The haXe Project Contributors
+ * 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 HAXE PROJECT CONTRIBUTORS "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 HAXE PROJECT 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.
+ */
+
+@:core_api @:final class Date
+{
+	private var __t : Float;
+
+	public function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void {
+		__t = untyped __call__("mktime", hour, min, sec, month+1, day, year);
+	}
+
+	public function getTime() : Float {
+		return __t*1000;
+	}
+
+	private function getPhpTime() : Float {
+		return __t;
+	}
+
+	public function getFullYear() : Int {
+		return untyped __call__("intval", __call__("date", "Y", this.__t));
+	}
+
+	public function getMonth() : Int {
+		var m : Int = untyped __call__("intval", __call__("date", "n", this.__t));
+		return -1 + m;
+	}
+
+	public function getDate() : Int {
+		return untyped __call__("intval", __call__("date", "j", this.__t));
+	}
+
+	public function getHours() : Int {
+		return untyped __call__("intval", __call__("date", "G", this.__t));
+	}
+
+	public function getMinutes() : Int {
+		return untyped __call__("intval", __call__("date", "i", this.__t));
+	}
+
+	public function getSeconds() : Int {
+		return untyped __call__("intval", __call__("date", "s", this.__t));
+	}
+
+	public function getDay() : Int {
+		return untyped __call__("intval", __call__("date", "w", this.__t));
+	}
+
+	public function toString():String {
+		return untyped __call__("date", "Y-m-d H:i:s", this.__t);
+	}
+
+	public static function now() : Date {
+		return fromPhpTime(untyped __call__("time"));
+	}
+
+	static function fromPhpTime( t : Float ) : Date {
+		var d = new Date(2000,1,1,0,0,0);
+		d.__t = t;
+		return d;
+	}
+
+	public static function fromTime( t : Float ) : Date {
+		var d = new Date(2000,1,1,0,0,0);
+		d.__t = t/1000;
+		return d;
+	}
+
+	public static function fromString( s : String ) : Date {
+		return fromPhpTime(untyped __call__("strtotime", s));
+	}
+}
+
+

+ 101 - 0
std/php/_std/EReg.hx

@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2005, The haXe Project Contributors
+ * 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 HAXE PROJECT CONTRIBUTORS "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 HAXE PROJECT 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.
+ */
+
+@:core_api @:final class EReg {
+
+	var r : Dynamic;
+	var last : String;
+	var global : Bool;
+	var pattern : String;
+	var options : String;
+	var re : String;
+	var matches : ArrayAccess<Dynamic>;
+
+	public function new( r : String, opt : String ) : Void {
+		this.pattern = r;
+		var a = opt.split("g");
+		global = a.length > 1;
+		if( global )
+			opt = a.join("");
+		this.options = opt;
+		this.re = "/" + untyped __php__("str_replace")("/", "\\/", r) + "/" + opt;
+	}
+
+	public function match( s : String ) : Bool {
+		var p : Int = untyped __php__("preg_match")(re, s, matches, __php__("PREG_OFFSET_CAPTURE"));
+		if(p > 0)
+			last = s;
+		else
+			last = null;
+		return p > 0;
+	}
+
+	public function matched( n : Int ) : String {
+		if( n < 0 ) throw "EReg::matched";
+		// we can't differenciate between optional groups at the end of a match
+		// that have not been matched and invalid groups
+		if( n >= untyped __call__("count", matches)) return null;
+		if(untyped __php__("$this->matches[$n][1] < 0")) return null;
+		return untyped __php__("$this->matches[$n][0]");
+	}
+
+	public function matchedLeft() : String {
+		if( untyped __call__("count", matches) == 0 ) throw "No string matched";
+		return last.substr(0, untyped __php__("$this->matches[0][1]"));
+	}
+
+	public function matchedRight() : String {
+		if( untyped __call__("count", matches) == 0 ) throw "No string matched";
+		var x : Int = untyped __php__("$this->matches[0][1]") + __php__("strlen")(__php__("$this->matches[0][0]"));
+		return last.substr(x);
+	}
+
+	public function matchedPos() : { pos : Int, len : Int } {
+		return untyped { pos : __php__("$this->matches[0][1]"), len : __php__("strlen")(__php__("$this->matches[0][0]")) };
+	}
+
+	public function split( s : String ) : Array<String> {
+		return untyped __php__("new _hx_array(preg_split($this->re, $s, $this->hglobal ? -1 : 2))");
+	}
+
+	public function replace( s : String, by : String ) : String {
+		by = untyped __call__("str_replace", "$$", "\\$", by);
+		untyped __php__("if(!preg_match('/\\\\([^?].+?\\\\)/', $this->re)) $by = preg_replace('/\\$(\\d+)/', '\\\\\\$\\1', $by)");
+		return untyped __php__("preg_replace")(re, by, s, global ? -1 : 1);
+	}
+
+	public function customReplace( s : String, f : EReg -> String ) : String {
+		var buf = "";
+		while( true ) {
+			if( !match(s) )
+				break;
+			buf += matchedLeft();
+			buf += f(this);
+			s = matchedRight();
+		}
+		buf += s;
+		return buf;
+	}
+}

+ 85 - 0
std/php/_std/Hash.hx

@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2005, The haXe Project Contributors
+ * 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 HAXE PROJECT CONTRIBUTORS "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 HAXE PROJECT 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.
+ */
+
+@:core_api class Hash<T> implements php.IteratorAggregate<T> {
+	private var h : ArrayAccess<T>;
+
+	public function new() : Void {
+		h = untyped __call__('array');
+	}
+
+	public function set( key : String, value : T ) : Void {
+		untyped h[key] = value;
+	}
+
+	public function get( key : String ) : Null<T> {
+		if (untyped __call__("array_key_exists", key, h))
+			return untyped h[key];
+		else
+			return null;
+	}
+
+	public function exists( key : String ) : Bool {
+		return untyped __call__("array_key_exists", key, h);
+	}
+
+	public function remove( key : String ) : Bool {
+		if (untyped __call__("array_key_exists", key, h)) {
+			untyped __call__("unset", h[key]);
+			return true;
+		} else
+			return false;
+	}
+
+	public function keys() : Iterator<String> {
+		return untyped __call__("new _hx_array_iterator", __call__("array_keys", h));
+	}
+
+	public function iterator() : Iterator<T> {
+		return untyped __call__("new _hx_array_iterator", __call__("array_values", h));
+	}
+
+	public function toString() : String {
+		var s = "{";
+		var it = keys();
+		for( i in it ) {
+			s += i;
+			s += " => ";
+			s += Std.string(get(i));
+			if( it.hasNext() )
+				s += ", ";
+		}
+		return s + "}";
+	}
+	
+	/**
+		Implement IteratorAggregate for native php iteration
+	**/
+	#if php
+	function getIterator() : Iterator<T> {
+		return iterator();
+	}
+	#end
+}

+ 84 - 0
std/php/_std/IntHash.hx

@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2005, The haXe Project Contributors
+ * 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 HAXE PROJECT CONTRIBUTORS "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 HAXE PROJECT 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.
+ */
+
+@:core_api class IntHash<T> implements php.IteratorAggregate<T> {
+	private var h : ArrayAccess<Int>;
+	public function new() : Void {
+		h = untyped __call__('array');
+	}
+
+	public function set( key : Int, value : T ) : Void {
+		untyped h[key] = value;
+	}
+
+	public function get( key : Int ) : Null<T> {
+		if (untyped __call__("array_key_exists", key, h))
+			return untyped h[key];
+		else
+			return null;
+	}
+
+	public function exists( key : Int ) : Bool {
+		return untyped __call__("array_key_exists", key, h);
+	}
+
+	public function remove( key : Int ) : Bool {
+		if (untyped __call__("array_key_exists", key, h)) {
+			untyped __call__("unset", h[key]);
+			return true;
+		} else
+			return false;
+	}
+
+	public function keys() : Iterator<Int> {
+		return untyped __call__("new _hx_array_iterator", __call__("array_keys", h));
+	}
+
+	public function iterator() : Iterator<T> {
+		return untyped __call__("new _hx_array_iterator", __call__("array_values", h));
+	}
+
+	public function toString() : String {
+		var s = "{";
+		var it = keys();
+		for( i in it ) {
+			s += i;
+			s += " => ";
+			s += Std.string(get(i));
+			if( it.hasNext() )
+				s += ", ";
+		}
+		return s + "}";
+	}
+	
+	/**
+		Implement IteratorAggregate for native php iteration
+	**/
+	#if php
+	function getIterator() : Iterator<T> {
+		return iterator();
+	}
+	#end
+}

+ 63 - 0
std/php/_std/Math.hx

@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2005, The haXe Project Contributors
+ * 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 HAXE PROJECT CONTRIBUTORS "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 HAXE PROJECT 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.
+ */
+
+class Math
+{
+	public static var PI;
+	public static var NaN;
+	public static var POSITIVE_INFINITY;
+	public static var NEGATIVE_INFINITY;
+
+	public static function abs(v) : Float      { return untyped __call__("abs", v); }
+	public static function min(a,b) : Float    { return untyped __call__("min", a, b); }
+	public static function max(a,b) : Float    { return untyped __call__("max", a, b); }
+	public static function sin(v) : Float      { return untyped __call__("sin", v); }
+	public static function cos(v) : Float      { return untyped __call__("cos", v); }
+	public static function atan2(y,x) : Float  { return untyped __call__("atan2", y, x); }
+	public static function tan(v) : Float      { return untyped __call__("tan", v); }
+	public static function exp(v) : Float      { return untyped __call__("exp", v); }
+	public static function log(v) : Float      { return untyped __call__("log", v); }
+	public static function sqrt(v) : Float     { return untyped __call__("sqrt", v); }
+	public static function round(v) : Int      { return untyped __call__("(int) floor", v + 0.5); }
+	public static function floor(v) : Int      { return untyped __call__("(int) floor", v); }
+	public static function ceil(v) : Int       { return untyped __call__("(int) ceil", v); }
+	public static function atan(v) : Float     { return untyped __call__("atan", v); }
+	public static function asin(v) : Float     { return untyped __call__("asin", v); }
+	public static function acos(v) : Float     { return untyped __call__("acos", v); }
+	public static function pow(b,e) : Float    { return untyped __call__("pow", b, e); }
+	public static function random() : Float    { return untyped __call__("mt_rand") / __call__("mt_getrandmax"); }
+	public static function isNaN(f) : Bool     { return untyped __call__("is_nan", f); }
+	public static function isFinite(f) : Bool  { return untyped __call__("is_finite", f); }
+
+	static function __init__() {
+	 	PI = untyped __php__("M_PI");
+	 	NaN = untyped __php__("acos(1.01)");
+	 	NEGATIVE_INFINITY = untyped __php__("log(0)");
+	 	POSITIVE_INFINITY = -NEGATIVE_INFINITY;
+	}
+
+}
+
+

+ 104 - 0
std/php/_std/Reflect.hx

@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2005, The haXe Project Contributors
+ * 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 HAXE PROJECT CONTRIBUTORS "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 HAXE PROJECT 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.
+ */
+
+/**
+	The Reflect API is a way to manipulate values dynamicly through an
+	abstract interface in an untyped manner. Use with care.
+**/
+@:core_type class Reflect {
+
+	public inline static function hasField( o : Dynamic, field : String ) : Bool {
+		return untyped __call__("_hx_has_field", o, field);
+	}
+
+	public static function field( o : Dynamic, field : String ) : Dynamic {
+		return untyped __call__("_hx_field", o, field);
+	}
+
+	public inline static function setField( o : Dynamic, field : String, value : Dynamic ) : Void {
+		untyped __setfield__(o, field, value);
+	}
+
+	public static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
+		if(__call__("is_string", o) && !__call__("is_array", func)) {
+			if(args.length == 0) return __call__("call_user_func", field(o, func));
+			else if(args.length == 1) return __call__("call_user_func", field(o, func), args[0]);
+			else return __call__("call_user_func", field(o, func), args[0], args[1]);
+		}
+		return __call__("call_user_func_array", __call__("is_callable", func) ? func : __call__("array", o, func), (null == args ? __call__("array") : __field__(args, "»a")));
+	}
+
+	public static function fields( o : Dynamic ) : Array<String> {
+		if( o == null ) return new Array();
+		return untyped __php__('$o instanceof _hx_array')
+				? __php__("new _hx_array(array('concat','copy','insert','iterator','length','join','pop','push','remove','reverse','shift','slice','sort','splice','toString','unshift'))")
+				: (__call__('is_string', o)
+					? __php__("new _hx_array(array('charAt','charCodeAt','indexOf','lastIndexOf','length','split','substr','toLowerCase','toString','toUpperCase'))")
+					: __php__("new _hx_array(_hx_get_object_vars($o))"));
+	}
+
+	public static function isFunction( f : Dynamic ) : Bool {
+		return untyped __php__("(is_array($f) && is_callable($f)) || _hx_is_lambda($f)") || (__php__("is_array($f)") && hasField(__php__("$f[0]"), __php__("$f[1]")) && __php__("$f[1]") != "length");
+	}
+
+	public static function compare<T>( a : T, b : T ) : Int {
+		return ( a == b ) ? 0 : (((cast a) > (cast b)) ? 1 : -1);
+	}
+
+	public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool {
+		if(untyped __call__("is_array", f1) && untyped __call__("is_array", f1))
+			return untyped __php__("$f1[0] === $f2[0] && $f1[1] == $f2[1]");
+		if(untyped __call__("is_string", f1) && untyped __call__("is_string", f2))
+			return f1 == f2;
+		return false;
+	}
+
+	public static function isObject( v : Dynamic ) : Bool {
+		if( v == null )
+			return false;
+		if(untyped __call__("is_object", v))
+			return untyped __php__("$v instanceof _hx_anonymous") || Type.getClass(v) != null;
+		if(untyped __php__("is_string($v) && !_hx_is_lambda($v)")) return true;
+		return false;
+	}
+
+	public static function deleteField( o : Dynamic, f : String ) : Bool {
+		if(!hasField(o,f)) return false;
+		untyped __php__("if(isset($o->»dynamics[$f])) unset($o->»dynamics[$f]); else unset($o->$f)");
+		return true;
+	}
+
+	public static function copy<T>( o : T ) : T {
+		if(untyped __call__("is_string", o)) return o;
+		var o2 : Dynamic = {};
+		for( f in Reflect.fields(o) )
+			Reflect.setField(o2,f,Reflect.field(o,f));
+		return o2;
+	}
+
+	public static function makeVarArgs( f : Array<Dynamic> -> Dynamic ) : Dynamic {
+		untyped __php__("return array(new _hx_lambda(array('f' => &$f), null, array('args'), 'return call_user_func($f, new _hx_array($args));'), 'makeArgs')");
+	}
+}

+ 54 - 0
std/php/_std/Std.hx

@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2005, The haXe Project Contributors
+ * 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 HAXE PROJECT CONTRIBUTORS "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 HAXE PROJECT 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.
+ */
+
+@:core_type class Std {
+
+	public static function is( v : Dynamic, t : Dynamic ) : Bool {
+		return untyped untyped __call__("_hx_instanceof", v,t);
+	}
+
+	public static function string( s : Dynamic ) : String {
+		return untyped __call__("_hx_string_rec", s, '');
+	}
+
+	public inline static function int( x : Float ) : Int {
+		return untyped __php__("intval")(x);
+	}
+
+	public static function parseInt( x : String ) : Null<Int> {
+		untyped if (!__php__("is_numeric")(x))
+			return null;
+		else
+			return x.substr(0, 2).toLowerCase() == "0x" ? __php__("intval(substr($x, 2), 16)") : __php__("intval($x)");
+	}
+
+	public static function parseFloat( x : String ) : Float {
+		return untyped __php__("is_numeric($x) ? floatval($x) : acos(1.01)");
+	}
+
+	public static function random( x : Int ) : Int {
+		return untyped __call__("rand", 0, x-1);
+	}
+}

+ 48 - 0
std/php/_std/StringBuf.hx

@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2005, The haXe Project Contributors
+ * 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 HAXE PROJECT CONTRIBUTORS "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 HAXE PROJECT 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.
+ */
+
+@:core_type class StringBuf {
+	private var b : String;
+
+	public function new() {
+		b = "";
+	}
+
+	public inline function add( ?x : Dynamic ) {
+		b += x;
+	}
+
+	public inline function addSub( s : String, pos : Int, ?len : Int ) {
+		b += s.substr(pos,len);
+	}
+
+	public inline function addChar( c : Int ) {
+		b += String.fromCharCode(c);
+	}
+
+	public inline function toString() : String {
+		return b;
+	}
+}

+ 228 - 0
std/php/_std/Type.hx

@@ -0,0 +1,228 @@
+enum ValueType {
+	TNull;
+	TInt;
+	TFloat;
+	TBool;
+	TObject;
+	TFunction;
+	TClass( c : Class<Dynamic> );
+	TEnum( e : Enum<Dynamic> );
+	TUnknown;
+}
+
+@:core_type class Type {
+	public static function getClass<T>( o : T ) : Class<T> untyped {
+		if(o == null) return null;
+		untyped if(__call__("is_array",  o)) {
+			if(__call__("count", o) == 2 && __call__("is_callable", o)) return null;
+			return __call__("_hx_ttype", 'Array');
+		}
+		if(untyped __call__("is_string", o)) {
+			if(__call__("_hx_is_lambda", untyped o)) return null;
+			return __call__("_hx_ttype", 'String');
+		}
+		if(!untyped __call__("is_object", o)) {
+			return null;
+		}
+		var c = __call__("get_class", o);
+		if(c == false || c == '_hx_anonymous' || __call__("is_subclass_of", c, "enum"))
+			return null;
+		else
+			return __call__("_hx_ttype", c);
+	}
+
+	public static function getEnum( o : Dynamic ) : Enum<Dynamic> untyped {
+		if(!__php__("$o instanceof Enum"))
+			return null;
+		else
+			return __php__("_hx_ttype(get_class($o))");
+	}
+
+	public static function getSuperClass( c : Class<Dynamic> ) : Class<Dynamic> {
+		var s = untyped __php__("get_parent_class")(c.__tname__);
+		if(s == false)
+			return null;
+		else
+			return untyped __call__("_hx_ttype", s);
+	}
+
+	public static function getClassName( c : Class<Dynamic> ) : String {
+		if( c == null )
+			return null;
+		return untyped c.__qname__;
+	}
+
+	public static function getEnumName( e : Enum<Dynamic> ) : String {
+		return untyped e.__qname__;
+	}
+
+	public static function resolveClass( name : String ) : Class<Dynamic> untyped {
+		var c = untyped __call__("_hx_qtype", name);
+		if(__php__("$c instanceof _hx_class"))
+			return c;
+		else
+			return null;
+	}
+
+	public static function resolveEnum( name : String ) : Enum<Dynamic> {
+		var e = untyped __call__("_hx_qtype", name);
+		if(untyped __php__("$e instanceof _hx_enum"))
+			return e;
+		else
+			return null;
+	}
+
+	public static function createInstance<T>( cl : Class<T>, args : Array<Dynamic> ) : T untyped {
+		if(cl.__qname__ == 'Array') return [];
+		if(cl.__qname__ == 'String') return args[0];
+		var c = cl.__rfl__();
+		if(c == null) return null;
+		return __php__("$inst = $c->getConstructor() ? $c->newInstanceArgs($args->»a) : $c->newInstanceArgs()");
+	}
+
+	public static function createEmptyInstance<T>( cl : Class<T> ) : T untyped {
+		if(cl.__qname__ == 'Array') return [];
+		if(cl.__qname__ == 'String') return '';
+		try {
+			__php__("php_Boot::$skip_constructor = true");
+			var rfl = cl.__rfl__();
+			if(rfl == null) return null;
+			var m = __php__("$rfl->getConstructor()");
+			var nargs : Int = m.getNumberOfRequiredParameters();
+			var i;
+			if(nargs > 0) {
+				var args = __call__("array_fill", 0, m.getNumberOfRequiredParameters(), null);
+				i = __php__("$rfl->newInstanceArgs($args)");
+			} else {
+				i = __php__("$rfl->newInstanceArgs(array())");
+			}
+			__php__("php_Boot::$skip_constructor = false");
+			return i;
+		} catch( e : Dynamic ) {
+			__php__("php_Boot::$skip_constructor = false");
+			throw "Unable to instantiate " + Std.string(cl);
+		}
+		return null;
+	}
+
+	public static function createEnum<T>( e : Enum<T>, constr : String, ?params : Array<Dynamic> ) : T {
+		var f = Reflect.field(e,constr);
+		if( f == null ) throw "No such constructor "+constr;
+		if( Reflect.isFunction(f) ) {
+			if( params == null ) throw "Constructor "+constr+" need parameters";
+			return Reflect.callMethod(e,f,params);
+		}
+		if( params != null && params.length != 0 )
+			throw "Constructor "+constr+" does not need parameters";
+		return f;
+	}
+
+	public static function createEnumIndex<T>( e : Enum<T>, index : Int, ?params : Array<Dynamic> ) : T {
+		var c = Type.getEnumConstructs(e)[index];
+		if( c == null ) throw index+" is not a valid enum constructor index";
+		return createEnum(e,c,params);
+	}
+
+	public static function getInstanceFields( c : Class<Dynamic> ) : Array<String> {
+		if(untyped c.__qname__ == 'String') return ['substr', 'charAt', 'charCodeAt', 'indexOf', 'lastIndexOf', 'split', 'toLowerCase', 'toUpperCase', 'toString', 'length'];
+		if(untyped c.__qname__ == 'Array') return  ['push', 'concat', 'join', 'pop', 'reverse', 'shift', 'slice', 'sort', 'splice', 'toString', 'copy', 'unshift', 'insert', 'remove', 'iterator', 'length'];
+		untyped __php__("
+		$rfl = $c->__rfl__();
+		if($rfl === null) return new _hx_array(array());
+		$r = array();
+		$internals = array('__construct', '__call', '__get', '__set', '__isset', '__unset', '__toString');
+		$ms = $rfl->getMethods();
+		while(list(, $m) = each($ms)) {
+			$n = $m->getName();
+			if(!$m->isStatic() && ! in_array($n, $internals)) $r[] = $n;
+		}
+		$ps = $rfl->getProperties();
+		while(list(, $p) = each($ps))
+			if(!$p->isStatic()) $r[] = $p->getName()");
+		return untyped __php__("new _hx_array(array_values(array_unique($r)))");
+	}
+
+	public static function getClassFields( c : Class<Dynamic> ) : Array<String> {
+		if(untyped c.__qname__ == 'String') return ['fromCharCode'];
+		if(untyped c.__qname__ == 'Array')  return [];
+		untyped __php__("
+		$rfl = $c->__rfl__();
+		if($rfl === null) return new _hx_array(array());
+		$ms = $rfl->getMethods();
+		$r = array();
+		while(list(, $m) = each($ms))
+			if($m->isStatic()) $r[] = $m->getName();
+		$ps = $rfl->getProperties();
+		while(list(, $p) = each($ps))
+			if($p->isStatic()) $r[] = $p->getName();
+		");
+		return untyped __php__("new _hx_array(array_unique($r))");
+	}
+
+	public static function getEnumConstructs( e : Enum<Dynamic> ) : Array<String> untyped {
+		if (__php__("$e->__tname__ == 'Bool'")) return ['true', 'false'];
+		if (__php__("$e->__tname__ == 'Void'")) return [];
+		return __call__("new _hx_array", e.__constructors);
+	}
+
+	public static function typeof( v : Dynamic ) : ValueType untyped {
+		if(v == null) return TNull;
+		if(__call__("is_array", v)) {
+			if(__call__("is_callable", v)) return TFunction;
+			return TClass(Array);
+		}
+		if(__call__("is_string", v)) {
+			if(__call__("_hx_is_lambda", v)) return TFunction;
+			return TClass(String);
+		}
+		if(__call__("is_bool", v)) return TBool;
+		if(__call__("is_int", v)) return TInt;
+		if(__call__("is_float", v)) return TFloat;
+		if(__php__("$v instanceof _hx_anonymous"))  return TObject;
+		if(__php__("$v instanceof _hx_enum"))  return TObject;
+		if(__php__("$v instanceof _hx_class"))  return TObject;
+
+		var c = __php__("_hx_ttype(get_class($v))");
+
+		if(__php__("$c instanceof _hx_enum"))  return TEnum(cast c);
+		if(__php__("$c instanceof _hx_class")) return TClass(cast c);
+		return TUnknown;
+	}
+
+	public static function enumEq<T>( a : T, b : T ) : Bool untyped {
+		if( a == b )
+			return true;
+		try {
+			if( a.index != b.index )
+				return false;
+			for( i in 0...__call__("count", a.params))
+				if(getEnum(untyped __php__("$a->params[$i]")) != null) {
+					if(!untyped enumEq(__php__("$a->params[$i]"),__php__("$b->params[$i]")))
+						return false;
+				} else {
+					if(!untyped __call__("_hx_equal", __php__("$a->params[$i]"),__php__("$b->params[$i]")))
+						return false;
+				}
+		} catch( e : Dynamic ) {
+			return false;
+		}
+		return true;
+	}
+
+	public static function enumConstructor( e : Dynamic ) : String {
+		return e.tag;
+	}
+
+	public static function enumParameters( e : Dynamic ) : Array<Dynamic> {
+		if(e.params == null)
+			return [];
+		else
+			return untyped __php__("new _hx_array($e->params)");
+	}
+
+	public inline static function enumIndex( e : Dynamic ) : Int {
+		return e.index;
+	}
+
+}
+

+ 405 - 0
std/php/_std/Xml.hx

@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2005, The haXe Project Contributors
+ * 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 HAXE PROJECT CONTRIBUTORS "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 HAXE PROJECT 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.
+ */
+
+enum XmlType {
+}
+
+@:core_api class Xml {
+
+	public static var Element(default,null) : XmlType;
+	public static var PCData(default,null) : XmlType;
+	public static var CData(default,null) : XmlType;
+	public static var Comment(default,null) : XmlType;
+	public static var DocType(default,null) : XmlType;
+	public static var Prolog(default,null) : XmlType;
+	public static var Document(default,null) : XmlType;
+
+	public var nodeType(default,null) : XmlType;
+	public var nodeName(getNodeName,setNodeName) : String;
+	public var nodeValue(getNodeValue,setNodeValue) : String;
+	public var parent(getParent,null) : Xml;
+
+	var _nodeName : String;
+	var _nodeValue : String;
+	var _attributes : Hash<String>;
+	var _children : Array<Xml>;
+	var _parent : Xml;
+
+	private static var build : Xml;
+	private static function __start_element_handler(parser : Dynamic, name : String, attribs : ArrayAccess<String>) : Void {
+		var node = createElement(name);
+		untyped __php__("while(list($k, $v) = each($attribs)) $node->set($k, $v)");
+		build.addChild(node);
+		build = node;
+	}
+
+	private static function __end_element_handler(parser : Dynamic, name : String) : Void {
+		build = build.getParent();
+	}
+
+	private static function __character_data_handler(parser : Dynamic, data : String) : Void {
+		// TODO: this function can probably be simplified
+//		var lc : Xml = (build._children == null || build._children.length == 0) ? null : build._children[build._children.length-1];
+//		if(lc != null && Xml.PCData == lc.nodeType) {
+//			lc.nodeValue = lc.nodeValue + untyped __call__("htmlentities", data);
+//		} else
+		if((untyped __call__("strlen", data) == 1 && __call__("htmlentities", data) != data) || untyped __call__("htmlentities", data) == data) {
+			build.addChild(createPCData(untyped __call__("htmlentities", data)));
+		} else
+			build.addChild(createCData(data));
+	}
+
+	private static function __default_handler(parser : Dynamic, data : String) : Void {
+		build.addChild(createPCData(data));
+	}
+
+	static var xmlChecker = new EReg("\\s*(<\\?xml|<!DOCTYPE)", "mi");
+
+	public static function parse( str : String ) : Xml {
+		build = createDocument();
+		var xml_parser = untyped __call__("xml_parser_create");
+		untyped __call__("xml_set_element_handler", xml_parser, __start_element_handler, __end_element_handler);
+		untyped __call__("xml_set_character_data_handler", xml_parser, __character_data_handler);
+		untyped __call__("xml_set_default_handler", xml_parser, __default_handler);
+		untyped __call__("xml_parser_set_option", xml_parser, __php__("XML_OPTION_CASE_FOLDING"), 0);
+		untyped __call__("xml_parser_set_option", xml_parser, __php__("XML_OPTION_SKIP_WHITE"), 0);
+
+		var isComplete = xmlChecker.match(str);
+
+		if(!isComplete)
+			str = "<doc>"+str+"</doc>";
+
+		if(1 != untyped __call__("xml_parse", xml_parser, str, true)) {
+			throw "Xml parse error ("+untyped __call__("xml_error_string", __call__("xml_get_error_code", xml_parser)) + ") line #" + __call__("xml_get_current_line_number", xml_parser);
+		}
+
+		untyped __call__("xml_parser_free", xml_parser);
+
+		if(isComplete) {
+			return build;
+		} else {
+			build = build._children[0];
+			build._parent = null;
+			build._nodeName = null;
+			build.nodeType = Document;
+			return build;
+		}
+	}
+
+	private function new() : Void;
+
+	public static function createElement( name : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.Element;
+		r._children = new Array();
+		r._attributes = new Hash();
+		r.setNodeName( name );
+		return r;
+	}
+
+	public static function createPCData( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.PCData;
+		r.setNodeValue( data );
+		return r;
+	}
+
+	public static function createCData( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.CData;
+		r.setNodeValue( data );
+		return r;
+	}
+
+	public static function createComment( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.Comment;
+		r.setNodeValue( data );
+		return r;
+	}
+
+	public static function createDocType( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.DocType;
+		r.setNodeValue( data );
+		return r;
+	}
+
+	public static function createProlog( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.Prolog;
+		r.setNodeValue( data );
+		return r;
+	}
+
+	public static function createDocument() : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.Document;
+		r._children = new Array();
+		return r;
+	}
+
+	private function getNodeName() : String {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		return _nodeName;
+	}
+
+	private function setNodeName( n : String ) : String {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		return _nodeName = n;
+	}
+
+	private function getNodeValue() : String {
+		if( nodeType == Xml.Element || nodeType == Xml.Document )
+			throw "bad nodeType";
+		return _nodeValue;
+	}
+
+	private function setNodeValue( v : String ) : String {
+		if( nodeType == Xml.Element || nodeType == Xml.Document )
+			throw "bad nodeType";
+		return _nodeValue = v;
+	}
+
+	private function getParent() : Xml {
+		return _parent;
+	}
+
+	public function get( att : String ) : String {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		return _attributes.get( att );
+	}
+
+	public function set( att : String, value : String ) : Void {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		_attributes.set( att, untyped __call__("htmlspecialchars", value, __php__('ENT_COMPAT'), 'UTF-8'));
+	}
+
+	public function remove( att : String ) : Void{
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		_attributes.remove( att );
+	}
+
+	public function exists( att : String ) : Bool {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		return _attributes.exists( att );
+	}
+
+	public function attributes() : Iterator<String> {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		return _attributes.keys();
+	}
+
+	public function iterator() : Iterator<Xml> {
+		if( _children == null ) throw "bad nodetype";
+		var me = this;
+		var it = null;
+		it = untyped {
+			cur: 0,
+			x: me._children,
+			hasNext : function(){
+				return it.cur < it.x.length;
+			},
+			next : function(){
+				return it.x[it.cur++];
+			}
+		}
+		return cast it;
+	}
+
+	public function elements() : Iterator<Xml> {
+		if( _children == null ) throw "bad nodetype";
+		var me = this;
+		var it = null;
+		it =  untyped {
+			cur: 0,
+			x: me._children,
+			hasNext : function() {
+				var k = it.cur;
+				var l = it.x.length;
+				while( k < l ) {
+
+					if( it.x[k].nodeType == Xml.Element )
+						__php__("break");
+					k += 1;
+				}
+				it.cur = k;
+				return k < l;
+			},
+			next : function() {
+				var k = it.cur;
+				var l = it.x.length;
+				while( k < l ) {
+					var n = it.x[k];
+					k += 1;
+					if( n.nodeType == Xml.Element ) {
+						it.cur = k;
+						return n;
+					}
+				}
+				return null;
+			}
+		}
+		return cast it;
+	}
+
+	public function elementsNamed( name : String ) : Iterator<Xml> {
+		if( _children == null ) throw "bad nodetype";
+
+		var me = this;
+		var it = null;
+		it =  untyped {
+			cur: 0,
+			x: me._children,
+			hasNext : function() {
+				var k = it.cur;
+				var l = it.x.length;
+				while( k < l ) {
+					var n = it.x[k];
+					if( n.nodeType == Xml.Element && n._nodeName == name )
+						__php__("break");
+					k++;
+				}
+				it.cur = k;
+				return k < l;
+			},
+			next : function() {
+				var k = it.cur;
+				var l = it.x.length;
+				while( k < l ) {
+					var n = it.x[k];
+					k++;
+					if( n.nodeType == Xml.Element && n._nodeName == name ) {
+						it.cur = k;
+						return n;
+					}
+				}
+				return null;
+			}
+		}
+		return cast it;
+	}
+
+	public function firstChild() : Xml {
+		if( _children == null ) throw "bad nodetype";
+		if( _children.length == 0 ) return null;
+		return _children[0];
+	}
+
+	public function firstElement() : Xml {
+		if( _children == null ) throw "bad nodetype";
+		var cur = 0;
+		var l = _children.length;
+		while( cur < l ) {
+			var n = _children[cur];
+			if( n.nodeType == Xml.Element )
+				return n;
+			cur++;
+		}
+		return null;
+	}
+
+	public function addChild( x : Xml ) : Void {
+		if( _children == null ) throw "bad nodetype";
+		if( x._parent != null ) x._parent._children.remove(x);
+		x._parent = this;
+		_children.push( x );
+	}
+
+	public function removeChild( x : Xml ) : Bool {
+		if( _children == null ) throw "bad nodetype";
+		var b = _children.remove( x );
+		if( b )
+			x._parent = null;
+		return b;
+	}
+
+	public function insertChild( x : Xml, pos : Int ) : Void {
+		if( _children == null ) throw "bad nodetype";
+		if( x._parent != null ) x._parent._children.remove(x);
+		x._parent = this;
+		_children.insert( pos, x );
+	}
+
+	public function toString() : String {
+		if( nodeType == Xml.PCData )
+			return _nodeValue;
+
+		var s = "";
+
+		if( nodeType == Xml.Element ) {
+			s += "<";
+			s += _nodeName;
+			for( k in _attributes.keys() ){
+				s += " ";
+				s += k;
+				s += "=\""; // \"
+				s += _attributes.get(k);
+				s += "\""; // \"
+			}
+			if( _children.length == 0 ) {
+				s += "/>";
+				return s;
+			}
+			s += ">";
+		} else if( nodeType == Xml.CData )
+			return "<![CDATA["+_nodeValue+"]]>";
+		else if( nodeType == Xml.Comment )
+			return "<!--"+_nodeValue+"-->";
+		else if( nodeType == Xml.DocType )
+			return "<!DOCTYPE "+_nodeValue+">";
+		else if( nodeType == Xml.Prolog )
+			return "<?"+_nodeValue+"?>";
+		
+
+		for( x in iterator() )
+			s += x.toString();
+
+		if( nodeType == Xml.Element ) {
+			s += "</";
+			s += _nodeName;
+			s += ">";
+		}
+		return s;
+	}
+
+	static function __init__() : Void untyped {
+		Xml.Element = "element";
+		Xml.PCData = "pcdata";
+		Xml.CData = "cdata";
+		Xml.Comment = "comment";
+		Xml.DocType = "doctype";
+		Xml.Prolog = "prolog";
+		Xml.Document = "document";
+	}
+
+}