diff scripts/dgen.rb @ 2:9fd439a28ce3

Adapted the scripts for the new bridge + a lot more
author Jacob Carlborg <doob@me.com>
date Sun, 05 Jul 2009 17:16:19 +0200
parents 033d260cfc9b
children d0162d8ca0f2
line wrap: on
line diff
--- a/scripts/dgen.rb	Thu Jun 18 22:00:13 2009 +0200
+++ b/scripts/dgen.rb	Sun Jul 05 17:16:19 2009 +0200
@@ -1,7 +1,7 @@
 #!/usr/bin/env ruby
 
 ##
-# Copyright:: Copyright (c) 2009 Jacob Carlborg. All rights reserved.
+# Copyright:: Copyright (c) 2009 Jacob Carlborg.
 # Author:: Jacob Carlborg
 # Version:: Initial created: 2009
 # License:: [Boost Software License 1.0]http://www.boost.org/LICENSE_1_0.txt
@@ -11,6 +11,7 @@
 gem "xml-simple"
 require "xmlsimple"
 require "optparse"
+require "date"
 
 # Extensions to String
 class String	
@@ -180,8 +181,8 @@
 end
 
 # This Struct represents a C/Objective-C header
-HeaderFile = Struct.new(:name, :framework, :cftypes, :constants, :d_constants, :d_constants_static_this, :defines, 
-			  			:enums, :functions, :function_wrappers, :imports, :path, :structs, :typedefs) do
+HeaderFile = Struct.new(:name, :framework, :cftypes, :constants, :c_constants, :d_constants, :d_constants_static_this, :defines, 
+			  			:enums, :functions, :c_functions, :function_wrappers, :imports, :path, :structs, :typedefs) do
 	def initialize
 		self.name = ""
 		self.cftypes = []
@@ -190,11 +191,13 @@
 		self.enums = []
 		self.framework = ""
 		self.functions = []
+		self.c_functions = []
 		self.function_wrappers = []
 		self.imports = []
 		self.path = ""
 		self.structs = []
 		self.typedefs = []
+		self.d_constants_static_this = []
 	end	
 end
 
@@ -208,12 +211,17 @@
 	# Creates a new instance of the ObjcToD class
 	def initialize
 		@classes = {}
+		@interfaces = {}
+		@interfaces2 = []
+		@templates = {}
 		@copyright = nil
+		@c_constants = []
 		@d_constants = []
 		@d_constants_static_this = []
 		@files = []
 		@frameworks = []
 		@function_wrappers = []
+		@c_functions = []
 		@headers = []
 		@package = "dstep"
 	end	
@@ -234,10 +242,12 @@
 						header = HeaderFile.new
 						header.name = file.name
 						header.constants = constants(file.constant) unless file.constant.nil?
+						header.c_constants = c_constants unless file.constant.nil?
 						header.d_constants = d_constants unless file.constant.nil?
 						header.d_constants_static_this = d_constants_static_this unless file.constant.nil?
 						header.enums = enums(file.enum) unless file.enum.nil?
 						header.functions = functions(file.function) unless file.function.nil?
+						header.c_functions = c_functions unless file.function.nil?
 						header.function_wrappers = function_wrappers unless file.function.nil?
 						header.imports = imports(file.import, file.name, framework.name) unless file.import.nil?
 						header.structs = structs(file.struct) unless file.struct.nil?
@@ -258,10 +268,12 @@
 					header = HeaderFile.new
 					header.name = file.name
 					header.constants = constants(file.constant) unless file.constant.nil?
+					header.c_constants = c_constants unless file.constant.nil?
 					header.d_constants = d_constants unless file.constant.nil?
 					header.d_constants_static_this = d_constants_static_this unless file.constant.nil?
 					header.enums = enums(file.enum) unless file.enum.nil?
 					header.functions = functions(file.function) unless file.function.nil?
+					header.c_functions = c_functions unless file.function.nil?
 					header.function_wrappers = function_wrappers unless file.function.nil?
 					header.imports = imports(file.import, file.name) unless file.import.nil?
 					header.structs = structs(file.struct) unless file.struct.nil?
@@ -270,36 +282,41 @@
 					@headers << header
 				end
 			end
-
-			unless xml["class"].nil?
-				classes(xml["class"])
-			end
+			
+			interfaces(xml.protocol) unless xml.protocol.nil?
+			templates(xml.category) unless xml.category.nil?
+			classes(xml["class"]) unless xml["class"].nil?						
 		end
 	end
 	
 	# Outputs the generate D code
 	def output_code
 		@frameworks.each do |framework|
-			framework_path = framework_path = "#{@out_dir}/#{@package}/#{framework.name}"
+			framework_path = framework_path = "#{@out_dir}/#{@package}/#{get_identifier(get_framework_name(framework.name.downcase))}"
 			
 			FileUtils.mkdir_p(framework_path) unless File.exist?(framework_path)
 			
 			framework.files.each do |header|
-				file_path = "#{framework_path}/#{header.name}.d"
+				file_path = "#{framework_path}/#{get_identifier(header.name)}"
+				bindings_file_path = file_path + "_bindings.d"
+				file_path << ".d"
+				mod = "#{@package}.#{get_identifier(get_framework_name(framework.name.downcase))}.#{get_identifier(header.name)}"
 				
 				File.open(file_path, "w") do |file|
 					file << copyright
-					file << "module #{@package}.#{framework.name}.#{header.name};"
-					file << header.imports.nl(false)
+					file << "module #{mod};"
+					file << header.imports
+					file << "\n" unless @d_constants.length > 0 || @function_wrappers.length > 0
+					file << "import bindings = #{mod}_bindings".nl.nl(false) if @d_constants.length > 0 || @function_wrappers.length > 0
 					file << header.defines
 					file << header.typedefs
