Prechádzať zdrojové kódy

hl fully passing expect a few things to fix in haxe

Nicolas Cannasse 9 rokov pred
rodič
commit
82e488c58c
3 zmenil súbory, kde vykonal 229 pridanie a 19 odobranie
  1. 33 18
      genhl.ml
  2. 190 0
      std/hl/_std/UInt.hx
  3. 6 1
      std/hl/types/ArrayDyn.hx

+ 33 - 18
genhl.ml

@@ -289,6 +289,18 @@ let is_number = function
 	| HI8 | HI16 | HI32 | HF32 | HF64 -> true
 	| _ -> false
 
+let hash b =
+	let h = ref Int32.zero in
+	let rec loop i =
+		let c = if i = String.length b then 0 else int_of_char b.[i] in
+		if c <> 0 then begin
+			h := Int32.add (Int32.mul !h 223l) (Int32.of_int c);
+			loop (i + 1)
+		end else
+			Int32.rem !h 0x1FFFFF7Bl
+	in
+	loop 0
+
 let list_iteri f l =
 	let p = ref 0 in
 	List.iter (fun v -> f !p v; incr p) l
@@ -1693,6 +1705,13 @@ and eval_expr ctx e =
 			let v = eval_expr ctx v in
 			op ctx (OSetGlobal (alloc_global ctx "__types__" (rtype ctx v), v));
 			v
+		| "$hash", [v] ->
+			(match v.eexpr with
+			| TConst (TString str) ->
+				let r = alloc_tmp ctx HI32 in
+				op ctx (OInt (r,alloc_i32 ctx (hash str)));
+				r
+			| _ -> error "Constant string required" v.epos)
 		| "$enumIndex", [v] ->
 			let r = alloc_tmp ctx HI32 in
 			let re = eval_expr ctx v in
@@ -3477,20 +3496,10 @@ let interp code =
 
 	let hash_cache = Hashtbl.create 0 in
 
-	let hash b =
-		let h = ref Int32.zero in
-		let rec loop i =
-			let c = if i = String.length b then 0 else int_of_char b.[i] in
-			if c <> 0 then begin
-				h := Int32.add (Int32.mul !h 223l) (Int32.of_int c);
-				loop (i + 1)
-			end else begin
-				let h = Int32.rem !h 0x1FFFFF7Bl in
-				if not (Hashtbl.mem hash_cache h) then Hashtbl.add hash_cache h (String.sub b 0 i);
-				h
-			end
-		in
-		loop 0
+	let hash str =
+		let h = hash str in
+		if not (Hashtbl.mem hash_cache h) then Hashtbl.add hash_cache h (String.sub str 0 (try String.index str '\000' with _ -> String.length str));
+		h
 	in
 
 	let null_access() =
@@ -3655,20 +3664,26 @@ let interp code =
 			throw_msg "Invalid object access"
 
 	and dyn_get_field obj field rt =
-		let set_with v t = dyn_cast v t rt in
+		let get_with v t = dyn_cast v t rt in
 		match obj with
 		| VDynObj d ->
 			(try
 				let idx = Hashtbl.find d.dfields field in
-				set_with d.dvalues.(idx) d.dtypes.(idx)
+				get_with d.dvalues.(idx) d.dtypes.(idx)
 			with Not_found ->
 				default rt)
 		| VObj o ->
+			let default rt =
+				match get_method o.oproto.pclass "__get_field" with
+				| None -> default rt
+				| Some f ->
+					get_with (fcall (func f) [obj; VInt (hash field)]) HDyn
+			in
 			let rec loop p =
 				try
 					let fid = PMap.find field p.pfunctions in
 					(match functions.(fid) with
-					| FFun fd as f -> set_with (VClosure (f,Some obj)) (match fd.ftype with HFun (_::args,t) -> HFun(args,t) | _ -> assert false)
+					| FFun fd as f -> get_with (VClosure (f,Some obj)) (match fd.ftype with HFun (_::args,t) -> HFun(args,t) | _ -> assert false)
 					| FNativeFun _ -> assert false)
 				with Not_found ->
 					match p.psuper with
@@ -3678,7 +3693,7 @@ let interp code =
 			(try
 				let idx, t = get_index field o.oproto.pclass in
 				if idx < 0 then raise Not_found;
-				set_with o.ofields.(idx) t
+				get_with o.ofields.(idx) t
 			with Not_found ->
 				loop o.oproto.pclass)
 		| VVirtual vp ->

+ 190 - 0
std/hl/_std/UInt.hx

