460 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			460 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| 
								 | 
							
								package webidl;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if macro
							 | 
						||
| 
								 | 
							
								import webidl.Data;
							 | 
						||
| 
								 | 
							
								import haxe.macro.Context;
							 | 
						||
| 
								 | 
							
								import haxe.macro.Expr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class Module {
							 | 
						||
| 
								 | 
							
									var p : Position;
							 | 
						||
| 
								 | 
							
									var hl : Bool;
							 | 
						||
| 
								 | 
							
									var pack : Array<String>;
							 | 
						||
| 
								 | 
							
									var opts : Options;
							 | 
						||
| 
								 | 
							
									var types : Array<TypeDefinition> = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function new(p, pack, hl, opts) {
							 | 
						||
| 
								 | 
							
										this.p = p;
							 | 
						||
| 
								 | 
							
										this.pack = pack;
							 | 
						||
| 
								 | 
							
										this.hl = hl;
							 | 
						||
| 
								 | 
							
										this.opts = opts;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function makeName( name : String ) {
							 | 
						||
| 
								 | 
							
										if( opts.chopPrefix != null && StringTools.startsWith(name, opts.chopPrefix) ) name = name.substr(opts.chopPrefix.length);
							 | 
						||
| 
								 | 
							
										return capitalize(name);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function buildModule( decls : Array<Definition> ) {
							 | 
						||
| 
								 | 
							
										for( d in decls )
							 | 
						||
| 
								 | 
							
											buildDecl(d);
							 | 
						||
| 
								 | 
							
										return types;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function makeType( t : TypeAttr ) : ComplexType {
							 | 
						||
| 
								 | 
							
										return switch( t.t ) {
							 | 
						||
| 
								 | 
							
										case TVoid: macro : Void;
							 | 
						||
| 
								 | 
							
										case TInt: macro : Int;
							 | 
						||
| 
								 | 
							
										case TShort: hl ? macro : hl.UI16 : macro : Int;
							 | 
						||
| 
								 | 
							
										case TFloat: hl ? macro : Single : macro : Float;
							 | 
						||
| 
								 | 
							
										case TDouble: macro : Float;
							 | 
						||
| 
								 | 
							
										case TBool: macro : Bool;
							 | 
						||
| 
								 | 
							
										case TAny: macro : webidl.Types.Any;
							 | 
						||
| 
								 | 
							
										case TArray(t):
							 | 
						||
| 
								 | 
							
											var tt = makeType({ t : t, attr : [] });
							 | 
						||
| 
								 | 
							
											macro : webidl.Types.NativePtr<$tt>;
							 | 
						||
| 
								 | 
							
										case TVoidPtr: macro : webidl.Types.VoidPtr;
							 | 
						||
| 
								 | 
							
										case TCustom(id): TPath({ pack : [], name : makeName(id) });
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function defVal( t : TypeAttr ) : Expr {
							 | 
						||
| 
								 | 
							
										return switch( t.t ) {
							 | 
						||
| 
								 | 
							
										case TVoid: throw "assert";
							 | 
						||
| 
								 | 
							
										case TInt, TShort: { expr : EConst(CInt("0")), pos : p };
							 | 
						||
| 
								 | 
							
										case TFloat, TDouble: { expr : EConst(CFloat("0.")), pos : p };
							 | 
						||
| 
								 | 
							
										case TBool: { expr : EConst(CIdent("false")), pos : p };
							 | 
						||
| 
								 | 
							
										default: { expr : EConst(CIdent("null")), pos : p };
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function makeNative( name : String ) : MetadataEntry {
							 | 
						||
| 
								 | 
							
										return { name : ":hlNative", params : [{ expr : EConst(CString(opts.nativeLib)), pos : p },{ expr : EConst(CString(name)), pos : p }], pos : p };
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function makeEither( arr : Array<ComplexType> ) {
							 | 
						||
| 
								 | 
							
										var i = 0;
							 | 
						||
| 
								 | 
							
										var t = arr[i++];
							 | 
						||
| 
								 | 
							
										while( i < arr.length ) {
							 | 
						||
| 
								 | 
							
											var t2 = arr[i++];
							 | 
						||
| 
								 | 
							
											t = TPath({ pack : ["haxe", "extern"], name : "EitherType", params : [TPType(t), TPType(t2)] });
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return t;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function makePosition( pos : webidl.Data.Position ) {
							 | 
						||
| 
								 | 
							
										if( pos == null )
							 | 
						||
| 
								 | 
							
											return p;
							 | 
						||
| 
								 | 
							
										return Context.makePosition({ min : pos.pos, max : pos.pos + 1, file : pos.file });
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function makeNativeField( iname : String, f : webidl.Data.Field, args : Array<FArg>, ret : TypeAttr, pub : Bool ) : Field {
							 | 
						||
| 
								 | 
							
										var name = f.name;
							 | 
						||
| 
								 | 
							
										var isConstr = name == iname;
							 | 
						||
| 
								 | 
							
										if( isConstr ) {
							 | 
						||
| 
								 | 
							
											name = "new";
							 | 
						||
| 
								 | 
							
											ret = { t : TCustom(iname), attr : [] };
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										var expr = if( ret.t == TVoid )
							 | 
						||
| 
								 | 
							
											{ expr : EBlock([]), pos : p };
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
											{ expr : EReturn(defVal(ret)), pos : p };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										var access : Array<Access> = [];
							 | 
						||
| 
								 | 
							
										if( !hl ) access.push(AInline);
							 | 
						||
| 
								 | 
							
										if( pub ) access.push(APublic);
							 | 
						||
| 
								 | 
							
										if( isConstr ) access.push(AStatic);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return {
							 | 
						||
| 
								 | 
							
											pos : makePosition(f.pos),
							 | 
						||
| 
								 | 
							
											name : pub ? name : name + args.length,
							 | 
						||
| 
								 | 
							
											meta : [makeNative(iname+"_" + name + (name == "delete" ? "" : ""+args.length))],
							 | 
						||
| 
								 | 
							
											access : access,
							 | 
						||
| 
								 | 
							
											kind : FFun({
							 | 
						||
| 
								 | 
							
												ret : makeType(ret),
							 | 
						||
| 
								 | 
							
												expr : expr,
							 | 
						||
| 
								 | 
							
												args : [for( a in args ) { name : a.name, opt : a.opt, type : makeType(a.t) }],
							 | 
						||
| 
								 | 
							
											}),
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function buildDecl( d : Definition ) {
							 | 
						||
| 
								 | 
							
										var p = makePosition(d.pos);
							 | 
						||
| 
								 | 
							
										switch( d.kind ) {
							 | 
						||
| 
								 | 
							
										case DInterface(iname, attrs, fields):
							 | 
						||
| 
								 | 
							
											var dfields : Array<Field> = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											var variants = new Map();
							 | 
						||
| 
								 | 
							
											function getVariants( name : String ) {
							 | 
						||
| 
								 | 
							
												if( variants.exists(name) )
							 | 
						||
| 
								 | 
							
													return null;
							 | 
						||
| 
								 | 
							
												variants.set(name, true);
							 | 
						||
| 
								 | 
							
												var fl = [];
							 | 
						||
| 
								 | 
							
												for( f in fields )
							 | 
						||
| 
								 | 
							
													if( f.name == name )
							 | 
						||
| 
								 | 
							
														switch( f.kind ) {
							 | 
						||
| 
								 | 
							
														case FMethod(args, ret):
							 | 
						||
| 
								 | 
							
															fl.push({args:args, ret:ret,pos:f.pos});
							 | 
						||
| 
								 | 
							
														default:
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
												return fl;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for( f in fields ) {
							 | 
						||
| 
								 | 
							
												switch( f.kind ) {
							 | 
						||
| 
								 | 
							
												case FMethod(_):
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													var vars = getVariants(f.name);
							 | 
						||
| 
								 | 
							
													if( vars == null ) continue;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													var isConstr = f.name == iname;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if( vars.length == 1 && !isConstr ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														var f = makeNativeField(iname, f, vars[0].args, vars[0].ret, true);
							 | 
						||
| 
								 | 
							
														dfields.push(f);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													} else {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														// create dispatching code
							 | 
						||
| 
								 | 
							
														var maxArgs = 0;
							 | 
						||
| 
								 | 
							
														for( v in vars ) if( v.args.length > maxArgs ) maxArgs = v.args.length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														if( vars.length > 1 && maxArgs == 0 )
							 | 
						||
| 
								 | 
							
															Context.error("Duplicate method declaration", makePosition(vars.pop().pos));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														var targs : Array<FunctionArg> = [];
							 | 
						||
| 
								 | 
							
														var argsTypes = [];
							 | 
						||
| 
								 | 
							
														for( i in 0...maxArgs ) {
							 | 
						||
| 
								 | 
							
															var types : Array<{t:TypeAttr,sign:String}>= [];
							 | 
						||
| 
								 | 
							
															var names = [];
							 | 
						||
| 
								 | 
							
															var opt = false;
							 | 
						||
| 
								 | 
							
															for( v in vars ) {
							 | 
						||
| 
								 | 
							
																var a = v.args[i];
							 | 
						||
| 
								 | 
							
																if( a == null ) {
							 | 
						||
| 
								 | 
							
																	opt = true;
							 | 
						||
| 
								 | 
							
																	continue;
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
																var sign = haxe.Serializer.run(a.t);
							 | 
						||
| 
								 | 
							
																var found = false;
							 | 
						||
| 
								 | 
							
																for( t in types )
							 | 
						||
| 
								 | 
							
																	if( t.sign == sign ) {
							 | 
						||
| 
								 | 
							
																		found = true;
							 | 
						||
| 
								 | 
							
																		break;
							 | 
						||
| 
								 | 
							
																	}
							 | 
						||
| 
								 | 
							
																if( !found ) types.push({ t : a.t, sign : sign });
							 | 
						||
| 
								 | 
							
																if( names.indexOf(a.name) < 0 )
							 | 
						||
| 
								 | 
							
																	names.push(a.name);
							 | 
						||
| 
								 | 
							
																if( a.opt )
							 | 
						||
| 
								 | 
							
																	opt = true;
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															argsTypes.push(types);
							 | 
						||
| 
								 | 
							
															targs.push({
							 | 
						||
| 
								 | 
							
																name : names.join("_"),
							 | 
						||
| 
								 | 
							
																opt : opt,
							 | 
						||
| 
								 | 
							
																type : makeEither([for( t in types ) makeType(t.t)]),
							 | 
						||
| 
								 | 
							
															});
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														// native impls
							 | 
						||
| 
								 | 
							
														var retTypes : Array<{t:TypeAttr,sign:String}> = [];
							 | 
						||
| 
								 | 
							
														for( v in vars ) {
							 | 
						||
| 
								 | 
							
															var f = makeNativeField(iname, f, v.args, v.ret, false );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															var sign = haxe.Serializer.run(v.ret);
							 | 
						||
| 
								 | 
							
															var found = false;
							 | 
						||
| 
								 | 
							
															for( t in retTypes )
							 | 
						||
| 
								 | 
							
																if( t.sign == sign ) {
							 | 
						||
| 
								 | 
							
																	found = true;
							 | 
						||
| 
								 | 
							
																	break;
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
															if( !found ) retTypes.push({ t : v.ret, sign : sign });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															dfields.push(f);
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														vars.sort(function(v1, v2) return v1.args.length - v2.args.length);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														// dispatch only on args count
							 | 
						||
| 
								 | 
							
														function makeCall( v : { args : Array<FArg>, ret : TypeAttr } ) : Expr {
							 | 
						||
| 
								 | 
							
															var ident = { expr : EConst(CIdent( (f.name == iname ? "new" : f.name) + v.args.length )), pos : p};
							 | 
						||
| 
								 | 
							
															var e : Expr = { expr : ECall(ident, [for( i in 0...v.args.length ) { expr : ECast({ expr : EConst(CIdent(targs[i].name)), pos : p }, null), pos : p }]), pos : p };
							 | 
						||
| 
								 | 
							
															if( v.ret.t != TVoid )
							 | 
						||
| 
								 | 
							
																e = { expr : EReturn(e), pos : p };
							 | 
						||
| 
								 | 
							
															else if( isConstr )
							 | 
						||
| 
								 | 
							
																e = macro this = $e;
							 | 
						||
| 
								 | 
							
															return e;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														var expr = makeCall(vars[vars.length - 1]);
							 | 
						||
| 
								 | 
							
														for( i in 1...vars.length ) {
							 | 
						||
| 
								 | 
							
															var v = vars[vars.length - 1 - i];
							 | 
						||
| 
								 | 
							
															var aname = targs[v.args.length].name;
							 | 
						||
| 
								 | 
							
															var call = makeCall(v);
							 | 
						||
| 
								 | 
							
															expr = macro if( $i{aname} == null ) $call else $expr;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														dfields.push({
							 | 
						||
| 
								 | 
							
															name : isConstr ? "new" : f.name,
							 | 
						||
| 
								 | 
							
															pos : makePosition(f.pos),
							 | 
						||
| 
								 | 
							
															access : [APublic, AInline],
							 | 
						||
| 
								 | 
							
															kind : FFun({
							 | 
						||
| 
								 | 
							
																expr : expr,
							 | 
						||
| 
								 | 
							
																args : targs,
							 | 
						||
| 
								 | 
							
																ret : makeEither([for( t in retTypes ) makeType(t.t)]),
							 | 
						||
| 
								 | 
							
															}),
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												case FAttribute(t):
							 | 
						||
| 
								 | 
							
													var tt = makeType(t);
							 | 
						||
| 
								 | 
							
													dfields.push({
							 | 
						||
| 
								 | 
							
														pos : p,
							 | 
						||
| 
								 | 
							
														name : f.name,
							 | 
						||
| 
								 | 
							
														kind : FProp("get", "set", tt),
							 | 
						||
| 
								 | 
							
														access : [APublic],
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
													dfields.push({
							 | 
						||
| 
								 | 
							
														pos : p,
							 | 
						||
| 
								 | 
							
														name : "get_" + f.name,
							 | 
						||
| 
								 | 
							
														meta : [makeNative(iname+"_get_" + f.name)],
							 | 
						||
| 
								 | 
							
														kind : FFun({
							 | 
						||
| 
								 | 
							
															ret : tt,
							 | 
						||
| 
								 | 
							
															expr : macro return ${defVal(t)},
							 | 
						||
| 
								 | 
							
															args : [],
							 | 
						||
| 
								 | 
							
														}),
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
													dfields.push({
							 | 
						||
| 
								 | 
							
														pos : p,
							 | 
						||
| 
								 | 
							
														name : "set_" + f.name,
							 | 
						||
| 
								 | 
							
														meta : [makeNative(iname+"_set_" + f.name)],
							 | 
						||
| 
								 | 
							
														kind : FFun({
							 | 
						||
| 
								 | 
							
															ret : tt,
							 | 
						||
| 
								 | 
							
															expr : macro return ${defVal(t)},
							 | 
						||
| 
								 | 
							
															args : [{ name : "_v", type : tt }],
							 | 
						||
| 
								 | 
							
														}),
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
												case DConst(name, type, value):
							 | 
						||
| 
								 | 
							
													dfields.push({
							 | 
						||
| 
								 | 
							
														pos : p,
							 | 
						||
| 
								 | 
							
														name : name,
							 | 
						||
| 
								 | 
							
														access : [APublic, AStatic, AInline],
							 | 
						||
| 
								 | 
							
														kind : FVar(
							 | 
						||
| 
								 | 
							
															makeType({t : type, attr : []}),
							 | 
						||
| 
								 | 
							
															macro $i{value}
							 | 
						||
| 
								 | 
							
														)
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											var td : TypeDefinition = {
							 | 
						||
| 
								 | 
							
												pos : p,
							 | 
						||
| 
								 | 
							
												pack : pack,
							 | 
						||
| 
								 | 
							
												name : makeName(iname),
							 | 
						||
| 
								 | 
							
												meta : [],
							 | 
						||
| 
								 | 
							
												kind : TDAbstract(macro : webidl.Types.Ref, [], [macro : webidl.Types.Ref]),
							 | 
						||
| 
								 | 
							
												fields : dfields,
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( attrs.indexOf(ANoDelete) < 0 )
							 | 
						||
| 
								 | 
							
												dfields.push(makeNativeField(iname, { name : "delete", pos : null, kind : null }, [], { t : TVoid, attr : [] }, true));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if( !hl ) {
							 | 
						||
| 
								 | 
							
												for( f in dfields )
							 | 
						||
| 
								 | 
							
													if( f.meta != null )
							 | 
						||
| 
								 | 
							
														for( m in f.meta )
							 | 
						||
| 
								 | 
							
															if( m.name == ":hlNative" ) {
							 | 
						||
| 
								 | 
							
																if( f.access == null ) f.access = [];
							 | 
						||
| 
								 | 
							
																switch( f.kind ) {
							 | 
						||
| 
								 | 
							
																case FFun(df):
							 | 
						||
| 
								 | 
							
																	var call = opts.nativeLib + "._eb_" + switch( m.params[1].expr ) { case EConst(CString(name)): name; default: throw "!"; };
							 | 
						||
| 
								 | 
							
																	var args : Array<Expr> = [for( a in df.args ) { expr : EConst(CIdent(a.name)), pos : p }];
							 | 
						||
| 
								 | 
							
																	if( f.access.indexOf(AStatic) < 0 )
							 | 
						||
| 
								 | 
							
																		args.unshift(macro this);
							 | 
						||
| 
								 | 
							
																	df.expr = macro return untyped $i{call}($a{args});
							 | 
						||
| 
								 | 
							
																default: throw "assert";
							 | 
						||
| 
								 | 
							
																}
							 | 
						||
| 
								 | 
							
																if (f.access.indexOf(AInline) == -1) f.access.push(AInline);
							 | 
						||
| 
								 | 
							
																f.meta.remove(m);
							 | 
						||
| 
								 | 
							
																break;
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											types.push(td);
							 | 
						||
| 
								 | 
							
										case DImplements(name,intf):
							 | 
						||
| 
								 | 
							
											var name = makeName(name);
							 | 
						||
| 
								 | 
							
											var intf = makeName(intf);
							 | 
						||
| 
								 | 
							
											var found = false;
							 | 
						||
| 
								 | 
							
											for( t in types )
							 | 
						||
| 
								 | 
							
												if( t.name == name ) {
							 | 
						||
| 
								 | 
							
													found = true;
							 | 
						||
| 
								 | 
							
													switch( t.kind ) {
							 | 
						||
| 
								 | 
							
													case TDAbstract(a, _):
							 | 
						||
| 
								 | 
							
														t.fields.push({
							 | 
						||
| 
								 | 
							
															pos : p,
							 | 
						||
| 
								 | 
							
															name : "_to" + intf,
							 | 
						||
| 
								 | 
							
															meta : [{ name : ":to", pos : p }],
							 | 
						||
| 
								 | 
							
															access : [AInline],
							 | 
						||
| 
								 | 
							
															kind : FFun({
							 | 
						||
| 
								 | 
							
																args : [],
							 | 
						||
| 
								 | 
							
																expr : macro return cast this,
							 | 
						||
| 
								 | 
							
																ret : TPath({ pack : [], name : intf }),
							 | 
						||
| 
								 | 
							
															}),
							 | 
						||
| 
								 | 
							
														});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														var toImpl = [intf];
							 | 
						||
| 
								 | 
							
														while( toImpl.length > 0 ) {
							 | 
						||
| 
								 | 
							
															var intf = toImpl.pop();
							 | 
						||
| 
								 | 
							
															var td = null;
							 | 
						||
| 
								 | 
							
															for( t2 in types ) {
							 | 
						||
| 
								 | 
							
																if( t2.name == intf )
							 | 
						||
| 
								 | 
							
																	switch( t2.kind ) {
							 | 
						||
| 
								 | 
							
																	case TDAbstract(a2, _, to):
							 | 
						||
| 
								 | 
							
																		for ( inheritedField in t2.fields ) {
							 | 
						||
| 
								 | 
							
																			// Search for existing field
							 | 
						||
| 
								 | 
							
																			var fieldExists = false;
							 | 
						||
| 
								 | 
							
																			for ( existingField in t.fields ) {
							 | 
						||
| 
								 | 
							
																				if ( inheritedField.name == existingField.name ) {
							 | 
						||
| 
								 | 
							
																					fieldExists = true;
							 | 
						||
| 
								 | 
							
																					break;
							 | 
						||
| 
								 | 
							
																				}
							 | 
						||
| 
								 | 
							
																			}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
																			if ( !fieldExists ) {
							 | 
						||
| 
								 | 
							
																				t.fields.push(inheritedField);
							 | 
						||
| 
								 | 
							
																			}
							 | 
						||
| 
								 | 
							
																		}
							 | 
						||
| 
								 | 
							
																	default:
							 | 
						||
| 
								 | 
							
																	}
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													default:
							 | 
						||
| 
								 | 
							
														Context.warning("Cannot have " + name+" extends " + intf, p);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											if( !found )
							 | 
						||
| 
								 | 
							
												Context.warning("Class " + name+" not found for implements " + intf, p);
							 | 
						||
| 
								 | 
							
										case DEnum(name, values):
							 | 
						||
| 
								 | 
							
											var index = 0;
							 | 
						||
| 
								 | 
							
											types.push({
							 | 
						||
| 
								 | 
							
												pos : p,
							 | 
						||
| 
								 | 
							
												pack : pack,
							 | 
						||
| 
								 | 
							
												name : makeName(name),
							 | 
						||
| 
								 | 
							
												meta : [{ name : ":enum", pos : p }],
							 | 
						||
| 
								 | 
							
												kind : TDAbstract(macro : Int),
							 | 
						||
| 
								 | 
							
												fields : [for( v in values ) { pos : p, name : v, kind : FVar(null,{ expr : EConst(CInt(""+(index++))), pos : p }) }],
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public static function buildTypes( opts : Options, hl : Bool = false ):Array<TypeDefinition> {
							 | 
						||
| 
								 | 
							
										var p = Context.currentPos();
							 | 
						||
| 
								 | 
							
										if( opts.nativeLib == null ) {
							 | 
						||
| 
								 | 
							
											Context.error("Missing nativeLib option for HL", p);
							 | 
						||
| 
								 | 
							
											return null;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										// load IDL
							 | 
						||
| 
								 | 
							
										var file = opts.idlFile;
							 | 
						||
| 
								 | 
							
										var content = try {
							 | 
						||
| 
								 | 
							
											file = Context.resolvePath(file);
							 | 
						||
| 
								 | 
							
											sys.io.File.getBytes(file);
							 | 
						||
| 
								 | 
							
										} catch( e : Dynamic ) {
							 | 
						||
| 
								 | 
							
											Context.error("" + e, p);
							 | 
						||
| 
								 | 
							
											return null;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// parse IDL
							 | 
						||
| 
								 | 
							
										var parse = new webidl.Parser();
							 | 
						||
| 
								 | 
							
										var decls = null;
							 | 
						||
| 
								 | 
							
										try {
							 | 
						||
| 
								 | 
							
											decls = parse.parseFile(file,new haxe.io.BytesInput(content));
							 | 
						||
| 
								 | 
							
										} catch( msg : String ) {
							 | 
						||
| 
								 | 
							
											var lines = content.toString().split("\n");
							 | 
						||
| 
								 | 
							
											var start = lines.slice(0, parse.line-1).join("\n").length + 1;
							 | 
						||
| 
								 | 
							
											Context.error(msg, Context.makePosition({ min : start, max : start + lines[parse.line-1].length, file : file }));
							 | 
						||
| 
								 | 
							
											return null;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										var module = Context.getLocalModule();
							 | 
						||
| 
								 | 
							
										var pack = module.split(".");
							 | 
						||
| 
								 | 
							
										pack.pop();
							 | 
						||
| 
								 | 
							
										return new Module(p, pack, hl, opts).buildModule(decls);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public static function build( opts : Options ) {
							 | 
						||
| 
								 | 
							
										var file = opts.idlFile;
							 | 
						||
| 
								 | 
							
										var module = Context.getLocalModule();
							 | 
						||
| 
								 | 
							
										var types = buildTypes(opts, Context.defined("hl"));
							 | 
						||
| 
								 | 
							
										if (types == null) return macro : Void;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Add an init function for initializing the JS module
							 | 
						||
| 
								 | 
							
										if (Context.defined("js")) {
							 | 
						||
| 
								 | 
							
											types.push(macro class Init {
							 | 
						||
| 
								 | 
							
												public static function init(onReady:Void->Void) {
							 | 
						||
| 
								 | 
							
													untyped __js__('${opts.nativeLib} = ${opts.nativeLib}().then(onReady)');
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// For HL no initialization is required so execute the callback immediately
							 | 
						||
| 
								 | 
							
										} else if (Context.defined("hl")) {
							 | 
						||
| 
								 | 
							
											types.push(macro class Init {
							 | 
						||
| 
								 | 
							
												public static function init(onReady:Void->Void) {
							 | 
						||
| 
								 | 
							
													onReady();
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										Context.defineModule(module, types);
							 | 
						||
| 
								 | 
							
										Context.registerModuleDependency(module, file);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return macro : Void;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
									 * Capitalize the first letter of a string
							 | 
						||
| 
								 | 
							
									 * @param text The string to capitalize
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									private static function capitalize(text:String) {
							 | 
						||
| 
								 | 
							
										return text.charAt(0).toUpperCase() + text.substring(1);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#end
							 |