-					file << header.cftypes				
-					file << header.constants
+					file << header.cftypes
+					file << header.c_constants
 					file << header.d_constants
 					file << header.enums
 					file << header.structs
 					
-					unless header.d_constants_static_this.nil?
+					unless header.d_constants_static_this.length == 0
 						file << "static this ()".nl(false)
 						file << "{".nl(false)
 						file << header.d_constants_static_this
@@ -313,26 +330,54 @@
 						@classes.delete(clazz)
 					end
 					
-					file << header.functions
+					interfaces = get_interfaces(header.name)
+					
+					interfaces.each do |interface, value|
+						file << value.code.nl(false)
+						@interfaces.delete(interface)
+					end
+					
+					templates = get_templates(header.name)
+					
+					templates.each do |template, value|
+						file << value.code.nl(false)
+						@templates.delete(template)
+					end
+					
 					file << header.function_wrappers
+					file << header.c_functions									
 				end
+				
+				File.open(bindings_file_path, "w") do |file|
+					file << "module "
+					file << mod
+					file << "_bindings;"
+					file << header.imports.nl(false)
+					file << header.constants
+					file << header.functions
+				end if @d_constants.length > 0 || @function_wrappers.length > 0	
 			end
 		end
 		
 		package_path = "#{@out_dir}/#{@package}"
 		FileUtils.mkdir_p(package_path) unless File.exist?(package_path)
 		
-		@headers.each do |header|
-			header_path = "#{package_path}/#{header.name}.d"
+		@headers.each do |header|			
+			header_path = "#{package_path}/#{get_identifier(header.name)}"
+			bindings_file_path = header_path + "_bindings.d"
+			header_path << ".d"
+			mod = "#{@package}.#{get_identifier(header.name)}"
 			
 			File.open(header_path, "w") do |file|
 				file << copyright
-				file << "module #{@package}.#{header.name};"
-				file << header.imports.nl(false)
+				file << "module #{mod};"
+				file << header.imports
+				file << "\n" unless @d_constants.length > 0 || @function_wrappers.length > 0
+				file << "import bindings = #{mod}_bindings".nl.nl(false) if @d_constants.length > 0 || @function_wrappers.length > 0
 				file << header.defines
 				file << header.typedefs
-				file << header.cftypes				
-				file << header.constants
+				file << header.cftypes
+				file << header.c_constants
 				file << header.d_constants
 				file << header.enums
 				file << header.structs
@@ -350,14 +395,37 @@
 					file << value.code.nl(false)
 					@classes.delete(clazz)
 				end
+				
+				interfaces = get_interfaces(header.name)
+				
+				interfaces.each do |interface, value|
+					file << value.code.nl(false)
+					@interfaces.delete(interface)
+				end
+				
+				templates = get_templates(header.name)
+				
+				templates.each do |template, value|
+					file << value.code.nl(false)
+					@templates.delete(template)
+				end
 
+				file << header.function_wrappers
+				file << header.c_functions	
+			end
+				
+			File.open(bindings_file_path, "w") do |file|
+				file << "module "
+				file << mod
+				file << "_bindings;"
+				file << header.imports.nl(false)
+				file << header.constants
 				file << header.functions
-				file << header.function_wrappers
-			end			
+			end if @d_constants.length > 0 || @function_wrappers.length > 0					
 		end
 		
 		@classes.each do |clazz, value|
-			class_path = "#{package_path}/#{clazz}.d"
+			class_path = "#{package_path}/#{get_identifier(clazz)}.d"
 			
 			File.open(class_path, "w") do |file|
 				file << value.code unless value.nil?
@@ -395,7 +463,7 @@
 	def get_framework (class_name)
 		@frameworks.each do |framework|
 			framework.files.each do |file|
-				return framework.name if file.name == class_name
+				return get_identifier(framework.name) if file.name == class_name
 			end
 		end
 		
@@ -409,70 +477,194 @@
 		end
 		
 		return classes
-	end	
+	end
+	
+	# Gets the interfaces that belongs to the given file
+	def get_interfaces (name)		
+		interfaces = @interfaces.find_all do |interface, value|
+			value.file == name
+		end
+		
+		return interfaces
+	end
+	
+	# Gets the templates that belongs to the given file
+	def get_templates (name)		
+		templates = @templates.find_all do |template, value|
+			value.file == name
+		end
+		
+		return templates
+	end
 	
 	# Generates the D code for the classes
 	def classes (classes)
 		classes.each do |clazz|
 			str = StringIO.new
+			protocols = []
 			
 			str << "class "
 			
 			if clazz == ""
-				str << clazz.name.nl(false)
+				str << get_identifier(clazz.name).nl(false)
 			else
-				str << clazz.name
-				str << " : "
-				str << clazz.parent.nl(false)
+				str << get_identifier(clazz.name)
+				
+				unless clazz.parent == ""
+					str << " : "
+					str << get_identifier(clazz.parent)
+				end
+				
+				unless clazz.protocols.length == 0
+					protocols = clazz.protocols.split(",")
+					
+					str2 = StringIO.new
+					
+					str2 << ", " unless clazz.parent.length == 0
+					str2 << " : " if clazz.parent.length == 0
+					
+					protocols.each do |protocol|
+						str2 << "I"
+						str2 << get_identifier(protocol)
+						str2 << ", "
+					end
+					
+					str << str2.string[0 .. -3]
+				end
+				
+				str << "\n"
 			end			
 			
 			str << "{".nl(false)
+			str << "mixin ObjcWrap".indent.nl
+			
+			templates_for_class(clazz.name).each do |template, value|
+				str << "mixin #{template}".indent.nl
+			end
+			
+			str << "\n"
+
 			str << methods(clazz.method, clazz.name)
