From 42c962888a72d460ea9c52b05e9275e7083dacd5 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 27 Nov 2021 15:29:38 +0100 Subject: [PATCH] WIP: parser enhancements --- scripts/mkqtdecl5/mkqtdecl.conf | 3 + scripts/mkqtdecl_common/c++.treetop | 4 +- scripts/mkqtdecl_common/cpp_classes.rb | 7 +- scripts/mkqtdecl_common/cpp_parser_classes.rb | 2 +- scripts/mkqtdecl_common/produce.rb | 99 +++++++++++++------ 5 files changed, 81 insertions(+), 34 deletions(-) diff --git a/scripts/mkqtdecl5/mkqtdecl.conf b/scripts/mkqtdecl5/mkqtdecl.conf index 5d7330ad3..6ddb717ea 100644 --- a/scripts/mkqtdecl5/mkqtdecl.conf +++ b/scripts/mkqtdecl5/mkqtdecl.conf @@ -30,6 +30,9 @@ drop_method :all_classes, /::qt_check_for_QOBJECT_macro/ # don't include in API! drop_method :all_classes, /::devType\(/ # not required drop_method :all_classes, /::data_ptr/ # no private data drop_method :all_classes, /::x11/ # no X11 stuff +drop_method :all_classes, /\(.*&&.*\)/ # no move semantics +drop_method :all_classes, /.*\s+&&$/ # no move semantics +drop_method :all_classes, /\(.*std::initializer_list.*\)/ # no brace initialization rename :all_classes, /::create\(/, "qt_create" # clashes with GSI/Ruby rename :all_classes, /::destroy\(/, "qt_destroy" # clashes with GSI/Ruby diff --git a/scripts/mkqtdecl_common/c++.treetop b/scripts/mkqtdecl_common/c++.treetop index bc90c0a55..8c3dbcb68 100644 --- a/scripts/mkqtdecl_common/c++.treetop +++ b/scripts/mkqtdecl_common/c++.treetop @@ -289,11 +289,11 @@ grammar CPP end rule func_spec - "(" s fa:( a:func_args )? s ")" cvspec:( s cv:cv )? ( s "throw" s "(" s ( type_wo_comma s )? ")" / s noexcept_spec / s override_key )* a + "(" s fa:( a:func_args )? s ")" cvspec:( s cv:cv )? refspec:( s ref:( "&" !"&" / "&&" ) )? ( s "throw" s "(" s ( type_wo_comma s )? ")" / s noexcept_spec / s override_key )* a end rule member_pointer - cspec:( qid:qualified_id s "::*" s ) itspec:( it:inner_type )? cvspec:( s cv:cv )? + cspec:( qid:qualified_id s "::*" s ) itspec:( it:inner_type )? cvspec:( s cv:cv )? refspec:( s ref:( "&" !"&" / "&&" ) )? end rule inner_type_with_cv diff --git a/scripts/mkqtdecl_common/cpp_classes.rb b/scripts/mkqtdecl_common/cpp_classes.rb index 7168e38eb..bfad113f7 100644 --- a/scripts/mkqtdecl_common/cpp_classes.rb +++ b/scripts/mkqtdecl_common/cpp_classes.rb @@ -87,8 +87,8 @@ end # "cv" is a CPPCV object. class CPPFunc < CPPOuterType - attr_accessor :inner, :args, :cv - def_initializer :inner, :args, :cv + attr_accessor :inner, :args, :cv, :ref + def_initializer :inner, :args, :cv, :ref def to_s a = self.args @@ -96,12 +96,13 @@ class CPPFunc < CPPOuterType if !a.is_a?(Array) a = [a] end - self.inner.to_s + " (" + a.join(", ") + ")" + (self.cv ? " " + self.cv.to_s : "") + self.inner.to_s + " (" + a.join(", ") + ")" + (self.cv ? " " + self.cv.to_s : "") + (self.ref ? " " + self.ref.to_s : "") end def dump(i) i + "CPPFunc\n" + i + " inner:\n" + self.inner.dump(i + " ") + "\n" + i + " cv: " + self.cv.to_s + "\n" + + i + " ref: " + self.ref.to_s + "\n" + i + " args:\n" + (self.args || []).collect { |f| f.dump(i + " ") }.join("\n") end diff --git a/scripts/mkqtdecl_common/cpp_parser_classes.rb b/scripts/mkqtdecl_common/cpp_parser_classes.rb index beeba344d..08990bb43 100644 --- a/scripts/mkqtdecl_common/cpp_parser_classes.rb +++ b/scripts/mkqtdecl_common/cpp_parser_classes.rb @@ -241,7 +241,7 @@ end module PFuncSpec def cpp - CPPFunc::new(nil, (fa.nonterminal? && fa.text_value != "void") ? (fa.a.cpp || []) : [], cvspec.nonterminal? && cvspec.cv.to_symbol) + CPPFunc::new(nil, (fa.nonterminal? && fa.text_value != "void") ? (fa.a.cpp || []) : [], cvspec.nonterminal? && cvspec.cv.to_symbol, refspec.nonterminal? && refspec.ref.text_value) end end diff --git a/scripts/mkqtdecl_common/produce.rb b/scripts/mkqtdecl_common/produce.rb index 55e735b4e..188f59ad8 100755 --- a/scripts/mkqtdecl_common/produce.rb +++ b/scripts/mkqtdecl_common/produce.rb @@ -73,6 +73,10 @@ class CPPDeclaration self.type.func.cv == :const end + def ref + self.type.func.ref + end + def hash_str # TODO: this is a hack for making the hash values unique: @@ -83,6 +87,13 @@ class CPPDeclaration nmax = func.max_args hk = (self.is_const? ? "c" : "") + if self.ref + if self.ref == "&" + hk += "r" + elsif self.ref == "&&" + hk += "rr" + end + end if nmax > 0 @@ -111,17 +122,28 @@ class CPPDeclaration nmax = func.max_args args = nmax.times.collect { |ia| func.args[ia].anonymous_type.to_s }.join(", ") + res = "(" + args + ")" if self.is_const? - "(" + args + ") const" - else - "(" + args + ")" + res += " const" end + if self.ref + res += " " + self.ref + end + + res end def sig(cls) + self.type.name_substituted_type(CPPQualifiedId::new(false, [ cls, self.type.func.func_name ])).to_s + end + + def raw_sig(cls) # backward compatibility for signature computation s = self.type.name_substituted_type(CPPQualifiedId::new(false, [ cls, self.type.func.func_name ])).to_s + if self.ref + s = s.sub(/\s+&+$/, "") + end if self.is_const? s = s.sub(/\s+const$/, "") end @@ -739,7 +761,13 @@ class CPPType return "#{self.anonymous_type.to_s}(" + expr + ")" elsif self.is_special(decl_obj) ta = self.anonymous_type.to_s - if ta =~ /^const (.*) &$/ + if ta =~ /^const (.*) &&$/ + ta = $1 + acc = ".cmove()" + elsif ta =~ /^(.*) &&$/ + ta = $1 + acc = ".move()" + elsif ta =~ /^const (.*) &$/ ta = $1 acc = ".cref()" elsif ta =~ /^(.*) &$/ @@ -776,6 +804,8 @@ class CPPType # but can at least read them. if ta =~ /^const (.*) &$/ || ta =~ /^(.*) &$/ ta = $1 + elsif ta =~ /^const (.*) &&$/ || ta =~ /^(.*) &&$/ + ta = $1 elsif ta =~ /^const (.*) \*$/ || ta =~ /^(.*) \*$/ ta = $1 acc = "*" @@ -1140,6 +1170,7 @@ class Configurator # static and non-static methods if bd.storage_class == :static sig = "static " + sig + sig2 = "static " + sig2 end if is_dropped?(cls, sig) || is_dropped?(cls2, sig2) @@ -1832,7 +1863,7 @@ END # create a default ctor if there is no ctor at all and we can have one if ctors.empty? && conf.has_default_ctor?(cls) - func = CPPFunc::new(CPPQualifiedId::new(false, [ CPPId::new(decl_obj.myself, nil) ]), [], nil) + func = CPPFunc::new(CPPQualifiedId::new(false, [ CPPId::new(decl_obj.myself, nil) ]), [], nil, nil) type = CPPType::new(nil, func, nil) def_ctor = CPPDeclaration::new(type, nil, :public, nil, false, false) def_ctor.parent = decl_obj @@ -1905,6 +1936,7 @@ END func = bd.type.func hk = bd.hash_str sig = bd.sig(cls) + rsig = bd.raw_sig(cls) mn = decl_obj.myself # ctor! mn_name = conf.target_name(cls, bd, mn) @@ -1923,7 +1955,7 @@ END qt_alist = n_args.times.collect { |ia| func.args[ia].renamed_type(alist[ia]).access_qt_arg(decl_obj) } ofile.puts("") - ofile.puts("// Constructor #{sig}") + ofile.puts("// Constructor #{rsig}") ofile.puts("") ofile.puts("") @@ -1951,7 +1983,7 @@ END ofile.puts("}") ofile.puts("") - mdecl_ctors << "new qt_gsi::GenericStaticMethod (\"#{mn_name}\", \"@brief Constructor #{sig}\\nThis method creates an object of class #{cls}.\", &_init_ctor_#{clsn}_#{hk}, &_call_ctor_#{clsn}_#{hk});" + mdecl_ctors << "new qt_gsi::GenericStaticMethod (\"#{mn_name}\", \"@brief Constructor #{rsig}\\nThis method creates an object of class #{cls}.\", &_init_ctor_#{clsn}_#{hk}, &_call_ctor_#{clsn}_#{hk});" end @@ -1978,6 +2010,7 @@ END const = bd.is_const? hk = bd.hash_str sig = bd.sig(cls) + rsig = bd.raw_sig(cls) if conf.event_args(cls, sig) && bd.type.return_type.is_void? # don't produce bindings for signals (which are public in Qt5) @@ -2005,7 +2038,7 @@ END qt_alist = n_args.times.collect { |ia| func.args[ia].renamed_type(alist[ia]).access_qt_arg(decl_obj) } ofile.puts("") - ofile.puts("// #{sig}") + ofile.puts("// #{rsig}") ofile.puts("") ofile.puts("") @@ -2030,7 +2063,7 @@ END ofile.puts("}") ofile.puts("") - mdecl << "new qt_gsi::GenericMethod (\"#{mn_name}\", \"@brief Method #{sig}\\n" + (is_reimp ? "This is a reimplementation of #{is_reimp.parent.myself}::#{mid}" : "") + "\", #{const.to_s}, &_init_f_#{mn}_#{hk}, &_call_f_#{mn}_#{hk});" + mdecl << "new qt_gsi::GenericMethod (\"#{mn_name}\", \"@brief Method #{rsig}\\n" + (is_reimp ? "This is a reimplementation of #{is_reimp.parent.myself}::#{mid}" : "") + "\", #{const.to_s}, &_init_f_#{mn}_#{hk}, &_call_f_#{mn}_#{hk});" end @@ -2065,6 +2098,7 @@ END end sig = bd_short.sig(cls) + rsig = bd_short.raw_sig(cls) hk = bd_short.hash_str n_args = func.max_args @@ -2078,7 +2112,7 @@ END al = ant.collect { |a| a.to_s }.join(", ") aln = ren_args.collect { |a| a.to_s }.join(", ") - sig_wo_void = sig.sub(/^void /, "") + rsig_wo_void = rsig.sub(/^void /, "") al_subst = al SignalSubstitutions.each do |t,s| @@ -2087,9 +2121,9 @@ END argspecs = argnames.collect { |a| "gsi::arg(\"#{a}\"), " }.join("") if gsi_args.empty? - mdecl << "gsi::qt_signal (\"#{mid}(#{al_subst})\", \"#{mn_name}\", \"@brief Signal declaration for #{sig_wo_void}\\nYou can bind a procedure to this signal.\");" + mdecl << "gsi::qt_signal (\"#{mid}(#{al_subst})\", \"#{mn_name}\", \"@brief Signal declaration for #{rsig_wo_void}\\nYou can bind a procedure to this signal.\");" else - mdecl << "gsi::qt_signal<#{event_al} > (\"#{mid}(#{al_subst})\", \"#{mn_name}\", #{argspecs}\"@brief Signal declaration for #{sig_wo_void}\\nYou can bind a procedure to this signal.\");" + mdecl << "gsi::qt_signal<#{event_al} > (\"#{mid}(#{al_subst})\", \"#{mn_name}\", #{argspecs}\"@brief Signal declaration for #{rsig_wo_void}\\nYou can bind a procedure to this signal.\");" end end @@ -2114,6 +2148,7 @@ END const = bd.is_const? hk = bd.hash_str sig = bd.sig(cls) + rsig = bd.raw_sig(cls) mn = conf.mid2str(mid) mn_name = conf.target_name(cls, bd, mid, all_methods_by_name, bd) @@ -2132,7 +2167,7 @@ END qt_alist = n_args.times.collect { |ia| func.args[ia].renamed_type(alist[ia]).access_qt_arg(decl_obj) } ofile.puts("") - ofile.puts("// static #{sig}") + ofile.puts("// static #{rsig}") ofile.puts("") ofile.puts("") @@ -2156,7 +2191,7 @@ END ofile.puts("}") ofile.puts("") - mdecl << "new qt_gsi::GenericStaticMethod (\"#{mn_name}\", \"@brief Static method #{sig}\\nThis method is static and can be called without an instance.\", &_init_f_#{mn}_#{hk}, &_call_f_#{mn}_#{hk});" + mdecl << "new qt_gsi::GenericStaticMethod (\"#{mn_name}\", \"@brief Static method #{rsig}\\nThis method is static and can be called without an instance.\", &_init_f_#{mn}_#{hk}, &_call_f_#{mn}_#{hk});" end @@ -2173,6 +2208,7 @@ END const = bd.is_const? hk = bd.hash_str sig = bd.sig("") + rsig = bd.raw_sig("") # operators may be present twice with the same signature # (here: same hash key) @@ -2206,7 +2242,7 @@ END args = rnt.collect { |t| t.gsi_decl_arg(decl_obj) }.join(", ") ofile.puts("") - ofile.puts("// #{sig}") + ofile.puts("// #{rsig}") ofile.puts("static #{rt.gsi_decl_return(decl_obj)} op_#{clsn}_#{mn}_#{hk}(#{args}) {") if !rt.is_void? @@ -2219,7 +2255,7 @@ END argspecs = argnames[1..-1].collect { |a| "gsi::arg (\"#{a}\"), " }.join("") - mdecl << "gsi::method_ext(\"#{mn_name}\", &::op_#{clsn}_#{mn}_#{hk}, #{argspecs}\"@brief Operator #{sig}\\nThis is the mapping of the global operator to the instance method.\");" + mdecl << "gsi::method_ext(\"#{mn_name}\", &::op_#{clsn}_#{mn}_#{hk}, #{argspecs}\"@brief Operator #{rsig}\\nThis is the mapping of the global operator to the instance method.\");" end @@ -2383,6 +2419,7 @@ END func = bd.type.func hk = bd.hash_str sig = bd.sig(cls) + rsig = bd.raw_sig(cls) mn = decl_obj.myself # ctor! mn_name = conf.target_name(cls, bd, mn) @@ -2406,7 +2443,7 @@ END args = rnt.collect { |t| t.to_s }.join(", ") ofile.puts("") - ofile.puts(" // [adaptor ctor] #{sig}") + ofile.puts(" // [adaptor ctor] #{rsig}") ofile.puts(" #{clsn}_Adaptor(#{args}) : #{cls}(#{argnames.join(', ')})") ofile.puts(" {") ofile.puts(" qt_gsi::QtObjectBase::init (this);") @@ -2430,6 +2467,7 @@ END func = bd.type.func hk = bd.hash_str sig = bd.sig(cls) + rsig = bd.raw_sig(cls) const = bd.is_const? # exclude events @@ -2453,7 +2491,7 @@ END argexpr = rnt.collect { |t| t.access_qt_arg(decl_obj) }.join(", ") ofile.puts("") - ofile.puts(" // [expose] #{sig}") + ofile.puts(" // [expose] #{rsig}") ofile.puts(" " + (bd.storage_class == :static ? "static " : "") + "#{rt.gsi_decl_return(decl_obj)} fp_#{clsn}_#{mn}_#{hk} (#{args}) " + (const ? "const " : "") + "{") if rt.is_void? ofile.puts(" #{cls}::#{mid}(#{argexpr});") @@ -2481,6 +2519,7 @@ END func = bd.type.func hk = bd.hash_str sig = bd.sig(cls) + rsig = bd.raw_sig(cls) const = bd.is_const? rt = bd.type.return_type @@ -2504,6 +2543,7 @@ END end sig = bd_short.sig(cls) + rsig = bd_short.raw_sig(cls) # for events produce an emitter function @@ -2517,7 +2557,7 @@ END call_args = argnames.join(", ") ofile.puts("") - ofile.puts(" // [emitter impl] #{sig}") + ofile.puts(" // [emitter impl] #{rsig}") ofile.puts(" #{rt.to_s} emitter_#{clsn}_#{mn}_#{hk}(#{raw_args})") ofile.puts(" {") if is_private @@ -2560,7 +2600,7 @@ END call_args = argnames.join(", ") ofile.puts("") - ofile.puts(" // [adaptor impl] #{sig}") + ofile.puts(" // [adaptor impl] #{rsig}") ofile.puts(" #{rt.gsi_decl_return(decl_obj)} cbs_#{mn}_#{hk}_#{i_var}(#{args})" + (const ? " const" : "")) ofile.puts(" {") if abstract @@ -2625,6 +2665,7 @@ END func = bd.type.func hk = bd.hash_str sig = bd.sig(cls) + rsig = bd.raw_sig(cls) mn = decl_obj.myself # ctor! mn_name = conf.target_name(cls, bd, mn) @@ -2642,7 +2683,7 @@ END qt_alist = n_args.times.collect { |ia| func.args[ia].renamed_type(alist[ia]).access_qt_arg(decl_obj) } ofile.puts("") - ofile.puts("// Constructor #{sig} (adaptor class)") + ofile.puts("// Constructor #{rsig} (adaptor class)") ofile.puts("") ofile.puts("static void _init_ctor_#{clsn}_Adaptor_#{hk} (qt_gsi::GenericStaticMethod *decl)") ofile.puts("{") @@ -2664,7 +2705,7 @@ END ofile.puts("}") ofile.puts("") - mdecl << "new qt_gsi::GenericStaticMethod (\"#{mn_name}\", \"@brief Constructor #{sig}\\nThis method creates an object of class #{cls}.\", &_init_ctor_#{clsn}_Adaptor_#{hk}, &_call_ctor_#{clsn}_Adaptor_#{hk});" + mdecl << "new qt_gsi::GenericStaticMethod (\"#{mn_name}\", \"@brief Constructor #{rsig}\\nThis method creates an object of class #{cls}.\", &_init_ctor_#{clsn}_Adaptor_#{hk}, &_call_ctor_#{clsn}_Adaptor_#{hk});" end @@ -2677,6 +2718,7 @@ END func = bd.type.func hk = bd.hash_str sig = bd.sig(cls) + rsig = bd.raw_sig(cls) const = bd.is_const? rt = bd.type.return_type @@ -2698,6 +2740,7 @@ END end sig = bd_short.sig(cls) + rsig = bd_short.raw_sig(cls) n_args = func.max_args n_min_args = func.min_args @@ -2707,7 +2750,7 @@ END ifc_obj = "GenericMethod" ofile.puts("") - ofile.puts("// emitter #{sig}") + ofile.puts("// emitter #{rsig}") ofile.puts("") ofile.puts("static void _init_emitter_#{mn}_#{hk} (qt_gsi::#{ifc_obj} *decl)") ofile.puts("{") @@ -2728,7 +2771,7 @@ END if bd_short.storage_class != :static const_flag = ", " + const.to_s end - mdecl << "new qt_gsi::#{ifc_obj} (\"emit_#{mn_name}\", \"@brief Emitter for signal #{sig}\\nCall this method to emit this signal.\"#{const_flag}, &_init_emitter_#{mn}_#{hk}, &_call_emitter_#{mn}_#{hk});" + mdecl << "new qt_gsi::#{ifc_obj} (\"emit_#{mn_name}\", \"@brief Emitter for signal #{rsig}\\nCall this method to emit this signal.\"#{const_flag}, &_init_emitter_#{mn}_#{hk}, &_call_emitter_#{mn}_#{hk});" elsif !bd.virtual && bd.visibility == :protected @@ -2742,7 +2785,7 @@ END ifc_obj = bd.storage_class == :static ? "GenericStaticMethod" : "GenericMethod" ofile.puts("") - ofile.puts("// exposed #{sig}") + ofile.puts("// exposed #{rsig}") ofile.puts("") ofile.puts("static void _init_fp_#{mn}_#{hk} (qt_gsi::#{ifc_obj} *decl)") ofile.puts("{") @@ -2781,7 +2824,7 @@ END if bd.storage_class != :static const_flag = ", " + const.to_s end - mdecl << "new qt_gsi::#{ifc_obj} (\"*#{mn_name}\", \"@brief Method #{sig}\\nThis method is protected and can only be called from inside a derived class.\"#{const_flag}, &_init_fp_#{mn}_#{hk}, &_call_fp_#{mn}_#{hk});" + mdecl << "new qt_gsi::#{ifc_obj} (\"*#{mn_name}\", \"@brief Method #{rsig}\\nThis method is protected and can only be called from inside a derived class.\"#{const_flag}, &_init_fp_#{mn}_#{hk}, &_call_fp_#{mn}_#{hk});" elsif bd.virtual @@ -2798,7 +2841,7 @@ END alist = n_args.times.collect { |ia| "arg#{ia + 1}" } ofile.puts("") - ofile.puts("// #{sig}") + ofile.puts("// #{rsig}") ofile.puts("") ofile.puts("static void _init_cbs_#{mn}_#{hk}_#{i_var} (qt_gsi::GenericMethod *decl)") ofile.puts("{") @@ -2834,7 +2877,7 @@ END ofile.puts("}") ofile.puts("") - mdecl << "new qt_gsi::GenericMethod (\"#{pp}#{mn_name}\", \"@brief Virtual method #{sig}\\nThis method can be reimplemented in a derived class.\", #{const.to_s}, &_init_cbs_#{mn}_#{hk}_#{i_var}, &_call_cbs_#{mn}_#{hk}_#{i_var});" + mdecl << "new qt_gsi::GenericMethod (\"#{pp}#{mn_name}\", \"@brief Virtual method #{rsig}\\nThis method can be reimplemented in a derived class.\", #{const.to_s}, &_init_cbs_#{mn}_#{hk}_#{i_var}, &_call_cbs_#{mn}_#{hk}_#{i_var});" mdecl << "new qt_gsi::GenericMethod (\"#{pp}#{mn_name}\", \"@hide\", #{const.to_s}, &_init_cbs_#{mn}_#{hk}_#{i_var}, &_call_cbs_#{mn}_#{hk}_#{i_var}, &_set_callback_cbs_#{mn}_#{hk}_#{i_var});" end