@@ -0,0 +1,190 @@
+/*
+ * Copyright (C)2005-2016 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+@:coreApi
+abstract UInt(Int) from Int to Int {
+
+	@:op(A + B) private static inline function add(a:UInt, b:UInt):UInt {
+		return a.toInt() + b.toInt();
+	}
+
+	@:op(A / B) private static inline function div(a:UInt, b:UInt):Float {
+		return a.toFloat() / b.toFloat();
+	}
+
+	@:op(A * B) private static inline function mul(a:UInt, b:UInt):UInt {
+		return a.toInt() * b.toInt();
+	}
+
+	@:op(A - B) private static inline function sub(a:UInt, b:UInt):UInt {
+		return a.toInt() - b.toInt();
+	}
+
+	@:op(A > B) private static function gt(a:UInt, b:UInt):Bool;
+
+	@:op(A >= B) private static function gte(a:UInt, b:UInt):Bool;
+
+	@:op(A < B) private static function lt(a:UInt, b:UInt):Bool;
+
+	@:op(A <= B) private static function lte(a:UInt, b:UInt):Bool;
+
+	@:op(A & B) private static inline function and(a:UInt, b:UInt):UInt {
+		return a.toInt() & b.toInt();
+	}
+
+	@:op(A | B) private static inline function or(a:UInt, b:UInt):UInt {
+		return a.toInt() | b.toInt();
+	}
+
+	@:op(A ^ B) private static inline function xor(a:UInt, b:UInt):UInt {
+		return a.toInt() ^ b.toInt();
+	}
+
+	@:op(A << B) private static inline function shl(a:UInt, b:Int):UInt {
+		return a.toInt() << b;
+	}
+
+	@:op(A >> B) private static inline function shr(a:UInt, b:Int):UInt {
+		return a.toInt() >>> b;
+	}
+
+	@:op(A >>> B) private static inline function ushr(a:UInt, b:Int):UInt {
+		return a.toInt() >>> b;
+	}
+
+	@:op(A % B) private static function mod(a:UInt, b:UInt):UInt;
+
+	@:commutative @:op(A + B) private static inline function addWithFloat(a:UInt, b:Float):Float {
+		return a.toFloat() + b;
+	}
+
+	@:commutative @:op(A * B) private static inline function mulWithFloat(a:UInt, b:Float):Float {
+		return a.toFloat() * b;
+	}
+
+	@:op(A / B) private static inline function divFloat(a:UInt, b:Float):Float {
+		return a.toFloat() / b;
+	}
+
+	@:op(A / B) private static inline function floatDiv(a:Float, b:UInt):Float {
+		return a / b.toFloat();
+	}
+
+	@:op(A - B) private static inline function subFloat(a:UInt, b:Float):Float {
+		return a.toFloat() - b;
+	}
+
+	@:op(A - B) private static inline function floatSub(a:Float, b:UInt):Float {
+		return a - b.toFloat();
+	}
+
+	@:op(A > B) private static inline function gtFloat(a:UInt, b:Float):Bool {
+		return a.toFloat() > b;
+	}
+
+	@:commutative @:op(A == B) private static inline function equalsInt<T:Int>(a:UInt, b:T):Bool {
+		return a.toInt() == b;
+	}
+
+	@:commutative @:op(A != B) private static inline function notEqualsInt<T:Int>(a:UInt, b:T):Bool {
+		return a.toInt() != b;
+	}
+
+	@:commutative @:op(A == B) private static inline function equalsFloat<T:Float>(a:UInt, b:T):Bool {
+        return a.toFloat() == b;
+    }
+
+    @:commutative @:op(A != B) private static inline function notEqualsFloat<T:Float>(a:UInt, b:T):Bool {
+        return a.toFloat() != b;
+    }
+
+	@:op(A >= B) private static inline function gteFloat(a:UInt, b:Float):Bool {
+		return a.toFloat() >= b;
+	}
+
+
+	@:op(A > B) private static inline function floatGt(a:Float, b:UInt):Bool {
+		return a > b.toFloat();
+	}
+
+	@:op(A >= B) private static inline function floatGte(a:Float, b:UInt):Bool {
+		return a >= b.toFloat();
+	}
+
+	@:op(A < B) private static inline function ltFloat(a:UInt, b:Float):Bool {
+		return a.toFloat() < b;
+	}
+
+	@:op(A <= B) private static inline function lteFloat(a:UInt, b:Float):Bool {
+		return a.toFloat() <= b;
+	}
+
+	@:op(A < B) private static inline function floatLt(a:Float, b:UInt):Bool {
+		return a < b.toFloat();
+	}
+
+	@:op(A <= B) private static inline function floatLte(a:Float, b:UInt):Bool {
+		return a <= b.toFloat();
+	}
+
+	@:op(A % B) private static inline function modFloat(a:UInt, b:Float):Float {
+		return a.toFloat() % b;
+	}
+
+	@:op(A % B) private static inline function floatMod(a:Float, b:UInt):Float {
+		return a % b.toFloat();
+	}
+
+	@:op(~A) private inline function negBits():UInt {
+		return ~this;
+	}
+
+	@:op(++A) private inline function prefixIncrement():UInt {
+		return ++this;
+	}
+
+	@:op(A++) private inline function postfixIncrement():UInt {
+		return this++;
+	}
+
+	@:op(--A) private inline function prefixDecrement():UInt {
+		return --this;
+	}
+
+	@:op(A--) private inline function postfixDecrement():UInt {
+		return this--;
+	}
+
+	// TODO: radix is just defined to deal with doc_gen issues
+	private inline function toString(?radix:Int):String {
+		return Std.string(toFloat());
+	}
+
+	private inline function toInt():Int {
+		return this;
+	}
+
+	@:to private inline function toFloat():Float {
+		return cast (this:UInt);
+	}
+}
+

+ 6 - 1
std/hl/types/ArrayDyn.hx

@@ -21,7 +21,6 @@ class ArrayDynIterator {
 @:keep
 class ArrayDyn extends ArrayAccess {
 
-	// TODO : for Dynamic access, we need to support __getField(hash("length")) !
 	public var length(get,never) : Int;
 	var array : ArrayBase;
 	var allowReinterpret : Bool;
@@ -155,6 +154,12 @@ class ArrayDyn extends ArrayAccess {
 		return alloc(a,true);
 	}
 
+	function __get_field( fid : Int ) : Dynamic {
+		if( fid == untyped $hash("length") )
+			return length;
+		return null;
+	}
+	
 	function __cast( t : Type ) : Dynamic {
 		if( t.check(array) )
 			return array;