From 560832789945320e06881d8277709275044d9539 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 31 Aug 2020 23:44:02 +0200 Subject: [PATCH] Another cool one: void as C++ return value is translated to returning self for Ruby. --- src/db/db/dbLayoutToNetlist.cc | 4 ++-- src/db/db/dbLayoutToNetlist.h | 10 ++++----- src/db/db/gsiDeclDbLayoutToNetlist.cc | 4 ++-- src/lay/lay/doc/programming/ruby_binding.xml | 23 ++++++++++++++++++++ src/rba/rba/rba.cc | 16 ++++++++++++++ testdata/ruby/dbPolygonTest.rb | 13 +++++++++++ 6 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index 9232b78ea..15d0d5c12 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -284,7 +284,7 @@ void LayoutToNetlist::connect_impl (const db::ShapeCollection &a, const db::Shap m_conn.connect (dla.layer (), dlb.layer ()); } -void LayoutToNetlist::connect_global_impl (const db::ShapeCollection &l, const std::string &gn) +size_t LayoutToNetlist::connect_global_impl (const db::ShapeCollection &l, const std::string &gn) { if (m_netlist_extracted) { throw tl::Exception (tl::to_string (tr ("The netlist has already been extracted"))); @@ -297,7 +297,7 @@ void LayoutToNetlist::connect_global_impl (const db::ShapeCollection &l, const s db::DeepLayer dl = deep_layer_of (l); m_dlrefs.insert (dl); - m_conn.connect_global (dl.layer (), gn); + return m_conn.connect_global (dl.layer (), gn); } const std::string &LayoutToNetlist::global_net_name (size_t id) const diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index 4d103e66e..a7875863c 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -398,18 +398,18 @@ public: * @brief Connects the given layer with a global net with the given name * Returns the global net ID */ - void connect_global (const db::Region &l, const std::string &gn) + size_t connect_global (const db::Region &l, const std::string &gn) { - connect_global_impl (l, gn); + return connect_global_impl (l, gn); } /** * @brief Connects the given text layer with a global net with the given name * Returns the global net ID */ - void connect_global (const db::Texts &l, const std::string &gn) + size_t connect_global (const db::Texts &l, const std::string &gn) { - connect_global_impl (l, gn); + return connect_global_impl (l, gn); } /** @@ -872,7 +872,7 @@ private: db::properties_id_type make_netname_propid (db::Layout &ly, const tl::Variant &netname_prop, const db::Net &net) const; db::CellMapping make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector *nets, bool with_device_cells); void connect_impl (const db::ShapeCollection &a, const db::ShapeCollection &b); - void connect_global_impl (const db::ShapeCollection &l, const std::string &gn); + size_t connect_global_impl (const db::ShapeCollection &l, const std::string &gn); // implementation of NetlistManipulationCallbacks virtual size_t link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &trans); diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc index cedc464ab..1f46e9139 100644 --- a/src/db/db/gsiDeclDbLayoutToNetlist.cc +++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc @@ -357,12 +357,12 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "\n" "This variant has been introduced in version 0.27.\n" ) + - gsi::method ("connect_global", (void (db::LayoutToNetlist::*) (const db::Region &, const std::string &)) &db::LayoutToNetlist::connect_global, gsi::arg ("l"), gsi::arg ("global_net_name"), + gsi::method ("connect_global", (size_t (db::LayoutToNetlist::*) (const db::Region &, const std::string &)) &db::LayoutToNetlist::connect_global, gsi::arg ("l"), gsi::arg ("global_net_name"), "@brief Defines a connection of the given layer with a global net.\n" "This method returns the ID of the global net. Use \\global_net_name to get " "the name back from the ID." ) + - gsi::method ("connect_global", (void (db::LayoutToNetlist::*) (const db::Texts &, const std::string &)) &db::LayoutToNetlist::connect_global, gsi::arg ("l"), gsi::arg ("global_net_name"), + gsi::method ("connect_global", (size_t (db::LayoutToNetlist::*) (const db::Texts &, const std::string &)) &db::LayoutToNetlist::connect_global, gsi::arg ("l"), gsi::arg ("global_net_name"), "@brief Defines a connection of the given text layer with a global net.\n" "This method returns the ID of the global net. Use \\global_net_name to get " "the name back from the ID." diff --git a/src/lay/lay/doc/programming/ruby_binding.xml b/src/lay/lay/doc/programming/ruby_binding.xml index b79241c2a..7449de54a 100644 --- a/src/lay/lay/doc/programming/ruby_binding.xml +++ b/src/lay/lay/doc/programming/ruby_binding.xml @@ -278,6 +278,29 @@ event._manage and pointers/references and also supports "out" parameters.

+

"void" as return value

+ +

+ While a "void" return value indicates "no return value" in C++, this concept is not + common in Ruby. Ruby methods will always return the last value generated in + a method. +

+ +

+ For consistency, KLayout's Ruby binding returns "self" from methods in this + case. This allows chaining of methods in many cases and fosters compact code: +

+ +
// C++
+class A {
+public:
+  virtual void f() { ... }
+  virtual void g() { ... }
+};
+
+# Ruby
+a = A::new.f.g
+

References and pointers to simple types (FixNum, Float, String)

diff --git a/src/rba/rba/rba.cc b/src/rba/rba/rba.cc index d7e9a1091..3ee9dd964 100644 --- a/src/rba/rba/rba.cc +++ b/src/rba/rba/rba.cc @@ -887,6 +887,15 @@ method_name_from_id (int mid, VALUE self) return cls_decl->name () + "::" + mt->name (mid); } +static gsi::ArgType create_void_type () +{ + gsi::ArgType at; + at.init (); + return at; +} + +static gsi::ArgType s_void_type = create_void_type (); + VALUE method_adaptor (int mid, int argc, VALUE *argv, VALUE self, bool ctor) { @@ -1077,8 +1086,15 @@ method_adaptor (int mid, int argc, VALUE *argv, VALUE self, bool ctor) } + } else if (meth->ret_type () == s_void_type) { + + // simple, yet magical :) + return self; + } else { + ret = pop_arg (meth->ret_type (), p, retlist, heap); + } } diff --git a/testdata/ruby/dbPolygonTest.rb b/testdata/ruby/dbPolygonTest.rb index 73c592830..02602f61c 100644 --- a/testdata/ruby/dbPolygonTest.rb +++ b/testdata/ruby/dbPolygonTest.rb @@ -777,6 +777,19 @@ class DBPolygon_TestClass < TestBase end + def test_voidMethodsReturnSelf + + hull = [ RBA::Point::new(0, 0), RBA::Point::new(6000, 0), + RBA::Point::new(6000, 3000), RBA::Point::new(0, 3000) ] + hole1 = [ RBA::Point::new(1000, 1000), RBA::Point::new(2000, 1000), + RBA::Point::new(2000, 2000), RBA::Point::new(1000, 2000) ] + hole2 = [ RBA::Point::new(3000, 1000), RBA::Point::new(4000, 1000), + RBA::Point::new(4000, 2000), RBA::Point::new(3000, 2000) ] + poly = RBA::Polygon::new(hull).insert_hole(hole1).insert_hole(hole2) + assert_equal(poly.to_s, "(0,0;0,3000;6000,3000;6000,0/1000,1000;2000,1000;2000,2000;1000,2000/3000,1000;4000,1000;4000,2000;3000,2000)") + + end + end load("test_epilogue.rb")