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;
|
TempPropertiesRepository temp_pr;
|
||||||
|
|
||||||
db::SaveLayoutOptions options;
|
db::SaveLayoutOptions options;
|
||||||
EXPECT_EQ (options.get_option_by_name ("extended_features").to_bool (), true);
|
EXPECT_EQ (options.get_option_by_name ("gds2_extended_features").to_bool (), true);
|
||||||
options.set_option_by_name ("extended_features", false);
|
options.set_option_by_name ("gds2_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 (), false);
|
||||||
|
|
||||||
db::PropertiesSet ps1;
|
db::PropertiesSet ps1;
|
||||||
ps1.insert (tl::Variant ("prop_name"), db::DBox (0, 0, 1.5, 2.5));
|
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
|
void
|
||||||
Eval::eval_atomic (ExpressionParserContext &ex, std::unique_ptr<ExpressionNode> &n, int am)
|
Eval::eval_atomic (ExpressionParserContext &ex, std::unique_ptr<ExpressionNode> &n, int am)
|
||||||
{
|
{
|
||||||
double g = 0.0;
|
|
||||||
int match_group = 0;
|
int match_group = 0;
|
||||||
std::string t;
|
std::string t;
|
||||||
|
tl::Variant g;
|
||||||
|
|
||||||
ExpressionParserContext ex1 = ex;
|
ExpressionParserContext ex1 = ex;
|
||||||
if (ex.test ("(")) {
|
if (ex.test ("(")) {
|
||||||
|
|
@ -3881,97 +3965,9 @@ Eval::eval_atomic (ExpressionParserContext &ex, std::unique_ptr<ExpressionNode>
|
||||||
|
|
||||||
n.reset (new ConstantExpressionNode (ex1, tl::Variant (x)));
|
n.reset (new ConstantExpressionNode (ex1, tl::Variant (x)));
|
||||||
|
|
||||||
} else if (ex.try_read (g)) {
|
} else if (read_number (ex, g)) {
|
||||||
|
|
||||||
bool dbu_units = false;
|
n.reset (new ConstantExpressionNode (ex1, g));
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (ex.try_read_quoted (t)) {
|
} else if (ex.try_read_quoted (t)) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -616,6 +616,7 @@ private:
|
||||||
void eval_unary (ExpressionParserContext &context, std::unique_ptr<ExpressionNode> &v);
|
void eval_unary (ExpressionParserContext &context, std::unique_ptr<ExpressionNode> &v);
|
||||||
void eval_atomic (ExpressionParserContext &context, std::unique_ptr<ExpressionNode> &v, int am);
|
void eval_atomic (ExpressionParserContext &context, std::unique_ptr<ExpressionNode> &v, int am);
|
||||||
void eval_suffix (ExpressionParserContext &context, std::unique_ptr<ExpressionNode> &v);
|
void eval_suffix (ExpressionParserContext &context, std::unique_ptr<ExpressionNode> &v);
|
||||||
|
bool read_number (ExpressionParserContext &ex, tl::Variant &t);
|
||||||
|
|
||||||
static Eval m_global;
|
static Eval m_global;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,8 @@ TEST(1)
|
||||||
v = e.parse ("7%4").execute ();
|
v = e.parse ("7%4").execute ();
|
||||||
EXPECT_EQ (v.to_string (), std::string ("3"));
|
EXPECT_EQ (v.to_string (), std::string ("3"));
|
||||||
v = e.parse ("2+3/2").execute ();
|
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"));
|
EXPECT_EQ (v.to_string (), std::string ("3.5"));
|
||||||
|
|
||||||
v = e.parse ("to_i(1)*to_i(2)").execute ();
|
v = e.parse ("to_i(1)*to_i(2)").execute ();
|
||||||
|
|
@ -650,13 +652,57 @@ TEST(2)
|
||||||
EXPECT_EQ (v.to_string (), std::string ("2"));
|
EXPECT_EQ (v.to_string (), std::string ("2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// to_double
|
// numerical constants
|
||||||
TEST(3)
|
TEST(3)
|
||||||
{
|
{
|
||||||
tl::Eval e;
|
tl::Eval e;
|
||||||
tl::Variant v;
|
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"));
|
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"), None)
|
||||||
self.assertEqual(shape.property(2.0), None)
|
self.assertEqual(shape.property(2.0), None)
|
||||||
self.assertEqual(shape.property(22), None)
|
self.assertEqual(shape.property(22), None)
|
||||||
self.assertEqual(shape.property(42), "the answer")
|
self.assertEqual(shape.property("42"), "the answer")
|
||||||
self.assertEqual(shape.property("42"), None)
|
self.assertEqual(shape.property(42), None)
|
||||||
self.assertEqual(shape.property(42.0), None)
|
self.assertEqual(shape.property(42.0), None)
|
||||||
|
|
||||||
ly2 = pya.Layout()
|
ly2 = pya.Layout()
|
||||||
|
|
|
||||||
|
|
@ -40,12 +40,12 @@ class TLTest(unittest.TestCase):
|
||||||
self.assertEqual(str(type(res)).replace("class", "type"), "<type 'NoneType'>")
|
self.assertEqual(str(type(res)).replace("class", "type"), "<type 'NoneType'>")
|
||||||
self.assertEqual(repr(res), "None")
|
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(str(type(expr)).replace("class", "type"), "<type 'float'>")
|
||||||
self.assertEqual(repr(expr), "3.0")
|
self.assertEqual(repr(expr), "3.0")
|
||||||
|
|
||||||
expr = pya.Expression()
|
expr = pya.Expression()
|
||||||
expr.text = "1+2"
|
expr.text = "1+2.0"
|
||||||
res = expr.eval()
|
res = expr.eval()
|
||||||
self.assertEqual(str(type(res)).replace("class", "type"), "<type 'float'>")
|
self.assertEqual(str(type(res)).replace("class", "type"), "<type 'float'>")
|
||||||
self.assertEqual(str(res), "3.0")
|
self.assertEqual(str(res), "3.0")
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,18 @@ class Tl_TestClass < TestBase
|
||||||
assert_equal(res.to_s, "")
|
assert_equal(res.to_s, "")
|
||||||
|
|
||||||
expr = RBA::Expression.eval("1+2")
|
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.class.to_s, "Float")
|
||||||
assert_equal(expr.to_s, "3.0")
|
assert_equal(expr.to_s, "3.0")
|
||||||
|
|
||||||
expr = RBA::Expression::new
|
expr = RBA::Expression::new
|
||||||
expr.text = "1+2"
|
expr.text = "1+2"
|
||||||
res = expr.eval
|
res = expr.eval
|
||||||
assert_equal(res.class.to_s, "Float")
|
assert_equal(res.class.to_s, "Integer")
|
||||||
assert_equal(res.to_s, "3.0")
|
assert_equal(res.to_s, "3")
|
||||||
|
|
||||||
expr = RBA::Expression::new
|
expr = RBA::Expression::new
|
||||||
expr.var("a", 5)
|
expr.var("a", 5)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue