Browse Source

added @:multitype, added js.JQuery

Nicolas Cannasse 14 years ago
parent
commit
a5ae01e436
5 changed files with 313 additions and 22 deletions
  1. 4 0
      doc/CHANGES.txt
  2. 32 0
      std/haxe/macro/Tools.hx
  3. 231 0
      std/js/JQuery.hx
  4. 15 0
      std/js/jquery-1.5.min.js
  5. 31 22
      typer.ml

+ 4 - 0
doc/CHANGES.txt

@@ -1,3 +1,7 @@
+2011-??-??: 2.08
+	js : added js.JQuery
+	all : added @:multitype
+
 2011-01-30: 2.07
 	all : fixed completion support with --remap
 	all : added macros, added --interp

+ 32 - 0
std/haxe/macro/Tools.hx

@@ -0,0 +1,32 @@
+package haxe.macro;
+#if macro
+import haxe.macro.Expr;
+#end
+
+/**
+	Some macro utility methods that can be used on different platforms
+**/
+#if !macro extern #end
+class Tools {
+
+	#if (js || macro)
+	/**
+		Embed an on-disk javascript file (can be called into an __init__ method)
+	**/
+	@:macro public static function includeFile( fileName : Expr ) {
+		var str = switch( fileName.expr ) {
+		case EConst(c):
+			switch( c ) {
+			case CString(str): str;
+			default: null;
+			}
+		default: null;
+		}
+		if( str == null ) Context.error("Should be a constant string", fileName.pos);
+		var f = try neko.io.File.getContent(Context.resolvePath(str)) catch( e : Dynamic ) Context.error(Std.string(e), fileName.pos);
+		var p = Context.currentPos();
+		return { expr : EUntyped( { expr : ECall( { expr : EConst(CIdent("__js__")), pos : p }, [ { expr : EConst(CString(f)), pos : p } ]), pos : p } ), pos : p };
+	}
+	#end
+
+}

+ 231 - 0
std/js/JQuery.hx

@@ -0,0 +1,231 @@
+package js;
+
+typedef JqEvent = {
+	var target : Dom.HtmlDom;
+	var currentTarget : Dom.HtmlDom;
+	var relatedTarget : Dom.HtmlDom;
+
+	var type : String;
+	var timeStamp : Int;
+
+	//var data : Dynamic;
+	//var namespace : String;
+	//var result : Dynamic;
+
+	// position
+	var pageX : Int;
+	var pageY : Int;
+
+	// keys
+	var which : Int;
+
+	// propagation
+	function isDefaultPrevented() : Bool;
+	function isImmediatePropagationStopped() : Bool;
+	function isPropationStopped() : Bool;
+	function preventDefault() : Void;
+	function stopImmediatePropagation() : Void;
+	function stopPropagation() : Void;
+}
+
+extern class JQuery implements ArrayAccess<JQuery> {
+
+	var context(default,null) : Dom.HtmlDom;
+	var length(default, null) : Int;
+
+	function new( queryOrHtml : String, ?context : JQuery ) : Void;
+
+	// attributes
+	function addClass( className : String ) : JQuery;
+	function removeClass( className : String ) : JQuery;
+	function hasClass( className : String ) : Bool;
+	function toggleClass( className : String, ?addRemove : Bool ) : JQuery;
+
+	function attr( name : String, ?value : String ) : String;
+	function removeAttr( attr : String ) : JQuery;
+
+	function css( prop : String, ?value : String ) : String;
+	function html( ?fill : String ) : String; // first element only
+	function val() : String; // for input elements
+	function text( ?value : String ) : String;
+
+	// Size & Position
+	function width( ?value : Int ) : Int;
+	function height( ?value : Int ) : Int;
+	function innerWidth( ?value : Int ) : Int;
+	function innerHeight( ?value : Int ) : Int;
+	function outerWidth( ?value : Int ) : Int;
+	function outerHeight( ?value : Int ) : Int;
+	function scrollLeft( ?value : Int ) : Int;
+	function scrollTop( ?value : Int ) : Int;
+	function offset( ?value : { left : Int, top : Int } ) : { left : Int, top : Int };
+	function offsetParent() : JQuery;
+	function position( ?value : { left : Int, top : Int } ) : { left : Int, top : Int };
+
+	// current group manipulation
+	function add( selectorOrHTML : String, ?context : JQuery ) : JQuery;
+	function andSelf() : JQuery;
+	function children( ?selector : String ) : JQuery;
+	function clone( ?withDataAndEvents : Bool ) : JQuery;
+	function closest( selector : String, ?context : JQuery ) : JQuery;
+	function contents() : JQuery;
+	function each( f : Void -> Void ) : JQuery;
+	function end() : JQuery;
+	function eq( index : Int ) : JQuery;
+	function filter( selector : String ) : JQuery;
+	function find( selector : String ) : JQuery;
+	function first() : JQuery;
+	function index( ?selector : String ) : Int;
+	function last( ?selector : String ) : JQuery;
+	function has( selector : String ) : JQuery;
+	function next( ?selector : String ) : JQuery;
+	function nextAll( ?selector : String ) : JQuery;
+	function nextUntil( ?selector : String ) : JQuery;
+	function parent( ?selector : String ) : JQuery;
+	function parents( ?selector : String ) : JQuery;
+	function parentsUntil( ?selector : String ) : JQuery;
+	function not( selector : String ) : JQuery;
+	function prev( ?selector : String ) : JQuery;
+	function prevAll( ?selector : String ) : JQuery;
+	function prevUntil( ?selector : String ) : JQuery;
+	function pushStack( elements : Array<Dom.HtmlDom> ) : JQuery;
+	function siblings( ?selector : String ) : JQuery;
+	function size() : Int;
+	function slice( start : Int, ?end : Int ) : JQuery;
+	function toArray() : Array<Dom.HtmlDom>;
+
+	// DOM changes
+	@:multitype function before( ?html : String, ?j : JQuery, ?h : Dom.HtmlDom ) : JQuery;
+	@:multitype function after( ?html : String, ?j : JQuery, ?h : Dom.HtmlDom ) : JQuery;
+	@:multitype function append( ?html : String, ?j : JQuery, ?h : Dom.HtmlDom ) : JQuery;
+	@:multitype function appendTo( ?html : String, ?j : JQuery, ?h : Dom.HtmlDom ) : JQuery;
+	function detach( ?selector : String ) : JQuery;
+	function empty() : JQuery; // remove all texts
+	@:multitype function insertBefore( ?html : String, ?j : JQuery, ?h : Dom.HtmlDom ) : JQuery;
+	@:multitype function insertAfter( ?html : String, ?j : JQuery, ?h : Dom.HtmlDom ) : JQuery;
+	@:multitype function prepend( ?html : String, ?j : JQuery, ?h : Dom.HtmlDom ) : JQuery;
+	@:multitype function prependTo( ?html : String, ?j : JQuery, ?h : Dom.HtmlDom ) : JQuery;
+	function remove( ?selector : String ) : JQuery;
+	function replaceAll( selector : String ) : JQuery;
+	@:multitype function replaceWith( ?html : String, ?j : JQuery, ?h : Dom.HtmlDom ) : JQuery;
+	function unwrap() : JQuery;
+	@:multitype function wrap( ?html : String, ?j : JQuery, ?h : Dom.HtmlDom ) : JQuery;
+	@:multitype function wrapAll( ?html : String, ?j : JQuery, ?h : Dom.HtmlDom ) : JQuery;
+	@:multitype function wrapInner( ?html : String, ?j : JQuery, ?h : Dom.HtmlDom ) : JQuery;
+
+	// animation
+	function animate( properties : { }, ?duration : Int, ?callb : Void -> Void ) : JQuery;
+	function delay( duration : Int, ?queueName : String ) : JQuery;
+	function hide( ?duration : Int, ?call : Void -> Void ) : JQuery;
+	function fadeIn( ?duration : Int, ?call : Void -> Void ) : JQuery;
+	function fadeOut( ?duration : Int, ?call : Void -> Void ) : JQuery;
+	function fadeTo( duration : Int, opacity : Float, ?call : Void -> Void ) : JQuery;
+	function fadeToggle( ?duration : Int, ?call : Void -> Void ) : JQuery;
+	function show( ?duration : Int, ?call : Void -> Void ) : JQuery;
+	function sliceDown( ?duration : Int, ?call : Void -> Void ) : JQuery;
+	function sliceToggle( ?duration : Int, ?call : Void -> Void ) : JQuery;
+	function sliceUp( ?duration : Int, ?call : Void -> Void ) : JQuery;
+	function stop( ?clearQueue : Bool, ?jumpToEnd : Bool ) : JQuery;
+	function toggle( ?duration : Int, ?call : Void -> Void ) : JQuery;
+
+	// Events
+	function blur( ?callb : JqEvent -> Void ) : JQuery;
+	function change( ?callb : JqEvent -> Void ) : JQuery;
+	function click( ?callb : JqEvent -> Void ) : JQuery;
+	function dblclick( ?callb : JqEvent -> Void ) : JQuery;
+	function error( ?callb : JqEvent -> Void ) : JQuery;
+	function focus( ?callb : JqEvent -> Void ) : JQuery;
+	function focusin( ?callb : JqEvent -> Void ) : JQuery;
+	function focusout( ?callb : JqEvent -> Void ) : JQuery;
+	function hover( onOver : JqEvent -> Void, ?onOut : Void -> Void ) : JQuery;
+	function keydown( ?callb : JqEvent -> Void ) : JQuery;
+	function keypress( ?callb : JqEvent -> Void ) : JQuery;
+	function keyup( ?callb : JqEvent -> Void ) : JQuery;
+	function mousedown( ?callb : JqEvent -> Void ) : JQuery;
+	function mouseenter( ?callb : JqEvent -> Void ) : JQuery;
+	function mouseleave( ?callb : JqEvent -> Void ) : JQuery;
+	function mouseout( ?callb : JqEvent -> Void ) : JQuery;
+	function mouseover( ?callb : JqEvent -> Void ) : JQuery;
+	function mouseup( ?callb : JqEvent -> Void ) : JQuery;
+	function load( ?callb : JqEvent -> Void ) : JQuery;
+	function ready( callb : JqEvent -> Void ) : JQuery;
+	function resize( ?callb : JqEvent -> Void ) : JQuery;
+	function scroll( ?callb : JqEvent -> Void ) : JQuery;
+	function select( ?callb : JqEvent -> Void ) : JQuery;
+	function submit( ?callb : JqEvent -> Void ) : JQuery;
+	function unload( ?callb : JqEvent -> Void ) : JQuery;
+
+	function bind( events : String, callb : JqEvent -> Void ) : JQuery;
+	function delegate( selector : String, events : String, callb : JqEvent -> Void ) : JQuery;
+	function die( ?events : String, ?callb : JqEvent -> Void ) : JQuery;
+	function one( events : String, callb : JqEvent -> Void ) : JQuery;
+	function live( events : String, callb : JqEvent -> Void ) : JQuery;
+	function trigger( events : String ) : JQuery;
+	function triggerHandler( events : String ) : JQuery;
+	function unbind( ?events : String, ?callb : JqEvent -> Void ) : JQuery;
+	function undelegate( ?selector : String, ?events : String, ?callb : JqEvent -> Void ) : JQuery;
+
+	// queue
+	function clearQueue( ?queueName : String ) : JQuery;
+	function dequeue( ?queueName : String ) : JQuery;
+	function queue( ?queueName : String ) : { length : Int };
+
+	// ajax
+	// TODO
+
+	// deferred
+	// TODO
+
+	// other tools
+	function get() : Array<Dom.HtmlDom>;
+	function is( selector : String ) : Bool;
+	function data<T>( key : String, ?value : T ) : T;
+	function removeData( ?key : String ) : JQuery;
+	function serialize() : String;
+	function serializeArray() : Array<{ name : String, value : String }>;
+	//inline function map<T>( f : JQuery -> T ) : Array<T> {
+	//	return untyped this["map"](function() return f(cur)).get();
+	//}
+
+
+	// haxe-additions
+	inline function noBubble( events : String ) : JQuery { return (cast this).bind(events, false); }
+	inline function loadURL( url : String, ?callb : Void -> Void ) : JQuery { return (cast this).load(url,callb); }
+	inline function toggleClick( ?first : Void -> Void, ?second : Void -> Void ) : JQuery { return (cast this).toggle(first, second); }
+
+	inline static function of( d : Dom.HtmlDom ) : JQuery { return new js.JQuery(cast d); }
+
+	/**
+		Return the current JQuery element (in a callback), similar to $(this) in JS.
+	**/
+	static var cur(getCurrent, null) : JQuery;
+
+	static var fx(default, null) : { off : Bool, interval : Int };
+	static var browser(default, null) : { webkit : Bool, opera : Bool, msie : Bool, mozilla : Bool, version : String };
+
+	static function contains( parent : Dom.HtmlDom, child : Dom.HtmlDom ) : Bool;
+	static function noConflict( ?removeAll : Bool ) : Void;
+	static function parseJSON( json : String ) : Dynamic;
+
+
+	//static function parseXML
+	//static function get, post
+	//static function getJSON, getScript, globalEval, grep
+	//static function is*, makeArray, map, merge, noop, now, param, proxy, sub, trim, type, unique
+
+	private static inline function getCurrent() : JQuery {
+		return untyped __js__("$(this)");
+	}
+
+	private static function __init__() : Void untyped {
+		#if !noEmbedJS
+		haxe.macro.Tools.includeFile("js/jquery-1.5.min.js");
+		#end
+		var q : Dynamic = window.jQuery;
+		js.JQuery = q;
+		q.fn.noBubble = q.fn.bind;
+		q.fn.loadURL = q.fn.load;
+		q.fn.toggleClick = q.fn.toggle;
+		q.of = q;
+	}
+}

File diff suppressed because it is too large
+ 15 - 0
std/js/jquery-1.5.min.js


+ 31 - 22
typer.ml

@@ -38,10 +38,11 @@ exception Display of t
 type access_kind =
 	| AKNo of string
 	| AKExpr of texpr
+	| AKField of texpr * tclass_field
 	| AKSet of texpr * string * t * string
 	| AKInline of texpr * tclass_field * t
 	| AKMacro of texpr * tclass_field
-	| AKUsing of texpr * texpr
+	| AKUsing of texpr * tclass_field * texpr
 
 let mk_infos ctx p params =
 	let file = if ctx.in_macro then p.pfile else Filename.basename p.pfile in
@@ -122,7 +123,7 @@ let type_expr_with_type ctx e t =
 let unify_call_params ctx name el args p inline =
 	let error txt =
 		let format_arg = (fun (name,opt,_) -> (if opt then "?" else "") ^ name) in
-		let argstr = "Function " ^ (match name with None -> "" | Some n -> "'" ^ n ^ "' ") ^ "requires " ^ (if args = [] then "no arguments" else "arguments : " ^ String.concat ", " (List.map format_arg args)) in
+		let argstr = "Function " ^ (match name with None -> "" | Some (n,_) -> "'" ^ n ^ "' ") ^ "requires " ^ (if args = [] then "no arguments" else "arguments : " ^ String.concat ", " (List.map format_arg args)) in
 		display_error ctx (txt ^ " arguments\n" ^ argstr) p
 	in
 	let arg_error ul name opt p =
@@ -158,7 +159,13 @@ let unify_call_params ctx name el args p inline =
 	let rec loop acc l l2 skip =
 		match l , l2 with
 		| [] , [] ->
-			if not (inline && ctx.g.doinline) && (match ctx.com.platform with Flash | Flash9 | Js -> true | _ -> false) then
+			if (match name with Some (_,meta) -> has_meta ":multitype" meta | _ -> false) then
+				let args = List.map fst (List.filter (fun o -> not (snd o)) acc) in
+				match List.rev args with
+				| [] -> error "Not enough"; []
+				| _ :: [] -> args
+				| args -> error "Too many"; args
+			else if not (inline && ctx.g.doinline) && (match ctx.com.platform with Flash | Flash9 | Js -> true | _ -> false) then
 				List.rev (no_opt acc)
 			else
 				List.rev (List.map fst acc)
@@ -297,9 +304,9 @@ let make_call ctx e params t p =
 let rec acc_get ctx g p =
 	match g with
 	| AKNo f -> error ("Field " ^ f ^ " cannot be accessed for reading") p
-	| AKExpr e -> e
+	| AKExpr e | AKField (e,_) -> e
 	| AKSet _ -> assert false
-	| AKUsing (et,e) ->
+	| AKUsing (et,_,e) ->
 		(* build a closure with first parameter applied *)
 		(match follow et.etype with
 		| TFun (_ :: args,ret) ->
@@ -350,10 +357,10 @@ let error_require r p =
 	error ("Accessing this field require " ^ r) p
 
 let field_access ctx mode f t e p =
-	let fnormal() = AKExpr (mk (TField (e,f.cf_name)) t p) in
+	let fnormal() = AKField ((mk (TField (e,f.cf_name)) t p),f) in
 	let normal() =
 		match follow e.etype with
-		| TAnon a -> (match !(a.a_status) with EnumStatics e -> AKExpr (mk (TEnumField (e,f.cf_name)) t p) | _ -> fnormal())
+		| TAnon a -> (match !(a.a_status) with EnumStatics e -> AKField ((mk (TEnumField (e,f.cf_name)) t p),f) | _ -> fnormal())
 		| _ -> fnormal()
 	in
 	match f.cf_kind with
@@ -427,7 +434,7 @@ let using_field ctx mode e i p =
 					(try unify_raise ctx e.etype t0 p with Error (Unify _,_) -> raise Not_found);
 					if follow e.etype == t_dynamic && follow t0 != t_dynamic then raise Not_found;
 					let et = type_module_type ctx (TClassDecl c) None p in
-					AKUsing (mk (TField (et,i)) t p,e)
+					AKUsing (mk (TField (et,i)) t p,f,e)
 				| _ -> raise Not_found)
 			with Not_found ->
 				loop l