+			str << "\n" if protocols.length > 0
+			
+			# implement the interfaces/protocols
+			protocols.each_with_index do |protocol, i|
+				interface = interface_for_protocol(protocol)
+				
+				unless interface.nil?
+					str << methods(interface.method, interface.name)
+					str << "\n" unless i == protocols.length - 1
+				end
+			end			
+			
 			str << "}".nl(false)
 			
 			@classes[clazz.name] ||= {}
 			@classes[clazz.name].code = str.string
 			framework = get_framework(clazz.file)
 			@classes[clazz.name].framework = framework unless framework.nil?
-			@classes[clazz.name].file = clazz.file
+			@classes[clazz.name].file = get_identifier(clazz.file)
+		end
+	end
+	
+	# Generates the D code for the interfaces
+	def interfaces (interfaces)
+		interfaces.each do |interface|
+			str = StringIO.new
+			
+			str << "interface I" # prepend I to the interface name, because it can be the same as a class name
+			
+			if interface == ""
+				str << get_identifier(interface.name).nl(false)
+			else
+				str << get_identifier(interface.name)
+				
+				unless interface.parent == ""
+					str << " : "
+					str << get_identifier(interface.parent)
+				end
+				
+				unless interface.protocols.length == 0
+					protocols = interface.protocols
+					protocols = protocols.split(",")
+					
+					str2 = StringIO.new
+					
+					str2 << ", " unless interface.parent.length == 0
+					str2 << " : " if interface.parent.length == 0
+					
+					protocols.each do |protocol|
+						str2 << "I"
+						str2 << get_identifier(protocol)
+						str2 << ", "
+					end
+					
+					str << str2.string[0 .. -3]
+				end
+				
+				str << "\n"
+			end
+			
+			str << "{".nl(false)
+			str << interface_methods(interface.method, interface.name)
+			str << "}".nl(false)
+			
+			@interfaces[interface.name] ||= {}
+			@interfaces[interface.name].code = str.string
+			framework = get_framework(interface.file)
+			@interfaces[interface.name].framework = framework unless framework.nil?
+			@interfaces[interface.name].file = get_identifier(interface.file)
+			@interfaces2 << interface
+		end
+	end
+	
+	# Generates the D code for the templates
+	def templates (templates)
+		templates.each do |template|
+			str = StringIO.new
+
+			str << "template "			
+			str << get_identifier(template.name)
+			str << " ()".nl(false)
+			str << "{".nl(false)
+			str << interface_methods(template.method, template.name) if template["class"] == "NSObject"
+			str << methods(template.method, template.name) unless template["class"] == "NSObject"
+			str << "}".nl(false)
+
+			@templates[template.name] ||= {}
+			@templates[template.name].code = str.string
+			framework = get_framework(template.file)
+			@templates[template.name].framework = framework unless framework.nil?
+			@templates[template.name].file = get_identifier(template.file)
+			@templates[template.name][:class] = get_identifier(template["class"])
 		end
 	end
 	
 	# Generates the D code for the constants/globals
 	def constants (constants)
+		return "" if constants.length == 0
+			
 		str = StringIO.new
 		
-		str << "private extern (C)".nl(false)
+		str << "extern (C)".nl(false)
 		str << "{".nl(false)
 		str << "extern".indent.nl(false)
 		str << "{".indent.nl(false)
 		
 		constants.each do |constant|
-			type = get_type(constant.type, constant["type64"], constant["declaredType"])
-			const = constant["const"] == "true"
+			type = get_type(constant.type, constant.type64, constant.declaredType)
+			const = constant.const == "true"
 			
-			if constant.type == "@"				
+			if constant.type == "@"
 				@d_constants << { :name => constant.name.dup, :type => constant.declaredType.gsub("*", ""), :const => const }
 				
-				if const
-					str << "const id".indent(2)
-				else
-					str << "id".indent(2)
-				end
-				
+				str << "private ".indent(2)
+				str << "const id" if const
+				str << "id" unless const				
 				str << " "
-				str << constant["name"]
-				str << "_".nl
+				str << get_identifier(constant["name"]).nl
 			else
-				if const
-					str << "const ".indent(2)
-					str << type
-				else
-					str << "id".indent(2)
-				end
-				
-				str << " "
-				str << constant["name"].nl
+				@c_constants << { :name => constant.name.dup, :type => type, :const => const }
 			end
 		end
 		
@@ -482,8 +674,40 @@
 		str.string
 	end
 	
+	def c_constants
+		return "" if @c_constants.length == 0
+		
+		str = StringIO.new
+		
+		str << "extern (C)".nl(false)
+		str << "{".nl(false)
+		str << "extern".indent.nl(false)
+		str << "{".indent.nl(false)
+		
+		@c_constants.each do |constant|
+			if constant.const
+				str << "const ".indent(2)
+				str << constant.type
+			else
+				str << constant.type.indent(2)
+			end
+			
+			str << " "
+			str << get_identifier(constant.name).nl
+		end
+		
+		str << "}".indent.nl(false)
+		str << "}".nl(false).nl(false)
+		
+		@c_constants.clear
+		str.string
+	end
+	
+	
     # Generates the D code for the constants that D can't handle directly, like classes
 	def d_constants
+		return "" if @d_constants.length == 0
+			
 		str = StringIO.new
 		
 		@d_constants.each do |constant|
@@ -493,9 +717,9 @@
 			c.type = c.type.dup
 			
 			str << "const " if constant.const
-			str << constant.type
+			str << get_identifier(constant.type)
 			str << " "			
-			str << constant.name.nl
+			str << get_identifier(constant.name).nl
 			@d_constants_static_this << c
 		end
 		
@@ -506,15 +730,18 @@
 	
 	# Generates the D code for the constants the has to be in a "static this"
 	def d_constants_static_this
