From f335ab69af5acb3c93bf289215f1763089b16735 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 29 Dec 2023 23:00:06 +0100 Subject: [PATCH] More compatibility with Ruby <2.7 --- .../drc/built-in-macros/drc_interpreters.lym | 6 +-- src/gsi/gsi/gsiDeclTl.cc | 16 ++------ .../lvs/built-in-macros/lvs_interpreters.lym | 6 +-- .../built-in-macros/d25_interpreters.lym | 6 +-- src/rba/rba/rba.cc | 39 ++++++++++++++----- testdata/ruby/tlTest.rb | 4 +- 6 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/drc/drc/built-in-macros/drc_interpreters.lym b/src/drc/drc/built-in-macros/drc_interpreters.lym index fbcdd0091..720b7e963 100644 --- a/src/drc/drc/built-in-macros/drc_interpreters.lym +++ b/src/drc/drc/built-in-macros/drc_interpreters.lym @@ -91,7 +91,7 @@ module DRC macro = RBA::Macro::macro_by_path(script) macro || raise("Can't find DRC script #{script} - unable to re-run") - DRCExecutable::new(macro, @interpreter, self.generator({ "script" => script }, 0), params["rdb_index"]) + DRCExecutable::new(macro, @interpreter, self.generator("script" => script), params["rdb_index"]) end @@ -128,7 +128,7 @@ module DRC # Implements the execute method def executable(macro) - DRCExecutable::new(macro, self, @recipe.generator({"script" => macro.path}, 0)) + DRCExecutable::new(macro, self, @recipe.generator("script" => macro.path)) end end @@ -155,7 +155,7 @@ module DRC # Implements the execute method def executable(macro) - DRCExecutable::new(macro, self, @recipe.generator({ "script" => macro.path }, 0)) + DRCExecutable::new(macro, self, @recipe.generator("script" => macro.path)) end end diff --git a/src/gsi/gsi/gsiDeclTl.cc b/src/gsi/gsi/gsiDeclTl.cc index e170b4847..11890f591 100644 --- a/src/gsi/gsi/gsiDeclTl.cc +++ b/src/gsi/gsi/gsiDeclTl.cc @@ -693,12 +693,12 @@ static Recipe_Impl *make_recipe (const std::string &name, const std::string &des return new Recipe_Impl (name, description); } -static tl::Variant make_impl (const std::string &generator, const std::map &add_params, int /*dummy*/) +static tl::Variant make_impl (const std::string &generator, const std::map &add_params) { return Recipe_Impl::make (generator, add_params); } -std::string generator_impl (Recipe_Impl *recipe, const std::map ¶ms, int /*dummy*/) +std::string generator_impl (Recipe_Impl *recipe, const std::map ¶ms) { return recipe->generator (params); } @@ -713,23 +713,15 @@ Class decl_Recipe_Impl ("tl", "Recipe", gsi::method ("description", &Recipe_Impl::description, "@brief Gets the description of the recipe." ) + - gsi::method ("make", &make_impl, gsi::arg ("generator"), gsi::arg ("add_params", std::map (), "{}"), gsi::arg ("dummy", 0), + gsi::method ("make", &make_impl, gsi::arg ("generator"), gsi::arg ("add_params", std::map (), "{}"), "@brief Executes the recipe given by the generator string.\n" "The generator string is the one delivered with \\generator.\n" "Additional parameters can be passed in \"add_params\". They have lower priority than the parameters " "kept inside the generator string." - "\n" - "The dummy argument has been added in version 0.29 and disambiguates between keyword parameters " - "and a single hash argument in Ruby. This is required for Ruby versions before 'real keywords'. Simply " - "add this parameter with any value.\n" ) + - gsi::method_ext ("generator", &generator_impl, gsi::arg ("params"), gsi::arg ("dummy", 0), + gsi::method_ext ("generator", &generator_impl, gsi::arg ("params"), "@brief Delivers the generator string from the given parameters.\n" "The generator string can be used with \\make to re-run the recipe." - "\n" - "The dummy argument has been added in version 0.29 and disambiguates between keyword parameters " - "and a single hash argument in Ruby. This is required for Ruby versions before 'real keywords'. Simply " - "add this parameter with any value.\n" ) + gsi::callback ("executable", &Recipe_Impl::executable, &Recipe_Impl::executable_cb, gsi::arg ("params"), "@brief Reimplement this method to provide an executable object for the actual implementation.\n" diff --git a/src/lvs/lvs/built-in-macros/lvs_interpreters.lym b/src/lvs/lvs/built-in-macros/lvs_interpreters.lym index 73ff49907..2aaf6f1fa 100644 --- a/src/lvs/lvs/built-in-macros/lvs_interpreters.lym +++ b/src/lvs/lvs/built-in-macros/lvs_interpreters.lym @@ -91,7 +91,7 @@ module LVS macro = RBA::Macro::macro_by_path(script) macro || raise("Can't find LVS script #{script} - unable to re-run") - LVSExecutable::new(macro, @interpreter, self.generator({ "script" => script }, 0), params["l2ndb_index"]) + LVSExecutable::new(macro, @interpreter, self.generator("script" => script), params["l2ndb_index"]) end @@ -128,7 +128,7 @@ module LVS # Implements the execute method def executable(macro) - LVSExecutable::new(macro, self, @recipe.generator({ "script" => macro.path }, 0)) + LVSExecutable::new(macro, self, @recipe.generator("script" => macro.path)) end end @@ -155,7 +155,7 @@ module LVS # Implements the execute method def executable(macro) - LVSExecutable::new(macro, self, @recipe.generator({ "script" => macro.path }, 0)) + LVSExecutable::new(macro, self, @recipe.generator("script" => macro.path)) end end diff --git a/src/plugins/tools/view_25d/lay_plugin/built-in-macros/d25_interpreters.lym b/src/plugins/tools/view_25d/lay_plugin/built-in-macros/d25_interpreters.lym index 5d0e4ff61..fd8e1bca5 100644 --- a/src/plugins/tools/view_25d/lay_plugin/built-in-macros/d25_interpreters.lym +++ b/src/plugins/tools/view_25d/lay_plugin/built-in-macros/d25_interpreters.lym @@ -92,7 +92,7 @@ module D25 macro = RBA::Macro::macro_by_path(script) macro || raise("Can't find D25 script #{script} - unable to re-run") - D25Executable::new(macro, @interpreter, self.generator({ "script" => script }, 0)) + D25Executable::new(macro, @interpreter, self.generator("script" => script)) end @@ -129,7 +129,7 @@ module D25 # Implements the execute method def executable(macro) - D25Executable::new(macro, self, @recipe.generator({ "script" => macro.path }, 0)) + D25Executable::new(macro, self, @recipe.generator("script" => macro.path)) end end @@ -156,7 +156,7 @@ module D25 # Implements the execute method def executable(macro) - D25Executable::new(macro, self, @recipe.generator({ "script" => macro.path }, 0)) + D25Executable::new(macro, self, @recipe.generator("script" => macro.path)) end end diff --git a/src/rba/rba/rba.cc b/src/rba/rba/rba.cc index c453bfc65..ecb2675d4 100644 --- a/src/rba/rba/rba.cc +++ b/src/rba/rba/rba.cc @@ -1147,15 +1147,6 @@ method_adaptor (int mid, int argc, VALUE *argv, VALUE self, bool ctor) RBA_TRY - VALUE kwargs = Qnil; - bool check_last = true; -#if HAVE_RUBY_VERSION_CODE>=20700 - check_last = rb_keyword_given_p (); -#endif - if (check_last && argc > 0 && RB_TYPE_P (argv[argc - 1], T_HASH)) { - kwargs = argv[--argc]; - } - tl::Heap heap; const gsi::ClassBase *cls_decl; @@ -1187,6 +1178,36 @@ method_adaptor (int mid, int argc, VALUE *argv, VALUE self, bool ctor) } + // Check for keyword arguments .. + + VALUE kwargs = Qnil; + bool check_last = true; +#if HAVE_RUBY_VERSION_CODE>=20700 + check_last = rb_keyword_given_p (); +#endif + + // This is a heuristics to distinguish methods that are potential candidates for + // accepting a keyword argument. Problem is that Ruby confuses function calls with + // keyword arguments with arguments that take a single hash argument. + // We accept only methods here as candidates that do not have a last argument which + // is a map. + // For compatibility we do this check also for Ruby >=2.7 which supports rb_keyword_given_p. + if (check_last) { + const MethodTableEntry &e = mt->entry (mid); + for (auto m = e.begin (); m != e.end () && check_last; ++m) { + auto a = (*m)->end_arguments (); + if (a != (*m)->begin_arguments () && (--a)->type () == gsi::T_map) { + check_last = false; + } + } + } + + if (check_last && argc > 0 && RB_TYPE_P (argv[argc - 1], T_HASH)) { + kwargs = argv[--argc]; + } + + // Identify the matching variant + const gsi::MethodBase *meth = mt->entry (mid).get_variant (argc, argv, kwargs, rb_block_given_p (), ctor, p == 0, p != 0 && p->const_ref ()); if (! meth) { diff --git a/testdata/ruby/tlTest.rb b/testdata/ruby/tlTest.rb index a77b8ae75..8980b2ec5 100644 --- a/testdata/ruby/tlTest.rb +++ b/testdata/ruby/tlTest.rb @@ -301,10 +301,10 @@ class Tl_TestClass < TestBase assert_equal(my_recipe.name, "rba_test_recipe") assert_equal(my_recipe.description, "description") - g = my_recipe.generator({ "A" => 6, "B" => 7.0 }, 0) + g = my_recipe.generator("A" => 6, "B" => 7.0) assert_equal(g, "rba_test_recipe: A=#6,B=##7") assert_equal("%g" % RBA::Recipe::make(g), "42") - assert_equal("%g" % RBA::Recipe::make(g, { "C" => 1.5 }, 0).to_s, "63") + assert_equal("%g" % RBA::Recipe::make(g, "C" => 1.5).to_s, "63") my_recipe._destroy my_recipe = nil