@@ -660,10 +667,10 @@ let rec type_binop ctx op e1 e2 p =
 	match op with
 	| OpAssign ->
 		let e1 = type_access ctx (fst e1) (snd e1) MSet in
-		let e2 = type_expr_with_type ctx e2 (match e1 with AKNo _ | AKInline _ | AKUsing _ | AKMacro _ -> None | AKExpr e | AKSet(e,_,_,_) -> Some e.etype) in
+		let e2 = type_expr_with_type ctx e2 (match e1 with AKNo _ | AKInline _ | AKUsing _ | AKMacro _ -> None | AKExpr e | AKField (e,_) | AKSet(e,_,_,_) -> Some e.etype) in
 		(match e1 with
 		| AKNo s -> error ("Cannot access field or identifier " ^ s ^ " for writing") p
-		| AKExpr e1 ->
+		| AKExpr e1 | AKField (e1,_) ->
 			unify ctx e2.etype e1.etype p;
 			check_assign ctx e1;
 			(match e1.eexpr , e2.eexpr with
@@ -680,7 +687,7 @@ let rec type_binop ctx op e1 e2 p =
 	| OpAssignOp op ->
 		(match type_access ctx (fst e1) (snd e1) MSet with
 		| AKNo s -> error ("Cannot access field or identifier " ^ s ^ " for writing") p
-		| AKExpr e ->
+		| AKExpr e | AKField (e,_) ->
 			let eop = type_binop ctx op e1 e2 p in
 			(match eop.eexpr with
 			| TBinop (_,_,e2) ->
@@ -867,7 +874,7 @@ and type_unop ctx op flag e p =
 		mk (TUnop (op,flag,e)) t p
 	in
 	match acc with
-	| AKExpr e -> access e
+	| AKExpr e | AKField (e,_) -> access e
 	| AKInline _ | AKUsing _ when not set -> access (acc_get ctx acc p)
 	| AKNo s ->
 		error ("The field or identifier " ^ s ^ " is not accessible for " ^ (if set then "writing" else "reading")) p
@@ -1442,7 +1449,7 @@ and type_expr ctx ?(need_val=true) (e,p) =
 			| _ -> ());
 			let el = (match follow (apply_params c.cl_types params (field_type f)) with
 			| TFun (args,r) ->
-				unify_call_params ctx (Some "new") el args p false
+				unify_call_params ctx (Some ("new",f.cf_meta)) el args p false
 			| _ ->
 				error "Constructor is not a function" p
 			) in
@@ -1655,7 +1662,7 @@ and type_call ctx e el p =
 			let f = get_constructor c p in
 			let el = (match follow (apply_params c.cl_types params (field_type f)) with
 			| TFun (args,_) ->
-				unify_call_params ctx (Some "new") el args p false
+				unify_call_params ctx (Some ("new",f.cf_meta)) el args p false
 			| _ ->
 				error "Constructor is not a function" p
 			) in
@@ -1669,14 +1676,13 @@ and type_call ctx e el p =
 		match type_access ctx (fst e) (snd e) MCall with
 		| AKInline (ethis,f,t) ->
 			let params, tret = (match follow t with
-				| TFun (args,r) -> unify_call_params ctx (Some f.cf_name) el args p true, r
+				| TFun (args,r) -> unify_call_params ctx (Some (f.cf_name,f.cf_meta)) el args p true, r
 				| _ -> error (s_type (print_context()) t ^ " cannot be called") p
 			) in
 			make_call ctx (mk (TField (ethis,f.cf_name)) t p) params tret p
-		| AKUsing (et,eparam) ->
-			let fname = (match et.eexpr with TField (_,f) -> f | _ -> assert false) in
+		| AKUsing (et,ef,eparam) ->
 			let params, tret = (match follow et.etype with
-				| TFun ( _ :: args,r) -> unify_call_params ctx (Some fname) el args p false, r
+				| TFun ( _ :: args,r) -> unify_call_params ctx (Some (ef.cf_name,ef.cf_meta)) el args p false, r
 				| _ -> assert false
 			) in
 			make_call ctx et (eparam::params) tret p
@@ -1687,11 +1693,14 @@ and type_call ctx e el p =
 				| None -> type_expr ctx (EConst (Ident "null"),p)
 				| Some e -> type_expr ctx e)
 			| _ -> assert false)
-		| acc ->
-			let e = acc_get ctx acc p in
+		| AKNo _ | AKSet _ as acc ->
+			ignore(acc_get ctx acc p);
+			assert false
+		| AKExpr e | AKField (e,_) as acc ->
 			let el , t = (match follow e.etype with
 			| TFun (args,r) ->
-				let el = unify_call_params ctx (match e.eexpr with TField (_,f) -> Some f | _ -> None) el args p false in
+				let fopts = (match acc with AKField (_,f) -> Some (f.cf_name,f.cf_meta) | _ -> match e.eexpr with TField (e,f) -> Some (f,[]) | _ -> None) in
+				let el = unify_call_params ctx fopts el args p false in
 				el , r
 			| TMono _ ->
 				let t = mk_mono() in
@@ -2112,7 +2121,7 @@ let type_macro ctx cpath f el p =
 
 let call_macro ctx path meth args p =
 	let ctx2, (margs,_), call = load_macro ctx path meth p in
-	let el = unify_call_params ctx2 (Some meth) args margs p false in
+	let el = unify_call_params ctx2 (Some (meth,[])) args margs p false in
 	call (List.map (fun e -> try Interp.make_const e with Exit -> error "Parameter should be a constant" e.epos) el)
 
 let call_init_macro ctx e =

Some files were not shown because too many files changed in this diff