+		return "" if @d_constants_static_this.length == 0
+		
 		str = StringIO.new
 		
 		@d_constants_static_this.each do |constant|
 			str << constant.name.indent
 			str << " = new "
-			str << constant.type
+			str << get_identifier(constant.type)
 			str << "("
-			str << constant.name
-			str << "_)".nl
+			str << "bindings."
+			str << get_identifier(constant.name)
+			str << ")".nl
 		end
 		
 		@d_constants_static_this.clear
@@ -523,33 +750,36 @@
 	
 	# Generates the D code for the enums
 	def enums (enums)
+		return "" if enums.length == 0
+		
 		str = StringIO.new
 		
 		enums.each do |enum|
 			str << "enum"
 								
-			if enum["name"] == ""
-				str << "\n{".nl
+			if enum.name.length == 0
+				str << "\n{".nl(false)
 				
 				enum.member.each_with_index do |member, i|
-					str << member["name"].indent
-					str << " = "
+					str << get_identifier(member["name"]).indent
+					str << " = " if member.value.length > 0
 					str << member.value
 					str << ",".nl(false) unless i == enum.member.length - 1
 				end				
 			else
-				str << enum["name"].nl
-				str << "{"
+				str << " "
+				str << get_identifier(enum["name"]).nl(false)
+				str << "{".nl(false)
 				
 				enum["member"].each_with_index do |member, i|
-					str << member["name"].indent
-					str << " = "
+					str << get_identifier(member["name"]).indent
+					str << " = " if member.value.length > 0
 					str << member.value
 					str << ",".nl(false) unless i == enum.member.length - 1
 				end
 			end
 			
-			str << "\n}".nl.nl(false)
+			str << "\n}".nl(false).nl(false)
 		end
 		
 		str.string
@@ -573,7 +803,7 @@
 			
 			str << type
 			str << " "
-			str << arg["name"]
+			str << get_identifier(arg["name"])
 			str << ", "
 		end
 		
@@ -590,7 +820,7 @@
 	# A helper function that generates the D code for the functions/methods
 	def build_function (function, method = false, static = false)
 		str = StringIO.new
-		variadic = function["variadic"] == "true"
+		variadic = function.variadic == "true"
 		return_type  = ""
 		args = ""
 		original_type = function.returnValue[0].type
@@ -615,49 +845,65 @@
 	
 	# Generates the D code for the functions
 	def functions (functions)
-		str = StringIO.new
+		return "" if functions.length == 0
 		
-		str << "private extern (C)".nl(false)
-		str << "{".nl(false)
+		str = StringIO.new
+		wrapper_needed = false
+		
+		str << "extern (C)".nl(false)
+		str << "{".nl(false)		
 		
 		functions.each do |function|
-			wrapper_needed = false
-			original_type = function["returnValue"][0].type
+			wrapper_needed = false		
+			original_type = function.returnValue[0].type
 			
 			if original_type == "@"
 				@function_wrappers << function
 				wrapper_needed = true
+				str << functions_helper(function, wrapper_needed)
 			else
-				function["arg"].each do |arg|
-					if (arg.type || arg["type64"]) == "@"
+				function.arg.each do |arg|
+					if (arg.type || arg.type64) == "@"
 						@function_wrappers << function
 						wrapper_needed = true
+						break
 					end
-				end unless function["arg"].nil?
+				end unless function.arg.nil?
+				
+				str << functions_helper(function, wrapper_needed) if wrapper_needed
+				@c_functions << function unless wrapper_needed
 			end
-			
-			return_type = get_type(function["returnValue"][0].type, function["returnValue"][0]["type64"], function["returnValue"][0]["declaredType"])
-			variadic = function["variadic"] == "true"			
-
-			str << functions_helper(function, wrapper_needed)
 		end
 		
-		str << "}".nl(false).nl(false)
+		str << "}"
 		str.string
 	end
 	
+	def c_functions	
+		return "" if @c_functions.length == 0
+		
+		str = StringIO.new
+		
+		str << "extern (C)".nl(false)
+		str << "{".nl(false)
+		
+		@c_functions.each do |function|
+			str << functions_helper(function, false)
+		end
+		
+		str << "}"
+		
+		@c_functions.clear
+		str.string
+	end
+	
+	
 	# A helper function that generates the D code for the functions
 	def functions_helper (function, wrapper_needed)
 		str = StringIO.new
-
-		if wrapper_needed
-			declaration = build_function(function)
-			index = declaration.index_of(" ")
-			index = declaration.index_of(" ", index)
-			str << (declaration[0 ... index] + "_" + declaration[index .. -1]).indent
-		else
-			str << build_function(function).indent
-		end
+		
+		str << ("private " + build_function(function)).indent if wrapper_needed
+		str << build_function(function).indent unless wrapper_needed
 
 		str.string
 	end	
@@ -665,113 +911,70 @@
 	# Generates the D code for the functions that D can't handle without wrappers, like functions that takes
 	# objects as arguments or returns an object
 	def function_wrappers
+		return "" if @function_wrappers.length == 0
+			
 		str = StringIO.new
 		
 		@function_wrappers.each do |function|
-			original_type = function["returnValue"][0].type
-			variadic = function["variadic"] == "true"
-			args = StringIO.new
-			out_args = []
-			return_type = get_type(original_type, function.returnValue[0].type64, function.returnValue[0].declaredType)
-			
-			function["arg"].each do |arg|
-				args << arg["name"]
-				
-				if arg.type == "@"
-					args << " !is null ? "
-					args << arg["name"]
-					args << ".id : null"
-				elsif arg.type == "^@"
-					type = get_type(arg.type, arg["type64"], arg["declaredType"])
-					out_args << { :type => type[4 .. -1], :name => arg["name"] }
-					
-					args << " &"
-					args << arg["name"]
-					args << "_.id"
-				end
-				
-				args << ", "
-			end unless function["arg"].nil?
-			
+			return_type = get_type(function.returnValue[0].type, function.returnValue[0].type64, function.returnValue[0].declaredType)
+			variadic = function.variadic == "true"
+
 			str << build_function(function, true)[0 ... -2].nl(false)
 			str << "{".nl(false)
