Mercurial > projects > dstep
diff scripts/dgen.rb @ 16:19885b43130e
Huge update, the bridge actually works now
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Sun, 03 Jan 2010 22:06:11 +0100 |
parents | 7ff919f595d5 |
children |
line wrap: on
line diff
--- a/scripts/dgen.rb Mon Aug 03 15:31:48 2009 +0200 +++ b/scripts/dgen.rb Sun Jan 03 22:06:11 2010 +0100 @@ -12,6 +12,7 @@ require "xmlsimple" require "optparse" require "date" +require "stringio" # Extensions to String class String @@ -323,15 +324,17 @@ file << header.function_pointers file << header.c_constants file << header.d_constants + file << header.d_constants_static_this unless header.d_constants_static_this.length == 0 file << header.enums_gnu if header.needs_type_encoding file << header.enums file << header.structs - unless header.d_constants_static_this.length == 0 - file << "static this ()".nl(false) - file << "{".nl(false) - file << header.d_constants_static_this - file << "}".nl(false).nl(false) + # Put the templates/mixins before the classes just to make sure we don't get forward reference errors + templates = get_templates(header.name) + + templates.each do |template, value| + file << value.code.nl(false) + @templates.delete(template) end classes = get_classes(header.name) @@ -348,18 +351,12 @@ @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 << copyright file << "module " file << mod file << "_bindings;" @@ -390,15 +387,17 @@ file << header.function_pointers file << header.c_constants file << header.d_constants + file << header.d_constants_static_this unless header.d_constants_static_this.nil? file << header.enums_gnu if header.needs_type_encoding file << header.enums file << header.structs - unless header.d_constants_static_this.nil? - file << "static this ()".nl(false) - file << "{".nl(false) - file << header.d_constants_static_this - file << "}".nl(false).nl(false) + # Put the templates/mixins before the classes just to make sure we don't get forward reference errors + templates = get_templates(header.name) + + templates.each do |template, value| + file << value.code.nl(false) + @templates.delete(template) end classes = get_classes(header.name) @@ -414,13 +413,6 @@ 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 @@ -548,12 +540,7 @@ end str << "{".nl(false) - str << "mixin ObjcWrap".indent.nl - - templates_for_class(clazz.name).each do |template, value| - str << "mixin #{get_identifier("T" + template)}".indent.nl - end - + str << "mixin (ObjcWrap)".indent.nl str << "\n" str << methods(clazz.method, clazz.name) @@ -567,7 +554,12 @@ str << methods(interface.method, interface.name) str << "\n" unless i == protocols.length - 1 end - end + end + + # Put the mixins at the end of the class just to make sure we don't get any forward reference errors + templates_for_class(clazz.name).each do |template, value| + str << "mixin (#{get_identifier("T" + template)})".indent.nl + end str << "}".nl(false) @@ -633,15 +625,20 @@ # Generates the D code for the templates def templates (templates) templates.each do |template| + methods = methods(template.method, template.name, true) #unless template["class"] == "NSObject" + bindings = bindings(template) + str = StringIO.new - str << "template " + str << "const " str << get_identifier("T" + 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) + str << " = `".nl(false) + str << "".nl(false) + #str << interface_methods(template.method, template.name) if template["class"] == "NSObject" + + str << methods.nl(false) + str << bindings.nl(false) + str << "`".nl @templates[template.name] ||= {} @templates[template.name].code = str.string @@ -652,6 +649,23 @@ end end + def bindings (template) + str = StringIO.new + + template.method.each do |method| + static = method.classMethod == "true" + + str << "mixin ObjcBindMethod!(".indent unless static + str << "mixin ObjcBindClassMethod!(".indent if static + str << get_method_name(method.selector) + str << ', "' + str << method.selector + str << '")'.nl + end + + str.string + end + # Generates the D code for the constants/globals def constants (constants) return "" if constants.length == 0 @@ -722,20 +736,23 @@ str = StringIO.new + str << "private\n{\n" + @d_constants.each do |constant| # Deep copy constant c = constant.dup c.name = c.name.dup c.type = c.type.dup - str << "const " if constant.const - str << get_identifier(constant.type) + #str << "const " if constant.const + str << get_identifier(constant.type).indent str << " " - str << get_identifier(constant.name).nl + str << get_identifier(constant.name) + str << "_".nl @d_constants_static_this << c end - str << "\n" + str << "}\n\n" @d_constants.clear str.string end @@ -747,13 +764,34 @@ str = StringIO.new @d_constants_static_this.each do |constant| - str << constant.name.indent - str << " = new " - str << get_identifier(constant.type) - str << "(" - str << "bindings." - str << get_identifier(constant.name) + # str << constant.name.indent + # str << " = new " + # str << get_identifier(constant.type) + # str << "(" + # str << "bindings." + # str << get_identifier(constant.name) + # str << ")".nl + + str << constant.type + str << " " + str << constant.name + str << " ()".nl(false) + str << "{".nl(false) + str << "if (".indent + str << constant.name + "_" + str << ")".nl(false) + str << "return ".indent(2) + str << constant.name + str << "_".nl + str << "\n" + str << "return ".indent + str << constant.name + str << "_ = new " + str << constant.type + str << "(bindings." + str << constant.name str << ")".nl + str << "}\n\n" end @d_constants_static_this.clear @@ -906,7 +944,7 @@ else return_type = get_type(original_type, function.returnValue[0].type64, function.returnValue[0].declaredType) args(function.arg, variadic) unless function.arg.nil? - end + end str << "static " if static str << return_type @@ -999,7 +1037,7 @@ def functions_helper (function, wrapper_needed) str = StringIO.new - str << ("private " + build_function(function)).indent if wrapper_needed + str << ("package " + build_function(function)).indent if wrapper_needed str << build_function(function).indent unless wrapper_needed str.string @@ -1074,7 +1112,7 @@ if @needs_bridge str << "import dstep.objc.bridge.Bridge".nl str << "import dstep.objc.bridge.TypeEncoding".nl if header.needs_type_encoding - str << "import dstep.objc.objc : id".nl + str << "import dstep.objc.objc".nl end str << "\n\n" @@ -1086,32 +1124,77 @@ end # Generates the D code for the methods - def methods (methods, class_name) + def methods (methods, class_name, template = false) return "" if methods.length == 0 str = StringIO.new - methods.each do |method| + methods.each do |method| + next if method.selector.length >= 5 && get_method_name(method.selector)[0 ... 5] == "alloc" # skip alloc + + name = get_method_name(method.selector) return_type = get_type(method.returnValue[0].type, method.returnValue[0].type64, method.returnValue[0].declaredType) + + if name.length >= 4 && name[0 ... 4] == "init" && name != "initialize" + if template + return_type = "typeof(this)" + else + return_type = class_name + end + + method["returnValue"][0]["declaredType"] = return_type + end + 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(" ") if static - index = declaration.index_of(" ", index) - name = get_method_name(method.selector) + index = declaration.index_of(" ", index) str << (declaration[0 .. index] + name + declaration[index .. -1]).gsub(/ +/, " ") str << "{".indent.nl(false) + has_ref = false + + method.arg.each_with_index do |arg, i| + if arg.declaredType =~ /NSError\*\*/ || arg.declaredType =~ /NSDictionary\*\*/ + has_ref = true + str << "id __arg#{i};\n".indent(2) + end + end if method.arg + + if has_ref + str << "\n" + + method.arg.each_with_index do |arg, i| + if arg.declaredType =~ /NSError\*\*/ || arg.declaredType =~ /NSDictionary\*\*/ + str << "if (#{arg.name})\n".indent(2) + str << "__arg#{i} = #{arg.name}.objcObject".indent(3).nl.nl(false) + end + end if method.arg + end + if static - str << "return invokeObjcSelfClass!(".indent(2) - str << return_type + if has_ref + str << "#{return_type} result = ".indent(2) unless return_type == "void" + str << "".indent(2) if return_type == "void" + str << "invokeObjcSelf!(" + str << return_type + else + str << "return invokeObjcSelfClass!(".indent(2) + str << return_type + end else if return_type == class_name str << "id result = invokeObjcSelf!(".indent(2) str << "id" + elsif has_ref + str << "#{return_type} result = ".indent(2) unless return_type == "void" + str << "".indent(2) if return_type == "void" + str << "invokeObjcSelf!(" + str << return_type else str << "return invokeObjcSelf!(".indent(2) str << return_type @@ -1124,7 +1207,12 @@ method.arg.each do |arg| str << ", " - str << get_type(arg.type, arg.type, arg.declaredType) + + if arg.declaredType =~ /NSError\*\*/ || arg.declaredType =~ /NSDictionary\*\*/ + str << "id*" + else + str << get_type(arg.type, arg.type, arg.declaredType) + end end unless method.arg.nil? unless method.arg.nil? @@ -1133,39 +1221,65 @@ end method.arg.each_with_index do |arg, i| - str << get_identifier(arg.name) + if arg.declaredType =~ /NSError\*\*/ || arg.declaredType =~ /NSDictionary\*\*/ + str << "&__arg#{i}" + else + str << get_identifier(arg.name) + end + str << ", " unless i == method.arg.length - 1 end unless method.arg.nil? str << ")".nl - str << "return result is this.objcObject ? this : (result !is null ? new #{return_type}(result) : null)".indent(2).nl if return_type == class_name && !static + + if has_ref + str << "\n" + + method.arg.each_with_index do |arg, i| + if arg.declaredType =~ /NSError\*\*/ || arg.declaredType =~ /NSDictionary\*\*/ + str << "if (__arg#{i})\n".indent(2) + argType = get_type(arg.type, arg.type64, arg.declaredType) + argType = argType[4 .. -1] # cut off "ref " + str << "#{arg.name} = new #{argType}(__arg#{i})".indent(3).nl + end + end + + unless return_type == "void" || return_type == class_name || return_type == "typeof(this)" + str << "\n" + str << "return result".indent(2).nl + end + end + + if (return_type == class_name || return_type == "typeof(this)") && !static + str << "\n" + str << "return result is this.objcObject ? this : (result !is null ? new #{return_type}(result) : null)".indent(2).nl + end + str << "}".indent.nl(false).nl(false) if name.length >= 4 && name[0 ... 4] == "init" && name != "initialize" str << ("this" + declaration[index .. -1]).gsub(/ +/, " ").indent str << "{".indent.nl(false) - str << 'objcObject = Bridge.invokeObjcClassMethod!(id, "alloc")(objcClass)'.indent(2).nl - str << 'id result = Bridge.invokeObjcMethod!(id, "'.indent(2) - str << method.selector - str << '"' - - method.arg.each do |arg| - str << ", " - str << get_type(arg.type, arg.type, arg.declaredType) - end unless method.arg.nil? + str << "super(".indent(2) + str << typeof(this) if template + str << class_name unless template + str << ".alloc." + str << get_method_name(method.selector) - str << ")(objcObject" + unless method.arg.nil? + str << "(" + args = StringIO.new + + method.arg.each do |arg| + args << get_identifier(arg.name) + args << ", " + end + + str << args.string[0 ... -2] + str << ")" + end - method.arg.each do |arg| - str << ", " - str << get_identifier(arg.name) - end unless method.arg.nil? - - str << ")".nl.nl(false) - - str << "if (result)".indent(2).nl(false) - str << "objcObject = ret".indent(3).nl.nl(false) - str << "dObject = this".indent(2).nl + str << ".objcObject)".nl str << "}".indent.nl(false).nl(false) end end @@ -1287,6 +1401,7 @@ when "NSInteger"; return type when "NSUInteger"; return type when "IMP"; return type; + when "size_t"; return type; when "unichar*" when "UniChar*"; return "wchar*" @@ -1294,6 +1409,7 @@ when "CGFloat*"; return type when "NSInteger*"; return type when "NSUInteger*"; return type + when "size_t*"; return type; when "unichar**" when "UniChar**"; return "wchar**" @@ -1301,7 +1417,14 @@ when "CGFloat**"; return type when "NSInteger**"; return type when "NSUInteger**"; return type - else return nil; + when "size_t**"; return type; + + # special case, asume ref parameter + when "NSError**"; return "ref NSError" + when "NSDictionary**"; return "ref NSDictionary" + when "typeof(this)"; return type + else + return nil; end end @@ -1338,13 +1461,13 @@ # get_type("I", "I", "unsigned int") #=> uint # def get_type (type, type64, declared_type) + t = check_declared_type(declared_type) + return t unless t.nil? + declared_type = "I" + $1 if declared_type =~ /\w+\s*<(.+)>/ declared_type.gsub!(/\(|\)/, "") 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 get_identifier(declared_type) if type != type64 @@ -1424,9 +1547,21 @@ get_identifier(resolved_types) when "^" - t = type[1 .. -1] - t64 = type64.nil? ? t : type64[1 .. -1] - get_identifier(get_type(t, t64, declared_type).dup + "*") + if type == "^@" + t = type[1 .. -1] + t64 = type64.nil? ? t : type64[1 .. -1] + get_identifier(get_type(t, t64, "ref " + declared_type).dup) + + elsif type == "^?" + tmp = cfp_to_dfp(type) + return get_identifier(tmp) unless tmp.nil? + end + # t = type[1 .. -1] + # t64 = type64.nil? ? t : type64[1 .. -1] + # get_identifier(get_type(t, t64, declared_type).dup + "*") + + + # if type == "^@" # return get_identifier(get_type(type[1 .. -1], type64[1 .. -1], declared_type).dup + "*")