mirror of https://github.com/KLayout/klayout.git
Bug fixes, tests improved
This commit is contained in:
parent
6e161d938f
commit
a0d7af3d70
|
|
@ -1928,9 +1928,9 @@ TEST(205_extended_props)
|
|||
TempPropertiesRepository temp_pr;
|
||||
|
||||
db::SaveLayoutOptions options;
|
||||
EXPECT_EQ (options.get_option_by_name ("extended_features").to_bool (), true);
|
||||
options.set_option_by_name ("extended_features", false);
|
||||
EXPECT_EQ (options.get_option_by_name ("extended_features").to_bool (), false);
|
||||
EXPECT_EQ (options.get_option_by_name ("gds2_extended_features").to_bool (), true);
|
||||
options.set_option_by_name ("gds2_extended_features", false);
|
||||
EXPECT_EQ (options.get_option_by_name ("gds2_extended_features").to_bool (), false);
|
||||
|
||||
db::PropertiesSet ps1;
|
||||
ps1.insert (tl::Variant ("prop_name"), db::DBox (0, 0, 1.5, 2.5));
|
||||
|
|
|
|||
|
|
@ -3722,12 +3722,96 @@ get_variable_name (tl::Extractor &ex, std::string &name)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Eval::read_number (ExpressionParserContext &ex, tl::Variant &t)
|
||||
{
|
||||
ExpressionParserContext exl = ex, exd = ex, ex1 = ex;
|
||||
|
||||
long long l = 0;
|
||||
double d = 0.0;
|
||||
bool is_long = exl.try_read (l);
|
||||
bool is_double = exd.try_read (d);
|
||||
|
||||
if (! is_long && ! is_double) {
|
||||
|
||||
return false;
|
||||
|
||||
} else if ((is_long && ! is_double) || (is_long && is_double && exl.get () >= exd.get ())) {
|
||||
|
||||
ex = exl;
|
||||
|
||||
if (l <= (long long) std::numeric_limits<long>::max () && l >= (long long) std::numeric_limits<long>::min ()) {
|
||||
t = tl::Variant (long (l));
|
||||
} else {
|
||||
t = tl::Variant (l);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
ex = exd;
|
||||
t = tl::Variant (d);
|
||||
|
||||
}
|
||||
|
||||
double f = 0.0;
|
||||
double dbu = ctx_handler () ? ctx_handler ()->dbu () : 1.0;
|
||||
|
||||
if (ex.test ("um2") || ex.test("micron2") || ex.test ("mic2")) {
|
||||
f = 1.0 / (dbu * dbu);
|
||||
} else if (ex.test ("nm2")) {
|
||||
f = 1e-6 / (dbu * dbu);
|
||||
} else if (ex.test ("mm2")) {
|
||||
f = 1e6 / (dbu * dbu);
|
||||
} else if (ex.test ("m2")) {
|
||||
f = 1e12 / (dbu * dbu);
|
||||
} else if (ex.test ("bs")) {
|
||||
f = 0.005 / dbu;
|
||||
} else if (ex.test ("nm")) {
|
||||
f = 1e-3 / dbu;
|
||||
} else if (ex.test ("um") || ex.test("micron") || ex.test ("mic")) {
|
||||
f = 1.0 / dbu;
|
||||
} else if (ex.test ("mm")) {
|
||||
f = 1e3 / dbu;
|
||||
} else if (ex.test ("m")) {
|
||||
f = 1e6 / dbu;
|
||||
}
|
||||
|
||||
// DBU conversion
|
||||
if (f != 0.0) {
|
||||
|
||||
if (! ctx_handler ()) {
|
||||
|
||||
if (m_sloppy) {
|
||||
t = tl::Variant ();
|
||||
} else {
|
||||
throw EvalError (tl::to_string (tr ("Length or area value with unit requires a layout context")), ex1);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (m_sloppy) {
|
||||
t = tl::Variant (t.to_double () * f);
|
||||
} else {
|
||||
double gg = t.to_double ();
|
||||
double g = floor (0.5 + t.to_double ());
|
||||
if (fabs (g) < 1e12 && fabs (g - gg) > 1e-3) {
|
||||
throw EvalError (tl::to_string (tr ("Value is not a multiple of the database unit")), ex1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Eval::eval_atomic (ExpressionParserContext &ex, std::unique_ptr<ExpressionNode> &n, int am)
|
||||
{
|
||||
double g = 0.0;
|
||||
int match_group = 0;
|
||||
std::string t;
|
||||
tl::Variant g;
|
||||
|
||||
ExpressionParserContext ex1 = ex;
|
||||
if (ex.test ("(")) {
|
||||
|
|
@ -3881,97 +3965,9 @@ Eval::eval_atomic (ExpressionParserContext &ex, std::unique_ptr<ExpressionNode>
|
|||
|
||||
n.reset (new ConstantExpressionNode (ex1, tl::Variant (x)));
|
||||
|
||||
} else if (ex.try_read (g)) {
|
||||
} else if (read_number (ex, g)) {
|
||||
|
||||
bool dbu_units = false;
|
||||
|
||||
if (ex.test ("um2") || ex.test("micron2") || ex.test ("mic2")) {
|
||||
dbu_units = true;
|
||||
if (ctx_handler ()) {
|
||||
g *= 1.0 / (ctx_handler ()->dbu () * ctx_handler ()->dbu ());
|
||||
}
|
||||
} else if (ex.test ("nm2")) {
|
||||
dbu_units = true;
|
||||
if (ctx_handler ()) {
|
||||
g *= 1e-6 / (ctx_handler ()->dbu () * ctx_handler ()->dbu ());
|
||||
}
|
||||
} else if (ex.test ("mm2")) {
|
||||
dbu_units = true;
|
||||
if (ctx_handler ()) {
|
||||
g *= 1e6 / (ctx_handler ()->dbu () * ctx_handler ()->dbu ());
|
||||
}
|
||||
} else if (ex.test ("m2")) {
|
||||
dbu_units = true;
|
||||
if (ctx_handler ()) {
|
||||
g *= 1e12 / (ctx_handler ()->dbu () * ctx_handler ()->dbu ());
|
||||
}
|
||||
} else if (ex.test ("bs")) {
|
||||
dbu_units = true;
|
||||
if (ctx_handler ()) {
|
||||
g *= 0.005 / ctx_handler ()->dbu ();
|
||||
}
|
||||
} else if (ex.test ("nm")) {
|
||||
dbu_units = true;
|
||||
if (ctx_handler ()) {
|
||||
g *= 1e-3 / ctx_handler ()->dbu ();
|
||||
}
|
||||
} else if (ex.test ("um") || ex.test("micron") || ex.test ("mic")) {
|
||||
dbu_units = true;
|
||||
if (ctx_handler ()) {
|
||||
g *= 1.0 / ctx_handler ()->dbu ();
|
||||
}
|
||||
} else if (ex.test ("mm")) {
|
||||
dbu_units = true;
|
||||
if (ctx_handler ()) {
|
||||
g *= 1e3 / ctx_handler ()->dbu ();
|
||||
}
|
||||
} else if (ex.test ("m")) {
|
||||
dbu_units = true;
|
||||
if (ctx_handler ()) {
|
||||
g *= 1e6 / ctx_handler ()->dbu ();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_sloppy) {
|
||||
|
||||
if (dbu_units && ! ctx_handler ()) {
|
||||
n.reset (new ConstantExpressionNode (ex1, tl::Variant ()));
|
||||
} else {
|
||||
n.reset (new ConstantExpressionNode (ex1, tl::Variant (g)));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (dbu_units && ! ctx_handler ()) {
|
||||
throw EvalError (tl::to_string (tr ("Length or area value with unit requires a layout context")), ex1);
|
||||
}
|
||||
|
||||
if (dbu_units) {
|
||||
|
||||
// round to integers and check whether that is possible
|
||||
double gg = g;
|
||||
g = floor (0.5 + g);
|
||||
if (fabs (g) < 1e12 && fabs (g - gg) > 1e-3) {
|
||||
throw EvalError (tl::to_string (tr ("Value is not a multiple of the database unit")), ex1);
|
||||
}
|
||||
|
||||
n.reset (new ConstantExpressionNode (ex1, tl::Variant (g)));
|
||||
|
||||
} else {
|
||||
|
||||
tl::Variant v (g);
|
||||
|
||||
// prefer integers
|
||||
if (g - floor (g) == 0.0 && v.can_convert_to_long ()) {
|
||||
n.reset (new ConstantExpressionNode (ex1, tl::Variant (v.to_long ())));
|
||||
} else {
|
||||
n.reset (new ConstantExpressionNode (ex1, v));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
n.reset (new ConstantExpressionNode (ex1, g));
|
||||
|
||||
} else if (ex.try_read_quoted (t)) {
|
||||
|
||||
|
|
|
|||
|
|
@ -616,6 +616,7 @@ private:
|
|||
void eval_unary (ExpressionParserContext &context, std::unique_ptr<ExpressionNode> &v);
|
||||
void eval_atomic (ExpressionParserContext &context, std::unique_ptr<ExpressionNode> &v, int am);
|
||||
void eval_suffix (ExpressionParserContext &context, std::unique_ptr<ExpressionNode> &v);
|
||||
bool read_number (ExpressionParserContext &ex, tl::Variant &t);
|
||||
|
||||
static Eval m_global;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ TEST(1)
|
|||
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"));
|
||||
v = e.parse ("2+3/2.0").execute ();
|
||||
EXPECT_EQ (v.to_string (), std::string ("3.5"));
|
||||
|
||||
v = e.parse ("to_i(1)*to_i(2)").execute ();
|
||||
|
|
@ -650,13 +652,57 @@ TEST(2)
|
|||
EXPECT_EQ (v.to_string (), std::string ("2"));
|
||||
}
|
||||
|
||||
// to_double
|
||||
// numerical constants
|
||||
TEST(3)
|
||||
{
|
||||
tl::Eval e;
|
||||
tl::Variant v;
|
||||
|
||||
v = e.parse ("[1,2,3]/2").execute ();
|
||||
v = e.parse ("2.5+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##3.5"));
|
||||
v = e.parse ("-2.5+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##-1.5"));
|
||||
v = e.parse ("2+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("#3"));
|
||||
v = e.parse ("-2+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("#-1"));
|
||||
v = e.parse ("2.0+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##3"));
|
||||
v = e.parse ("-2.0+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##-1"));
|
||||
v = e.parse ("2.+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##3"));
|
||||
v = e.parse ("-2.+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##-1"));
|
||||
v = e.parse ("2.e1+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##21"));
|
||||
v = e.parse ("-2.e1+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##-19"));
|
||||
v = e.parse ("2e-1+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##1.2"));
|
||||
v = e.parse ("-2e-1+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##0.8"));
|
||||
v = e.parse (".2e+1+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##3"));
|
||||
v = e.parse ("-.2e+1+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##-1"));
|
||||
v = e.parse (".2+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##1.2"));
|
||||
v = e.parse ("-.2+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##0.8"));
|
||||
v = e.parse ("0.2+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##1.2"));
|
||||
v = e.parse ("-0.2+1 ").execute ();
|
||||
EXPECT_EQ (v.to_parsable_string (), std::string ("##0.8"));
|
||||
}
|
||||
|
||||
// to_double
|
||||
TEST(4)
|
||||
{
|
||||
tl::Eval e;
|
||||
tl::Variant v;
|
||||
|
||||
v = e.parse ("[1,2,3]/2.0").execute ();
|
||||
EXPECT_EQ (v.to_string (), std::string ("1.5"));
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1146,8 +1146,8 @@ class DBLayoutTest(unittest.TestCase):
|
|||
self.assertEqual(shape.property("2"), None)
|
||||
self.assertEqual(shape.property(2.0), None)
|
||||
self.assertEqual(shape.property(22), None)
|
||||
self.assertEqual(shape.property(42), "the answer")
|
||||
self.assertEqual(shape.property("42"), None)
|
||||
self.assertEqual(shape.property("42"), "the answer")
|
||||
self.assertEqual(shape.property(42), None)
|
||||
self.assertEqual(shape.property(42.0), None)
|
||||
|
||||
ly2 = pya.Layout()
|
||||
|
|
|
|||
|
|
@ -40,12 +40,12 @@ class TLTest(unittest.TestCase):
|
|||
self.assertEqual(str(type(res)).replace("class", "type"), "<type 'NoneType'>")
|
||||
self.assertEqual(repr(res), "None")
|
||||
|
||||
expr = pya.Expression.eval("1+2")
|
||||
expr = pya.Expression.eval("1+2.0")
|
||||
self.assertEqual(str(type(expr)).replace("class", "type"), "<type 'float'>")
|
||||
self.assertEqual(repr(expr), "3.0")
|
||||
|
||||
expr = pya.Expression()
|
||||
expr.text = "1+2"
|
||||
expr.text = "1+2.0"
|
||||
res = expr.eval()
|
||||
self.assertEqual(str(type(res)).replace("class", "type"), "<type 'float'>")
|
||||
self.assertEqual(str(res), "3.0")
|
||||
|
|
|
|||
|
|
@ -40,14 +40,18 @@ class Tl_TestClass < TestBase
|
|||
assert_equal(res.to_s, "")
|
||||
|
||||
expr = RBA::Expression.eval("1+2")
|
||||
assert_equal(expr.class.to_s, "Integer")
|
||||
assert_equal(expr.to_s, "3")
|
||||
|
||||
expr = RBA::Expression.eval("1+2.0")
|
||||
assert_equal(expr.class.to_s, "Float")
|
||||
assert_equal(expr.to_s, "3.0")
|
||||
|
||||
expr = RBA::Expression::new
|
||||
expr.text = "1+2"
|
||||
res = expr.eval
|
||||
assert_equal(res.class.to_s, "Float")
|
||||
assert_equal(res.to_s, "3.0")
|
||||
assert_equal(res.class.to_s, "Integer")
|
||||
assert_equal(res.to_s, "3")
|
||||
|
||||
expr = RBA::Expression::new
|
||||
expr.var("a", 5)
|
||||
|
|
|
|||
Loading…
Reference in New Issue