-			
-			out_args.each do |arg|
-				str << arg.type.indent
-				str << " "
-				str << arg.name
-				str << "_ = new "
-				str << arg.type
-				str << "(false, false)".nl
-			end
-			
-			str << "\n" if out_args.length > 0
-			
-			if original_type == "@"
-				str << "id result = ".indent
-				str << function["name"]
-			elsif original_type != "v"
-				if out_args.length > 0					
-					str << return_type.indent				
-					str << " result = "
-				else
-					str << "return ".indent
-				end
-			end
-			
-			if original_type == "v"
-				str << function["name"].indent
-			elsif original_type != "@"
-				str << "cast("
-				str << return_type
-				str << ") "
-				str << function["name"]
-			end
-			
-			str << "_"
-			str << "("			
-			str << args.string[0 ... -2] unless function["arg"].nil?
-			str << ")".nl
-			str << "\n" if out_args.length > 0
-			
-			out_args.each do |arg|
-				str << arg.name.indent(2)
-				str << " = "
-				str << arg.name
-				str << "_".nl
-			end
-			
-			if out_args.length > 0
-				str << "\n"
-				str << "return result".indent unless original_type == "v"				
+			str << "return Bridge.invokeObjcFunction!(".indent
+			str << return_type
+			str << ", bindings."
+			str << function.name
+
+			function.arg.each do |arg|
+				str << ", "
+				str << get_type(arg.type, arg.type, arg.declaredType)
+			end unless function.arg.nil?
+
+			unless function.arg.nil?
+				str << ")"
+				str << "("
 			end
 
-			if original_type == "@"
-				str << "return result !is null ? new ".indent
-				str << return_type				
-				str << "(result)".nl
-			elsif original_type != "v" && out_args.length > 0
-				str << "".nl
-			end
-			
+			function.arg.each_with_index do |arg, i|
+				str << arg.name
+				str << ", " unless i == function.arg.length - 1
+			end unless function.arg.nil?
+
+			str << ")".nl
+
 			str << "}".nl(false).nl(false)
 		end
 		
 		@function_wrappers.clear		
-		str.string[0 ... -2]
+		str.string
 	end
 	
 	# Generates the D code for the imports
 	def imports (imports, filename, framework_name = nil)
+		return "" if imports.length == 0
+		
 		str = StringIO.new
 		
 		imports.each do |import|			
-			str << "import #{@package}."			
-			i = import.index('/')
-			import = import[0 ... i].downcase + import[i .. -1] if i
-			str << import.gsub("/", ".").gsub("Frameworks", "").gsub(".framework", "").gsub("Headers", "").gsub(/\.{2,}/, ".").nl
+			str << "import #{@package}."
+			import = import.gsub("/", ".").gsub("Frameworks", "").gsub(".framework", "").gsub("Headers", "").gsub(/\.{2,}/, ".").nl
+			
+			splits = import.split('.')
+			import = ""
+			
+			splits[0 .. -2].each do |s|
+				import << get_identifier(s.downcase)
+				import << '.'
+			end
+			
+			str << import
+			str << splits[-1 .. -1]
 		end
 		
+		str << "import dstep.objc.bridge.Bridge".nl
+		str << "import dstep.objc.objc : id".nl
+		
 		str << "\n\n"
 		str = str.string.sort.to_s		
 		
@@ -781,225 +984,83 @@
 	
 	# Generates the D code for the methods
 	def methods (methods, class_name)
+		return "" if methods.length == 0
+		
 		str = StringIO.new
 		
-		methods.each do |method|		
-			next if method.selector == ("alloc" || "init")
-				
-			return_type = get_type(method["returnValue"][0].type, method["returnValue"][0]["type64"], method["returnValue"][0]["declaredType"])
-			variadic = method["variadic"] == "true"
-			static = method["static"] == "true"
-			args = ""
-			out_args = []
-			original_type = method.returnValue[0].type
-			
-			if method.selector[0 ... 4] == "init" && return_type == "id"
-				return_type = class_name
-				method.returnValue[0].declaredType = class_name
-			end
+		methods.each do |method|				
+			return_type = get_type(method.returnValue[0].type, method.returnValue[0].type64, method.returnValue[0].declaredType)
+			variadic = method.variadic == "true"
+			static = method.classMethod == "true"
 			
-			method["arg"].each do |arg|
-				args << " &" if arg.type == "^@"
-				args << arg["name"]
-				
-				if arg.type == "@"
-					args << " !is null ? "
-					args << arg["name"]
-					args << ".id : null"
-				elsif arg.type == "^@"
-					type = get_type(arg.type, arg.type, arg["declaredType"])
-					out_args << { :type => type[4 .. -1], :name => arg["name"] }
-					args << "_.id"
-				end
-
-				args << ", "
-			end unless method["arg"].nil?
-			
+			index = 0
 			declaration = build_function(method, true, static)[0 ... -2].indent.nl(false)
-			index = declaration.index_of(" ")
+			index = declaration.index_of(" ") if static
+			index = declaration.index_of(" ", index) 
 			
 			str << (declaration[0 .. index] + get_method_name(method["selector"]) + declaration[index .. -1]).gsub(/ +/, " ")
 			str << "{".indent.nl(false)
