/* KLayout Layout Viewer Copyright (C) 2006-2022 Matthias Koefferlein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "tlExpression.h" #include "tlVariantUserClasses.h" #include "tlUnitTest.h" #include "tlEnv.h" #define _USE_MATH_DEFINES // for MSVC #include // basics TEST(1) { tl::Eval e; tl::Variant v; v = e.parse ("1").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("1+2").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("1.2e3").execute (); EXPECT_EQ (v.to_string (), std::string ("1200")); v = e.parse ("-0.25e-2").execute (); EXPECT_EQ (v.to_string (), std::string ("-0.0025")); v = e.parse ("0xffff").execute (); EXPECT_EQ (v.to_string (), std::string ("65535")); v = e.parse ("0x1001").execute (); EXPECT_EQ (v.to_string (), std::string ("4097")); v = e.parse ("0x1").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("1-2+3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("1-4*2+3").execute (); EXPECT_EQ (v.to_string (), std::string ("-4")); v = e.parse ("(1-4)*2+3").execute (); EXPECT_EQ (v.to_string (), std::string ("-3")); v = e.parse ("(4-1)*2%4").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("7%4").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("2+3/2").execute (); EXPECT_EQ (v.to_string (), std::string ("3.5")); v = e.parse ("to_i(1)*to_i(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_i(1)*to_ui(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_i(1)*to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_i(1)*to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_i(1)*to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_i(1)*2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("2.4")); v = e.parse ("to_i(1)*'2'").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_ui(1)*to_i(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_ui(1)*to_ui(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_ui(1)*to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_ui(1)*to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_ui(1)*to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_ui(1)*2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("2.4")); v = e.parse ("to_ui(1)*'2'").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_l(1)*to_i(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_l(1)*to_ui(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_l(1)*to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_l(1)*to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_l(1)*to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_l(1)*2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("2.4")); v = e.parse ("to_l(1)*'2'").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_ul(1)*to_i(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_ul(1)*to_ui(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_ul(1)*to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_ul(1)*to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_ul(1)*to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("to_ul(1)*2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("2.4")); v = e.parse ("to_ul(1)*'2'").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("1.4*to_i(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2.8")); v = e.parse ("1.4*to_ui(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2.8")); v = e.parse ("1.4*to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2.8")); v = e.parse ("1.4*to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2.8")); v = e.parse ("1.4*to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("2.8")); v = e.parse ("1.2*2.0").execute (); EXPECT_EQ (v.to_string (), std::string ("2.4")); v = e.parse ("'1'*2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("11")); v = e.parse ("'3'*'2'").execute (); EXPECT_EQ (v.to_string (), std::string ("33")); v = e.parse ("to_i(1)+to_i(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_i(1)+to_ui(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_i(1)+to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_i(1)+to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_i(1)+to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_i(1)+2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("3.4")); v = e.parse ("to_i(1)+'2'").execute (); EXPECT_EQ (v.to_string (), std::string ("12")); v = e.parse ("to_ui(1)+to_i(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_ui(1)+to_ui(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_ui(1)+to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_ui(1)+to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_ui(1)+to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_ui(1)+2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("3.4")); v = e.parse ("to_ui(1)+'2'").execute (); EXPECT_EQ (v.to_string (), std::string ("12")); v = e.parse ("to_l(1)+to_i(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_l(1)+to_ui(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_l(1)+to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_l(1)+to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_l(1)+to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_l(1)+2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("3.4")); v = e.parse ("to_l(1)+'2'").execute (); EXPECT_EQ (v.to_string (), std::string ("12")); v = e.parse ("to_ul(1)+to_i(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_ul(1)+to_ui(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_ul(1)+to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_ul(1)+to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_ul(1)+to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("to_ul(1)+2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("3.4")); v = e.parse ("to_ul(1)+'2'").execute (); EXPECT_EQ (v.to_string (), std::string ("12")); v = e.parse ("1.4+to_i(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3.4")); v = e.parse ("1.4+to_ui(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3.4")); v = e.parse ("1.4+to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3.4")); v = e.parse ("1.4+to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3.4")); v = e.parse ("1.4+to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("3.4")); v = e.parse ("1.4+2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("3.8")); v = e.parse ("'1'+2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("12.4")); v = e.parse ("'3'+'2'").execute (); EXPECT_EQ (v.to_string (), std::string ("32")); v = e.parse ("to_i(1)-to_i(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("-1")); v = e.parse ("to_i(1)-to_ui(2)").execute (); if (sizeof(long) == 8) { EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); } else { EXPECT_EQ (v.to_string (), std::string ("4294967295")); } v = e.parse ("to_i(1)-to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("-1")); v = e.parse ("to_i(1)-to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); v = e.parse ("to_i(1)-to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); v = e.parse ("to_i(1)-2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("-1.4")); v = e.parse ("to_i(1)-'2'").execute (); EXPECT_EQ (v.to_string (), std::string ("-1")); v = e.parse ("to_ui(1)-to_i(2)").execute (); if (sizeof(long) == 8) { EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); } else { EXPECT_EQ (v.to_string (), std::string ("4294967295")); } v = e.parse ("to_ui(1)-to_ui(2)").execute (); if (sizeof(long) == 8) { EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); } else { EXPECT_EQ (v.to_string (), std::string ("4294967295")); } v = e.parse ("to_ui(1)-to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("-1")); v = e.parse ("to_ui(1)-to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); v = e.parse ("to_ui(1)-to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); v = e.parse ("to_ui(1)-2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("-1.4")); v = e.parse ("to_ui(1)-'2'").execute (); if (sizeof(long) == 8) { EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); } else { EXPECT_EQ (v.to_string (), std::string ("4294967295")); } v = e.parse ("to_l(1)-to_i(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("-1")); v = e.parse ("to_l(1)-to_ui(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("-1")); v = e.parse ("to_l(1)-to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("-1")); v = e.parse ("to_l(1)-to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); v = e.parse ("to_l(1)-to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); v = e.parse ("to_l(1)-2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("-1.4")); v = e.parse ("to_l(1)-'2'").execute (); EXPECT_EQ (v.to_string (), std::string ("-1")); v = e.parse ("to_ul(1)-to_i(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); v = e.parse ("to_ul(1)-to_ui(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); v = e.parse ("to_ul(1)-to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); v = e.parse ("to_ul(1)-to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); v = e.parse ("to_ul(1)-to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); v = e.parse ("to_ul(1)-2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("-1.4")); v = e.parse ("to_ul(1)-'2'").execute (); EXPECT_EQ (v.to_string (), std::string ("18446744073709551615")); v = e.parse ("1.4-to_i(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("-0.6")); v = e.parse ("1.4-to_ui(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("-0.6")); v = e.parse ("1.4-to_l(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("-0.6")); v = e.parse ("1.4-to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("-0.6")); v = e.parse ("1.4-to_ul(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("-0.6")); v = e.parse ("1.4-2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("-1")); v = e.parse ("'1'-2.4").execute (); EXPECT_EQ (v.to_string (), std::string ("-1.4")); v = e.parse ("'3'-'2'").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("[1,2,3]").execute (); EXPECT_EQ (v.to_string (), std::string ("1,2,3")); v = e.parse ("1?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("false?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("nil?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("true?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("'a'+'x'").execute (); EXPECT_EQ (v.to_string (), std::string ("ax")); v = e.parse ("'a'*4").execute (); EXPECT_EQ (v.to_string (), std::string ("aaaa")); } class Point { public: Point () : m_x (0), m_y (0) { } Point (int x, int y) : m_x (x), m_y (y) { } int x () const { return m_x; } int y () const { return m_y; } std::string to_string () const { return tl::db_to_string (m_x) + "," + tl::db_to_string (m_y); } private: int m_x, m_y; }; class Box { public: Box (int x1, int y1, int x2, int y2) : m_p1 (x1 < x2 ? x1 : x2, y1 < y2 ? y1 : y2), m_p2 (x2 > x1 ? x2 : x1, y2 > y1 ? y2 : y1) { // .. nothing else .. } Box () : m_p1 (1, 1), m_p2 (-1, -1) { // .. nothing else .. } inline Box &operator&= (const Box &b) { if (b.empty ()) { *this = Box (); } else if (! empty ()) { Point p1 (m_p1.x () > b.m_p1.x () ? m_p1.x () : b.m_p1.x (), m_p1.y () > b.m_p1.y () ? m_p1.y () : b.m_p1.y ()); Point p2 (m_p2.x () < b.m_p2.x () ? m_p2.x () : b.m_p2.x (), m_p2.y () < b.m_p2.y () ? m_p2.y () : b.m_p2.y ()); m_p1 = p1; m_p2 = p2; } return *this; } Box operator& (const Box &b) const { Box r (*this); r &= b; return r; } int width () const { return m_p2.x () - m_p1.x (); } int height () const { return m_p2.y () - m_p1.y (); } bool empty () const { return m_p1.x () > m_p2.x (); } std::string to_string () const { if (empty ()) { return "()"; } else { return "(" + m_p1.to_string () + ";" + m_p2.to_string () + ")"; } } private: Point m_p1, m_p2; }; class Edge { public: Edge () : m_p1 (0, 0), m_p2 (0, 0) { // .. nothing else .. } Edge (int x1, int y1, int x2, int y2) : m_p1 (x1, y1), m_p2 (x2, y2) { // .. nothing else .. } Edge operator* (double s) const { return Edge (int (floor (m_p1.x () * s + 0.5)), int (floor (m_p1.y () * s + 0.5)), int (floor (m_p2.x () * s + 0.5)), int (floor (m_p2.y () * s + 0.5))); } int dx () const { return m_p2.x () - m_p1.x (); } int dy () const { return m_p2.y () - m_p1.y (); } std::string to_string () const { return "(" + m_p1.to_string () + ";" + m_p2.to_string () + ")"; } private: Point m_p1, m_p2; }; class BoxClassClass : public tl::VariantUserClassBase, private tl::EvalClass { public: virtual void execute (const tl::ExpressionParserContext &context, tl::Variant &out, tl::Variant &object, const std::string &method, const std::vector &args) const; virtual void *create () const { tl_assert (false); } virtual void destroy (void *) const { tl_assert (false); } virtual bool equal (const void *, const void *) const { tl_assert (false); } virtual bool less (const void *, const void *) const { tl_assert (false); } virtual void *clone (const void *) const { tl_assert (false); } virtual void assign (void *, const void *) const { tl_assert (false); } virtual std::string to_string (const void *) const { tl_assert (false); } virtual int to_int (const void *) const { tl_assert (false); } virtual double to_double (const void *) const { tl_assert (false); } virtual void to_variant (const void *, tl::Variant &) const { tl_assert (false); } virtual void read (void *, tl::Extractor &) const { } virtual const char *name () const { return "Box"; } virtual unsigned int type_code () const { return 0; } virtual const tl::EvalClass *eval_cls () const { return this; } virtual bool is_const () const { return false; } virtual bool is_ref () const { return false; } virtual void *deref_proxy (tl::Object *) const { return 0; } virtual const gsi::ClassBase*gsi_cls() const { return 0; } static BoxClassClass instance; }; BoxClassClass BoxClassClass::instance; class BoxClass : public tl::VariantUserClassImpl, private tl::EvalClass { public: virtual void execute (const tl::ExpressionParserContext &context, tl::Variant &out, tl::Variant &object, const std::string &method, const std::vector &args) const; virtual const tl::EvalClass *eval_cls () const { return this; } static BoxClass instance; }; BoxClass BoxClass::instance; void BoxClass::execute (const tl::ExpressionParserContext &context, tl::Variant &out, tl::Variant &object, const std::string &method, const std::vector &args) const { if (method == "width") { out = object.to_user ().width (); } else if (method == "height") { out = object.to_user ().height (); } else if (method == "&") { tl_assert (args.size () == 1); out = tl::Variant (new Box (object.to_user () & args[0].to_user ()), &BoxClass::instance, true); } else if (method == "to_s") { out = object.to_user ().to_string (); } else if (method == "is_box") { out = true; } else if (method == "is_edge") { out = false; } else { throw tl::NoMethodError("Box", method, context); } } void BoxClassClass::execute (const tl::ExpressionParserContext &context, tl::Variant &out, tl::Variant & /*object*/, const std::string &method, const std::vector &args) const { if (method == "new") { out = tl::Variant (new Box (args[0].to_long(), args[1].to_long(), args[2].to_long(), args[3].to_long()), &BoxClass::instance, true); } else { throw tl::NoMethodError("Box", method, context); } } class EdgeClassClass : public tl::VariantUserClassBase, private tl::EvalClass { public: virtual void execute (const tl::ExpressionParserContext &context, tl::Variant &out, tl::Variant &object, const std::string &method, const std::vector &args) const; virtual void *create () const { tl_assert (false); } virtual void destroy (void *) const { tl_assert (false); } virtual bool equal (const void *, const void *) const { tl_assert (false); } virtual bool less (const void *, const void *) const { tl_assert (false); } virtual void *clone (const void *) const { tl_assert (false); } virtual void assign (void *, const void *) const { tl_assert (false); } virtual std::string to_string (const void *) const { tl_assert (false); } virtual int to_int (const void *) const { tl_assert (false); } virtual double to_double (const void *) const { tl_assert (false); } virtual void to_variant (const void *, tl::Variant &) const { tl_assert (false); } virtual void read (void *, tl::Extractor &) const { } virtual const char *name () const { return "Edge"; } virtual unsigned int type_code () const { return 0; } virtual const tl::EvalClass *eval_cls () const { return this; } virtual bool is_const () const { return false; } virtual bool is_ref () const { return false; } virtual void *deref_proxy (tl::Object *) const { return 0; } virtual const gsi::ClassBase*gsi_cls() const { return 0; } static EdgeClassClass instance; }; EdgeClassClass EdgeClassClass::instance; class EdgeClass : public tl::VariantUserClassImpl, private tl::EvalClass { public: virtual void execute (const tl::ExpressionParserContext &context, tl::Variant &out, tl::Variant &object, const std::string &method, const std::vector &args) const { if (method == "dx") { out = object.to_user ().dx (); } else if (method == "dy") { out = object.to_user ().dy (); } else if (method == "to_s") { out = object.to_user ().to_string (); } else if (method == "is_box") { out = false; } else if (method == "is_edge") { out = true; } else if (method == "*") { out.set_user (new Edge (object.to_user () * args [0].to_double ()), object.user_cls (), true); } else { throw tl::NoMethodError("Edge", method, context); } } virtual const tl::EvalClass *eval_cls () const { return this; } static EdgeClass instance; }; EdgeClass EdgeClass::instance; void EdgeClassClass::execute (const tl::ExpressionParserContext &context, tl::Variant &out, tl::Variant & /*object*/, const std::string &method, const std::vector &args) const { if (method == "new") { out = tl::Variant (new Edge (args[0].to_long(), args[1].to_long(), args[2].to_long(), args[3].to_long()), &EdgeClass::instance, true); } else { throw tl::NoMethodError("Edge", method, context); } } // basics: custom objects TEST(1b) { tl::Eval e; tl::Variant v; e.set_var ("XBox", tl::Variant ((Box *) 0, &BoxClassClass::instance, false)); e.set_var ("XEdge", tl::Variant ((Edge *) 0, &EdgeClassClass::instance, false)); e.set_var ("b", tl::Variant (new Box (0, 10, 20, 40), &BoxClass::instance, true)); e.set_var ("e", tl::Variant (new Edge (0, 10, 20, 40), &EdgeClass::instance, true)); v = e.parse ("b.width").execute (); EXPECT_EQ (v.to_string (), std::string ("20")); v = e.parse ("b.width()").execute (); EXPECT_EQ (v.to_string (), std::string ("20")); v = e.parse ("b.height").execute (); EXPECT_EQ (v.to_string (), std::string ("30")); v = e.parse ("e.dx").execute (); EXPECT_EQ (v.to_string (), std::string ("20")); v = e.parse ("e.dy").execute (); EXPECT_EQ (v.to_string (), std::string ("30")); v = e.parse ("e.to_s").execute (); EXPECT_EQ (v.to_string (), std::string ("(0,10;20,40)")); v = e.parse ("(e*5).to_s").execute (); EXPECT_EQ (v.to_string (), std::string ("(0,50;100,200)")); v = e.parse ("(e.*(5)).to_s").execute (); EXPECT_EQ (v.to_string (), std::string ("(0,50;100,200)")); v = e.parse ("b.is_box").execute (); EXPECT_EQ (v.to_string (), std::string ("true")); v = e.parse ("b.is_edge").execute (); EXPECT_EQ (v.to_string (), std::string ("false")); v = e.parse ("XBox.new(1,2,3,4).is_box").execute (); EXPECT_EQ (v.to_string (), std::string ("true")); v = e.parse ("XBox.new(1,2,3,4).is_edge").execute (); EXPECT_EQ (v.to_string (), std::string ("false")); v = e.parse ("XBox.new(0, 0, 100, 200) & XBox.new(10, 10, 110, 210)").execute (); EXPECT_EQ (v.to_string (), std::string ("(10,10;100,200)")); v = e.parse ("XBox.new(0, 0, 100, 200) & XBox.new(1000, 1000, 1010, 1010)").execute (); EXPECT_EQ (v.to_string (), std::string ("()")); v = e.parse ("e.is_edge").execute (); EXPECT_EQ (v.to_string (), std::string ("true")); v = e.parse ("e.is_box").execute (); EXPECT_EQ (v.to_string (), std::string ("false")); v = e.parse ("XBox.new(1,2,3,4).width").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("XBox.new(1,2,3,4).width==2").execute (); EXPECT_EQ (v.to_string (), std::string ("true")); v = e.parse ("XBox.new(1,2,3,4).width==3").execute (); EXPECT_EQ (v.to_string (), std::string ("false")); } // to_bool TEST(2) { tl::Eval e; tl::Variant v; v = e.parse ("1?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("false?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("nil?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("[]?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("[1]?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("'1'?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("''?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); } // to_double TEST(3) { tl::Eval e; tl::Variant v; v = e.parse ("[1,2,3]/2").execute (); EXPECT_EQ (v.to_string (), std::string ("1.5")); } // functions TEST(5) { tl::Eval e; tl::Variant v; v = e.parse ("pow(sin(M_PI/4),2)").execute (); EXPECT_EQ (v.to_string (), std::string ("0.5")); v = e.parse ("sinh(log(2))").execute (); EXPECT_EQ (v.to_string (), std::string ("0.75")); v = e.parse ("cos(0.0)").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("cos(M_PI/3)").execute (); EXPECT_EQ (v.to_string (), std::string ("0.5")); v = e.parse ("cosh(log(2))").execute (); EXPECT_EQ (v.to_string (), std::string ("1.25")); v = e.parse ("tan(M_PI/4)").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("tanh(log(2))").execute (); EXPECT_EQ (v.to_string (), std::string ("0.6")); v = e.parse ("log(M_E)").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("exp(log(1.5))").execute (); EXPECT_EQ (v.to_string (), std::string ("1.5")); v = e.parse ("log10(0.1)").execute (); EXPECT_EQ (v.to_string (), std::string ("-1")); v = e.parse ("floor(0.5)").execute (); EXPECT_EQ (v.to_string (), std::string ("0")); v = e.parse ("floor(-0.5)").execute (); EXPECT_EQ (v.to_string (), std::string ("-1")); v = e.parse ("floor(1.5)").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("round(1.5)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("round(1.6)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("round(1.4)").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("ceil(0.5)").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("ceil(-0.5)").execute (); EXPECT_EQ (v.to_string () == std::string ("-0") || v.to_string () == std::string ("0"), true); v = e.parse ("ceil(1.5)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("sqrt(4)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("abs('-2')").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("abs(-1234567)").execute (); EXPECT_EQ (v.to_string (), std::string ("1234567")); v = e.parse ("abs(-0.2)").execute (); EXPECT_EQ (v.to_string (), std::string ("0.2")); v = e.parse ("acos(0)/M_PI").execute (); EXPECT_EQ (v.to_string (), std::string ("0.5")); // v = e.parse ("acosh(cosh(1.0))").execute (); // EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("asin(1)/M_PI").execute (); EXPECT_EQ (v.to_string (), std::string ("0.5")); // v = e.parse ("asinh(sinh(1.0))").execute (); // EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("atan(1)/M_PI").execute (); EXPECT_EQ (v.to_string (), std::string ("0.25")); // v = e.parse ("atanh(tanh(1))").execute (); // EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("min(1,6)").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("min(2,0,5)").execute (); EXPECT_EQ (v.to_string (), std::string ("0")); v = e.parse ("max(1,6)").execute (); EXPECT_EQ (v.to_string (), std::string ("6")); v = e.parse ("max(2,0,5)").execute (); EXPECT_EQ (v.to_string (), std::string ("5")); v = e.parse ("atan2(2,2)/M_PI").execute (); EXPECT_EQ (v.to_string (), std::string ("0.25")); v = e.parse ("to_i(6)/to_i(4)").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("to_i('6')/to_i('4')").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("to_f('6')/to_f('4')").execute (); EXPECT_EQ (v.to_string (), std::string ("1.5")); v = e.parse ("is_string('6')?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("is_string(6)?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("is_numeric('6')?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("is_numeric('a')?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("is_numeric(6)?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("is_array('6')?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("is_array(6)?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("is_array([])?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("is_nil([])?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("is_nil(nil)?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); } // string functions TEST(6) { tl::Eval e; tl::Variant v; v = e.parse ("gsub('bcabc','b','xx')").execute (); EXPECT_EQ (v.to_string (), std::string ("xxcaxxc")); v = e.parse ("gsub('abcabc','b','xx')").execute (); EXPECT_EQ (v.to_string (), std::string ("axxcaxxc")); v = e.parse ("sub('abcabc','b','xx')").execute (); EXPECT_EQ (v.to_string (), std::string ("axxcabc")); v = e.parse ("sub('bcabc','b','xx')").execute (); EXPECT_EQ (v.to_string (), std::string ("xxcabc")); v = e.parse ("find('abcabc','b')").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("rfind('abcabc','b')").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("find('abcabc','x')").execute (); EXPECT_EQ (v.to_string (), std::string ("nil")); v = e.parse ("rfind('abcabc','c')").execute (); EXPECT_EQ (v.to_string (), std::string ("0")); v = e.parse ("rfind('abcabc','x')").execute (); EXPECT_EQ (v.to_string (), std::string ("nil")); v = e.parse ("len('abcabc')").execute (); EXPECT_EQ (v.to_string (), std::string ("6")); v = e.parse ("len([])").execute (); EXPECT_EQ (v.to_string (), std::string ("0")); v = e.parse ("len([1,2,3])").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("substr('abcabc',2)").execute (); EXPECT_EQ (v.to_string (), std::string ("cabc")); v = e.parse ("substr('abcabc',2,1)").execute (); EXPECT_EQ (v.to_string (), std::string ("c")); v = e.parse ("substr('abcabc',8,1)").execute (); EXPECT_EQ (v.to_string (), std::string ("")); v = e.parse ("substr('abcabc',3,-1)").execute (); EXPECT_EQ (v.to_string (), std::string ("")); v = e.parse ("substr('abcabc',3,8)").execute (); EXPECT_EQ (v.to_string (), std::string ("abc")); v = e.parse ("substr('abcabc',6,8)").execute (); EXPECT_EQ (v.to_string (), std::string ("")); v = e.parse ("substr('abcabc',7,8)").execute (); EXPECT_EQ (v.to_string (), std::string ("")); v = e.parse ("join([],':')").execute (); EXPECT_EQ (v.to_string (), std::string ("")); v = e.parse ("item([1,2],-1)").execute (); EXPECT_EQ (v.to_string (), std::string ("nil")); v = e.parse ("item([1,2],0)").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("item([1,2],1)").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("item([1,2],2)").execute (); EXPECT_EQ (v.to_string (), std::string ("nil")); v = e.parse ("split('',':')").execute (); EXPECT_EQ (v.to_string (), std::string ("")); v = e.parse ("split('1:2',':')").execute (); EXPECT_EQ (v.to_string (), std::string ("1,2")); v = e.parse ("env('HJASK')").execute (); EXPECT_EQ (v.to_string (), std::string ("nil")); v = e.parse ("env('PATH')").execute (); EXPECT_EQ (v.to_string (), tl::get_env ("PATH")); v = e.parse ("absolute_path('./x.gds')").execute (); // EXPECT_EQ (v.to_string (), std::string ()); // not universal v = e.parse ("absolute_file_path('./x.gds')").execute (); // EXPECT_EQ (v.to_string (), std::string ()); // not universal v = e.parse ("path('../irgendwas/file.tar.gz')").execute (); #if defined(_WIN32) EXPECT_EQ (v.to_string (), std::string ("..\\irgendwas")); #else EXPECT_EQ (v.to_string (), std::string ("../irgendwas")); #endif v = e.parse ("basename('../irgendwas/file.tar.gz')").execute (); EXPECT_EQ (v.to_string (), std::string ("file")); v = e.parse ("extension('../irgendwas/file.tar.gz')").execute (); EXPECT_EQ (v.to_string (), std::string ("tar.gz")); v = e.parse ("file_exists('x.gds')?1:0").execute (); // EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("is_dir('x.gds')?1:0").execute (); EXPECT_EQ (v.to_string (), std::string ("0")); v = e.parse ("combine('.', 'x.gds')").execute (); // EXPECT_EQ (v.to_string (), std::string ("./x.gds")); // not universal v = e.parse ("is_dir('.')?1:0").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); v = e.parse ("sprintf('%g %e %f',M_PI,M_PI*1e6,M_PI*0.001)").execute (); EXPECT_EQ (v.to_string (), tl::sprintf("%g %e %f", M_PI, M_PI*1e6, M_PI*0.001)); v = e.parse ("sprintf('%g %e %f',M_PI*1e6,M_PI*1e6,M_PI*1e6)").execute (); EXPECT_EQ (v.to_string (), tl::sprintf("%g %e %f", M_PI*1e6, M_PI*1e6, M_PI*1e6)); v = e.parse ("sprintf('%-15g %015.8e %15.12f %g',M_PI,M_PI*1e6,M_PI*0.001,M_PI)").execute (); EXPECT_EQ (v.to_string (), tl::sprintf("%-15g %015.8e %15.12f %g", M_PI, M_PI*1e6, M_PI*0.001,M_PI)); v = e.parse ("sprintf('%-5s %5s %x %u %d (%s)','a','b',1234,2345,3456)").execute (); EXPECT_EQ (v.to_string (), tl::sprintf("%-5s %5s %x %u %d ()", "a", "b", 1234, 2345, 3456)); std::string msg; try { v = e.parse ("error('My error')").execute (); } catch (tl::Exception &ex) { msg = ex.msg(); } EXPECT_EQ (msg, std::string ("My error")); } // compare ops TEST(7) { tl::Eval e; tl::Variant v; v = e.parse ("1==2?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("1==1?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("1!=1?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("1!=2?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("1<1?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("1<2?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("2<1?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("1<=1?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("1<=2?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("2<=1?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("1>1?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("1>2?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("2>1?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("1>=1?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("1>=2?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("2>=1?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("1+1==2?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("2*3-4==2?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("2*3-3==2?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); } // boolean ops TEST(8) { tl::Eval e; tl::Variant v; bool t; v = e.parse ("1==2?log('a'):log(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("0.69314718056")); t = false; try { v = e.parse ("1==1?log('a'):log(2)").execute (); EXPECT_EQ (v.to_string (), std::string ("abc")); } catch (tl::EvalError) { t = true; } EXPECT_EQ (t, true); t = false; try { v = e.parse ("1==2||log('a')").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); } catch (tl::EvalError) { t = true; } EXPECT_EQ (t, true); v = e.parse ("1==1||log('a')").execute (); EXPECT_EQ (v.to_string (), std::string ("true")); v = e.parse ("1==2||1==1||log('a')").execute (); EXPECT_EQ (v.to_string (), std::string ("true")); t = false; try { v = e.parse ("1==1&&log('a')").execute (); EXPECT_EQ (v.to_string (), std::string ("false")); } catch (tl::EvalError) { t = true; } EXPECT_EQ (t, true); v = e.parse ("1==2&&log('a')").execute (); EXPECT_EQ (v.to_string (), std::string ("false")); v = e.parse ("1==1&&1==2&&log('a')").execute (); EXPECT_EQ (v.to_string (), std::string ("false")); } // shift ops TEST(9) { tl::Eval e; tl::Variant v; v = e.parse ("1<<2+3").execute (); EXPECT_EQ (v.to_string (), std::string ("32")); v = e.parse ("8*8>>2+3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); } // bitwise ops TEST(10) { tl::Eval e; tl::Variant v; v = e.parse ("(1<<2)|(1<<4)").execute (); EXPECT_EQ (v.to_string (), std::string ("20")); v = e.parse ("31&63").execute (); EXPECT_EQ (v.to_string (), std::string ("31")); v = e.parse ("31^63").execute (); EXPECT_EQ (v.to_string (), std::string ("32")); } // unary ops TEST(11) { tl::Eval e; tl::Variant v; v = e.parse ("!(1==2)?2:3").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("~1").execute (); EXPECT_EQ (v.to_string (), std::string ("-2")); v = e.parse ("-1").execute (); EXPECT_EQ (v.to_string (), std::string ("-1")); v = e.parse ("--1").execute (); EXPECT_EQ (v.to_string (), std::string ("1")); } class F0 : public tl::EvalFunction { public: void execute (const tl::ExpressionParserContext &, tl::Variant &out, const std::vector &) const { out = tl::Variant (17); } }; class F1 : public tl::EvalFunction { public: void execute (const tl::ExpressionParserContext &, tl::Variant &out, const std::vector &vv) const { out = tl::Variant (vv[0].to_long() + 1); } }; class F2 : public tl::EvalFunction { public: void execute (const tl::ExpressionParserContext &, tl::Variant &out, const std::vector &vv) const { out = tl::Variant (vv[0].to_long() + 2); } }; class F3 : public tl::EvalFunction { public: void execute (const tl::ExpressionParserContext &, tl::Variant &out, const std::vector &vv) const { out = tl::Variant (vv[0].to_long() + 3); } }; // variables and functions TEST(12) { tl::Eval e, ee; e.set_global_var ("GV", tl::Variant("gg")); e.set_var ("L", tl::Variant((long) 89)); ee.set_var ("L", tl::Variant((long) 123)); e.define_global_function ("f0", new F0()); e.define_global_function ("fg", new F1()); e.define_function ("fl", new F2()); ee.define_function ("fl", new F3()); tl::Variant v; v = e.parse ("f0").execute (); EXPECT_EQ (v.to_string (), std::string ("17")); v = e.parse ("f0()").execute (); EXPECT_EQ (v.to_string (), std::string ("17")); v = e.parse ("GV+(L+1)").execute (); EXPECT_EQ (v.to_string (), std::string ("gg90")); v = ee.parse ("GV+(L+1)").execute (); EXPECT_EQ (v.to_string (), std::string ("gg124")); v = e.parse ("to_s(fg(17))+fl(L)").execute (); EXPECT_EQ (v.to_string (), std::string ("1891")); e.define_function ("fl", new F3()); v = e.parse ("to_s(fg(17))+fl(L)").execute (); EXPECT_EQ (v.to_string (), std::string ("1892")); v = ee.parse ("to_s(fg(17))+fl(L)").execute (); EXPECT_EQ (v.to_string (), std::string ("18126")); } // interpolation TEST(13) { tl::Eval e, ee; e.set_var ("L", tl::Variant((long) 89)); ee.set_var ("L", tl::Variant((long) 123)); EXPECT_EQ (e.interpolate("A$L B$(L+100)C"), std::string ("A89 B189C")); EXPECT_EQ (ee.interpolate("123*11=$(L*11)."), std::string ("123*11=1353.")); } // assignment TEST(14) { tl::Eval e; tl::Variant v; v = e.parse ("var x=1; x=x+1").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("x").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("x=x*2").execute (); EXPECT_EQ (v.to_string (), std::string ("4")); v = e.parse ("x").execute (); EXPECT_EQ (v.to_string (), std::string ("4")); v = e.parse ("var y=x==4; y").execute (); EXPECT_EQ (v.to_string (), std::string ("true")); } // index TEST(15) { tl::Eval e; tl::Variant v; v = e.parse ("var x=[1,2,3]; x[1]").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("var x=[1,2,3]; x.size").execute (); EXPECT_EQ (v.to_string (), std::string ("3")); v = e.parse ("var x=[1,2,3]; x[6]").execute (); EXPECT_EQ (v.to_string (), std::string ("nil")); v = e.parse ("var x=[1,2,3]; x[1]=5; x").execute (); EXPECT_EQ (v.to_string (), std::string ("1,5,3")); v = e.parse ("var x=[1,2,3]; x.push('A'); x").execute (); EXPECT_EQ (v.to_string (), std::string ("1,2,3,A")); v = e.parse ("var x={1=>'A','B'=>5}; x[1]").execute (); EXPECT_EQ (v.to_string (), std::string ("A")); v = e.parse ("var x={1=>'A','B'=>5}; x.keys").execute (); EXPECT_EQ (v.to_string (), std::string ("1,B")); v = e.parse ("var x={1=>'A','B'=>5}; x.values").execute (); EXPECT_EQ (v.to_string (), std::string ("A,5")); v = e.parse ("var x={1=>'A','B'=>5}; x['B']").execute (); EXPECT_EQ (v.to_string (), std::string ("5")); v = e.parse ("var x={1=>'A','B'=>5}; x[0]").execute (); EXPECT_EQ (v.to_string (), std::string ("nil")); v = e.parse ("{1=>'A','B'=>5}['B']").execute (); EXPECT_EQ (v.to_string (), std::string ("5")); v = e.parse ("var x={1=>'A','B'=>5}; x[1]=5; x").execute (); EXPECT_EQ (v.to_string (), std::string ("1=>5,B=>5")); v = e.parse ("var x={1=>'A','B'=>5}; x.size").execute (); EXPECT_EQ (v.to_string (), std::string ("2")); v = e.parse ("var x={1=>'A','B'=>5}; x.insert(17, 3); x").execute (); EXPECT_EQ (v.to_string (), std::string ("1=>A,17=>3,B=>5")); } // match/nomatch TEST(16) { tl::Eval e; tl::Variant v; v = e.parse ("'abc' ~ '*a*'").execute (); EXPECT_EQ (v.to_string (), std::string ("true")); v = e.parse ("'abc' ~ '(*)a(*)'").execute (); EXPECT_EQ (v.to_string (), std::string ("true")); v = e.parse ("$1+'.'+$2+'.'+$3").execute (); EXPECT_EQ (v.to_string (), std::string (".bc.nil")); v = e.parse ("'abc' ~ 'b*'").execute (); EXPECT_EQ (v.to_string (), std::string ("false")); v = e.parse ("'abc' !~ '*a*'").execute (); EXPECT_EQ (v.to_string (), std::string ("false")); v = e.parse ("'abc' !~ 'b*'").execute (); EXPECT_EQ (v.to_string (), std::string ("true")); } // polymorphic functions TEST(18) { tl::Eval e; tl::Variant v; e.parse ("var tr=Trans.new(1,false,Vector.new(10,20))").execute (); e.parse ("var a=Point.new(1,2)").execute (); e.parse ("var b=Point.new(11,22)").execute (); v = e.parse ("var i=CellInstArray.new(17,tr,a,b,100,200); i.to_s()").execute (); EXPECT_EQ (v.to_string (), std::string ("#17 r90 10,20 [1,2*100;11,22*200]")); v = e.parse ("var i=CellInstArray.new(17,tr,a,b,100,200); i.is_complex()").execute (); EXPECT_EQ (v.to_string (), std::string ("false")); } // comments TEST(19) { tl::Eval e; e.parse ("var tr=Trans.new(1,false,Vector.new(10,20))").execute (); e.parse ("var a=Point.new(1,2)").execute (); e.parse ("var b=Point.new(11,22)").execute (); tl::Variant v; v = e.parse ("# A comment\nvar i=CellInstArray.new(17,tr,a,b,100,200); i.to_s(); # A final comment").execute (); EXPECT_EQ (v.to_string (), std::string ("#17 r90 10,20 [1,2*100;11,22*200]")); } // issue-787 TEST(20) { tl::Eval e; e.parse ("var ly=Layout.new(true)").execute (); e.parse ("var top=ly.create_cell('TOP')").execute (); e.parse ("var cell=ly.create_cell('CHILD')").execute (); e.parse ("var i1 = top.insert(CellInstArray.new(cell.cell_index,Trans.new(Vector.new(100,200))))").execute (); e.parse ("var i2 = top.insert(CellInstArray.new(cell.cell_index,Trans.new(Vector.new(-100,300))))").execute (); tl::Variant v; v = e.parse ("i1.dtrans.disp.x").execute (); EXPECT_EQ (v.to_string (), std::string ("0.1")); v = e.parse ("i1.dtrans.disp.y").execute (); EXPECT_EQ (v.to_string (), std::string ("0.2")); v = e.parse ("i2.dtrans.disp.x").execute (); EXPECT_EQ (v.to_string (), std::string ("-0.1")); v = e.parse ("i2.dtrans.disp.y").execute (); EXPECT_EQ (v.to_string (), std::string ("0.3")); }