+			str << "return invokeObjcSelf!(".indent(2) unless static
+			str << "return invokeObjcSelfClass!(".indent(2) if static
+			str << return_type
+			str << ', "'
+			str << method.selector
+			str << '"'
 			
-			out_args.each do |arg|
-				str << arg.type.indent(2)
-				str << " "
-				str << arg.name
-				str << "_ = new "
-				str << arg.type
-				str << "(false, false)".nl
+			method.arg.each do |arg|
+				str << ", "
+				str << get_type(arg.type, arg.type, arg.declaredType)
+			end unless method.arg.nil?
+			
+			unless method.arg.nil?
+				str << ")"
+				str << "("
 			end
 			
-			str << "\n" if out_args.length > 0
-			
+			method.arg.each_with_index do |arg, i|
+				str << arg.name
+				str << ", " unless i == method.arg.length - 1
+			end unless method.arg.nil?
 			
-			if method["returnValue"][0].type == "@"
-				str << "id result = objc_msgSend(#{this}, sel_".indent(2)
-				str << transform_selector(method["selector"])
-				str << ", " unless method.arg.nil?		
-				str << args[0 ... -2] unless method.arg.nil?
-				str << ")".nl					
-				str << "\n" if out_args.length > 0	
-				
-				out_args.each do |arg|
-					str << arg.name.indent(2)
-					str << " = "
-					str << arg.name
-					str << "_".nl
-				end
-				
-				str << "\n" if out_args.length > 0
-				
-				if method["returnValue"][0]["declaredType"] == class_name
-					str << "return result is this.id ? this : (return result ".indent(2)
-				else
-					str << "return result ".indent(2)
-				end
-				
-				str << "!is null ? new "
-				str << return_type					
-				str << "(result) : null"
-				
-				if method["returnValue"][0]["declaredType"] == class_name
-					str << ")".nl
-				else
-					str << "".nl
-				end
-				
-				str << "}".indent.nl(false).nl(false)				
-			else
-				if original_type == "d" || original_type == "f"
-					
-					str << "version (X86)".indent(2).nl(false)
-					
-					if out_args.length > 0
-						str << return_type.indent(3)
-						str << " result "
-					else						
-						if original_type == "d"
-							str << "return ".indent(3)
-						else
-							str << "return cast(".indent(3)
-							str << return_type
-							str << ") "
-						end							
-					end
-					
-					str << "objc_msgSend_fpret(#{this}, sel_"
-					str << transform_selector(method["selector"])
-					str << ", " unless method.arg.nil?
-
-					args = ""
-
-					method["arg"].each do |arg| 
-						args << arg["name"]
-						args << ", "
-					end unless method["arg"].nil?
-
-					str << args[0 ... -2] if args.length > 0
-					str << ")".nl.nl(false)
-					
-					str << "else".indent(2).nl(false)
-					
-					if out_args.length > 0
-						str << return_type.indent(3)
-						str << " result "
-					else						
-						if original_type == "d"
-							str << "return ".indent(3)
-						else
-							str << "return cast(".indent(3)
-							str << return_type
-							str << ") "
-						end							
-					end
-					
-					str << "objc_msgSend(#{this}, sel_"
-					str << transform_selector(method["selector"])
-					str << ", " unless method.arg.nil?
-
-					args = ""
-
-					method["arg"].each do |arg| 
-						args << arg["name"]
-						args << ", "
-					end unless method["arg"].nil?
-
-					str << args[0 ... -2] if args.length > 0
-					str << ")".nl
-					str << "\n" if out_args.length > 0					
-
-					out_args.each do |arg|
-						str << arg.name.indent(3)
-						str << " = "
-						str << arg.name
-						str << "_".nl
-					end
-
-					if out_args.length > 0
-						str << "\n"
-						str << "retrun result".indent(3).nl
-					end
-
-					str << "\n" if out_args.length > 0			
-					str << "}".indent.nl(false).nl(false)					
-				else
-					unless return_type == "void"					
-						if out_args.length > 0
-							str << return_type.indent(2)
-							str << " result "
-						else
-							str << "return cast(".indent(2)
-						end
-
-						str << return_type
-						str << ") "
-					end
-
-					str << "objc_msgSend(#{this}, sel_".indent(2) if return_type == "void"
-					str << "objc_msgSend(#{this}, sel_" unless return_type == "void"
-					str << transform_selector(method["selector"])
-					str << ", " unless method.arg.nil?
-
-					args = ""
-
-					method["arg"].each do |arg| 
-						args << arg["name"]
-						args << ", "
-					end unless method["arg"].nil?
-
-					str << args[0 ... -2] if args.length > 0
-					str << ")".nl
-
-					str << "\n" if out_args.length > 0
-
-					out_args.each do |arg|
-						str << arg.name.indent(2)
-						str << " = "
-						str << arg.name
-						str << "_".nl
-					end
-
-					if out_args.length > 0
-						str << "\n"
-						str << "retrun result".indent(2).nl
-					end
-							
-					str << "}".indent.nl(false).nl(false)
-				end				
-			end
+			str << ")".nl
+			
+			str << "}".indent.nl(false).nl(false)
 		end
 		
 		str.string[0 .. -2]
 	end
 	
+	# Generates the D code for the interface methods
+	def interface_methods (methods, interface_name)
+		return "" if methods.length == 0
+		
+		str = StringIO.new
+		
+		methods.each do |method|
+			return_type = get_type(method.returnValue[0].type, method.returnValue[0].type64, method.returnValue[0].declaredType)
+			
+			variadic = method.variadic == "true"
+			static = method.classMethod == "true"
+			
+			index = 0
+			declaration = build_function(method, true, static)[0 ... -2].indent.nl(false)
+			index = declaration.index_of(" ", index)
+			str << ((declaration[0 .. index] + get_method_name(method["selector"]) + declaration[index .. -1]).gsub(/ +/, " "))[0 .. -2]
+			str << ";\n"
+		end
+		
+		str.string
+	end	
+	
 	# Generates the D code for the structs
 	def structs (structs)
+		return "" if structs.length == 0
+		
 		str = StringIO.new
 		
 		structs.each do |struct|
 			str << "struct "
-			str << struct.name.nl(false)
+			str << get_identifier(struct.name).nl(false)
 			str << "{".nl
 			
 			struct.member.each do |member|
@@ -1007,7 +1068,7 @@
 				
 				str << type.indent
 				str << " "
-				str << member.name.nl
+				str << get_identifier(member.name).nl
 			end unless struct.member.nil?
 			
 			str << "}".nl
@@ -1019,6 +1080,8 @@
 	
 	# Generates the D code for the typedefs
 	def typedefs (typedefs)
+		return "" if typedefs.length == 0
+		
 		str = StringIO.new
 
 		typedefs.each do |typedef|
@@ -1027,26 +1090,24 @@
 			struct = false
 			
 			if typedef.type.struct?
-				type = get_struct_type(typedef.type, typedef["type64"], typedef["declaredType"])
+				type = get_struct_type(typedef.type, typedef.type64, typedef.declaredType)
 				struct = true
 			else
 				type = get_type(typedef.type, typedef.type64, typedef.declaredType)
 			end
 			
-			# Special case
-			type = "wchar" if typedef.name == "unichar"	
-			
 			if struct
-				str << typedef["declaredType"].gsub("*", "").nl
+				str << typedef.declaredType.gsub("*", "").nl
 				str << "alias "				
-				str << type[:name]
+				str << get_identifier(type.name)
+				str << "*" if typedef.declaredType =~ /\*/
 				str << " "
-				str << typedef["name"].nl
+				str << get_identifier(typedef.name).nl
 			else
 				str << "alias "
 				str << type
 				str << " "
-				str << typedef.name.nl
+				str << get_identifier(typedef.name).nl
 			end
 		end
 
@@ -1064,19 +1125,23 @@
 	#
 	def check_declared_type (type)		
 		case type
-			when "unichar"; return "wchar"
+			when "unichar"
+			when "UniChar"; return "wchar"
 			when "BOOL"; return "bool"
 			when "CGFloat"; return type
 			when "NSInteger"; return type
 			when "NSUInteger"; return type
+			when "IMP"; return type;
 				
-			when "unichar*"; return "wchar*"
+			when "unichar*"
+			when "UniChar*"; return "wchar*"
 			when "BOOL*"; return "bool*"
 			when "CGFloat*"; return type
 			when "NSInteger*"; return type
 			when "NSUInteger*"; return type
 				
-			when "unichar**"; return "wchar**"
+			when "unichar**"
+			when "UniChar**"; return "wchar**"
 			when "BOOL**"; return "bool**"
 			when "CGFloat**"; return type
 			when "NSInteger**"; return type
@@ -1093,7 +1158,7 @@
 	#
 	def get_method_name (selector)
 		i = selector.index_of(":")
-		selector[0 ... i]
+		get_identifier(selector[0 ... i])
 	end
 	
 	# Gets the D type from the encoded C/Objective-C type
@@ -1106,14 +1171,14 @@
 	# get_type("I", "I", "unsigned int")    #=> uint
 	#
 	def get_type (type, type64, declared_type)
-				
-		return declared_type if type.nil? || type64.nil?			
-				
+		
+		return get_identifier(declared_type) if type.nil? && type64.nil?
+			
 		t = check_declared_type(declared_type)
 		return t unless t.nil?
 		
 		unless type64 == "" || type64.nil?
-			return declared_type if type != type64
+			return get_identifier(declared_type) if type != type64
 		end
 		
 		case type
@@ -1135,9 +1200,15 @@
 		when '#'; return "Class"
 		when ":"; return "SEL"					
 		when "@"
-			return declared_type.gsub(/\*+/, "") unless declared_type.nil?
+			unless declared_type.nil?
+				t = declared_type.gsub(/\*+/, "")
+				return t == "id" ? "Object" : t
+			end
+			
 			raise "No declared type given"
 		else
+			return declared_type if type =~ /\{/
+			
 			case type[0, 1]
 			when "["
 				str = ""
@@ -1152,7 +1223,7 @@
 				str = get_type(t, t64, declared_type)
 				str << "[#{count}]"
 			
-				return str
+				return get_identifier(str)
 			when "("
 				resolved_types = []
 				types = $2 if type =~ /\((.+)=(.+)\)/
@@ -1162,28 +1233,34 @@
 					resolved_types << get_type(types[i], types64[i], declared_type)
 				end
 				
-				return resolved_types
-			when "^"				
+				return get_identifier(resolved_types)
+			when "^"	
 				if type == "^@"
-					return "out " << get_type(type[1 .. -1], type64[1 .. -1], declared_type).dup
+					return get_identifier(get_type(type[1 .. -1], type64[1 .. -1], declared_type).dup + "*")
 				elsif type.length > 2 && type[0 ... 2] == "^^"
-					return "out " << get_type(type[2 .. -1], type64[2 .. -1], declared_type).dup
-				elsif type == "^?"
+					return get_identifier(get_type(type[2 .. -1], type64[2 .. -1], declared_type).dup + "**")
+				elsif type == "^?" # assuming function pointer
 					tmp = cfp_to_dfp(type)
-					return tmp unless tmp.nil?
+					return get_identifier(tmp) unless tmp.nil?
 				end
 				
 				if !type.nil? && !type64.nil?
-					return get_type(type[1 .. -1], type64[1 .. -1], declared_type).dup << "*"
+					t = get_type(type[1 .. -1], type64[1 .. -1], declared_type).dup
+					
+					return get_identifier(t) if t =~ /\*/
+					return get_identifier(t + "*") if t !~ /\*/
 				elsif !type.nil?
-					return get_type(type[1 .. -1], type64, declared_type).dup << "*"
+					t = get_type(type[1 .. -1], type64, declared_type).dup << "*"
+					
+					return get_identifier(t) if t =~ /\*/
+					return get_identifier(t + "*") if t !~ /\*/
 				end			
 			when "{"
-				return declared_type
+				return get_identifier(declared_type)
 			end
 		end
 		
-		return declared_type
+		return get_identifier(declared_type)
 	end
 	
 	# Gets the D type from the encoded C/Objective-C type when it's a struct
@@ -1197,7 +1274,6 @@
     # { :name => "some", :types => ["uint", "uint", "uint"] }
 	#
 	def get_struct_type (type, type64, declared_type)
-		
 		return { :name => declared_type } if declared_type[0 ... 2] == "NS"
 		
 		case type[0, 1]
@@ -1205,11 +1281,11 @@
 			resolved_types = []
 		
 			if type =~ /\^{0,}\{(.{0,})=(.{0,})\}/
-				name = $1
-				types = $2
+				name = get_identifier($1)
+				types = get_identifier($2)
 			elsif type =~ /\^{0,}\((.{0,})=(.{0,})\)/
-				name = $1
-				types = $2
+				name = get_identifier($1)
+				types = get_identifier($2)
 			end
 		
 			unless types.nil?
@@ -1239,7 +1315,7 @@
 		name = $2
 		arg_types = $3
 		
-		return "#{return_type} function (#{arg_types})"
+		return "#{get_identifier(return_type)} function (#{arg_types})"
 	end
 	
 	# Is the supplied argument an "out" argument
@@ -1262,7 +1338,162 @@
 	#
 	def transform_selector (selector)
 		selector.gsub(/:/, "_")
+	end
+	
+	# Gets the identifier, if it's a D keyoword it
+	# will return string appended with a _ otherwise the string
+	def get_identifier (str)
+		return is_keyword?(str) ? str + "_" : str
 	end	
+	
+	# Returns true if the given string is a D(2) keyword
+	def is_keyword? (str)		
+		case str
+			when "abstract"; return true
+			when "alias"; return true
+			when "align"; return true
+			when "asm"; return true
+			when "assert"; return true
+			when "auto"; return true
+
+			when "body"; return true
+			when "bool"; return true
+			when "break"; return true
+			when "byte"; return true
+
+			when "case"; return true
+			when "cast"; return true
+			when "catch"; return true
+			when "cdouble"; return true
+			when "cent"; return true
+			when "cfloat"; return true
+			when "char"; return true
+			when "class"; return true
+			when "const"; return true
+			when "continue"; return true
+			when "creal"; return true
+
+			when "dchar"; return true
+			when "debug"; return true
+			when "default"; return true
+			when "delegate"; return true
+			when "delete"; return true
+			when "deprecated"; return true
+			when "do"; return true
+			when "double"; return true
+
+			when "else"; return true
+			when "enum"; return true
+			when "export"; return true
+			when "extern"; return true
+
+			when "false"; return true
+			when "final"; return true
+			when "finally"; return true
+			when "float"; return true
+			when "for"; return true
+			when "foreach"; return true
+			when "foreach_reverse"; return true
+			when "function"; return true
+
+			when "goto"; return true
+
+			when "idouble"; return true
+			when "if"; return true
+			when "ifloat"; return true
+			when "import"; return true
+			when "in"; return true
+			when "inout"; return true
+			when "int"; return true
+			when "interface"; return true
+			when "invariant"; return true
+			when "ireal"; return true
+			when "is"; return true
+
+			when "lazy"; return true
+			when "long"; return true
+
+			when "macro"; return true
+			when "mixin"; return true
+			when "module"; return true
+
+			when "new"; return true
+			when "nothrow"; return true
+			when "null"; return true
+
+			when "out"; return true
+			when "override"; return true
+
+			when "package"; return true
+			when "pragma"; return true
+			when "private"; return true
+			when "protected"; return true
+			when "public"; return true
+			when "pure"; return true
+
+			when "real"; return true
+			when "ref"; return true
+			when "return"; return true
+
+			when "scope"; return true
+			when "shared"; return true;s
+			when "short"; return true
+			when "static"; return true
+			when "struct"; return true
+			when "super"; return true
+			when "switch"; return true
+			when "synchronized"; return true
+
+			when "template"; return true
+			when "this"; return true
+			when "throw"; return true
+			when "true"; return true
+			when "try"; return true
+			when "typedef"; return true
+			when "typeid"; return true
+			when "typeof"; return true
+
+			when "ubyte"; return true
+			when "ucent"; return true
+			when "uint"; return true
+			when "ulong"; return true
+			when "union"; return true
+			when "unittest"; return true
+			when "ushort"; return true
+
+			when "version"; return true
+			when "void"; return true
+			when "volatile"; return true
+
+			when "wchar"; return true
+			when "while"; return true
+			when "with"; return true
+			else return false;
+		end
+	end
+	
+	def templates_for_class (clazz)		
+		templates = @templates.find_all do |template, value|
+			value[:class] == clazz
+		end
+		
+		return templates
+	end
+	
+	def interface_for_protocol (protocol)
+		interface = @interfaces2.find do |interface|
+			interface.name == protocol
+		end
+		
+		return interface
+	end	
+	
+	def get_framework_name (framework)
+		i = framework.rindex(".framework")
+		return framework if i.nil?
+		x = framework.rindex("/", i)
+		framework[x + 1 ... i]
+	end
 end
 
 # Prints the message to stderr, exits