mirror of https://github.com/KLayout/klayout.git
WIP: More on deep regions & hier processor
- Splitting of shapes on output of booleans - A bugfix: error happened when pulling intruders from second-next hier level - Tests added - Some TODO comments added
This commit is contained in:
parent
06c11d0096
commit
7073a74aa5
|
|
@ -346,7 +346,7 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const
|
|||
{
|
||||
DeepLayer dl_out (m_deep_layer.derived ());
|
||||
|
||||
db::BoolAndOrNotLocalOperation op (and_op);
|
||||
db::BoolAndOrNotLocalOperation op (and_op, m_deep_layer.store ()->max_area_ratio (), m_deep_layer.store ()->max_vertex_count ());
|
||||
|
||||
db::LocalProcessor proc (const_cast <db::Layout *> (m_deep_layer.layout ()), const_cast <db::Cell *> (m_deep_layer.initial_cell ()), other->deep_layer ().layout (), other->deep_layer ().initial_cell ());
|
||||
proc.set_threads (m_deep_layer.store ()->threads ());
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ struct DeepShapeStore::LayoutHolder
|
|||
static size_t s_instance_count = 0;
|
||||
|
||||
DeepShapeStore::DeepShapeStore ()
|
||||
: m_threads (1)
|
||||
: m_threads (1), m_max_area_ratio (3.0), m_max_vertex_count (16)
|
||||
{
|
||||
++s_instance_count;
|
||||
}
|
||||
|
|
@ -219,6 +219,16 @@ void DeepShapeStore::set_threads (int n)
|
|||
m_threads = n;
|
||||
}
|
||||
|
||||
void DeepShapeStore::set_max_area_ratio (double ar)
|
||||
{
|
||||
m_max_area_ratio = ar;
|
||||
}
|
||||
|
||||
void DeepShapeStore::set_max_vertex_count (size_t n)
|
||||
{
|
||||
m_max_vertex_count = n;
|
||||
}
|
||||
|
||||
void DeepShapeStore::add_ref (unsigned int layout, unsigned int layer)
|
||||
{
|
||||
tl::MutexLocker locker (&m_lock);
|
||||
|
|
@ -245,6 +255,13 @@ void DeepShapeStore::remove_ref (unsigned int layout, unsigned int layer)
|
|||
|
||||
DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio, size_t max_vertex_count)
|
||||
{
|
||||
if (max_area_ratio == 0.0) {
|
||||
max_area_ratio = m_max_area_ratio;
|
||||
}
|
||||
if (max_vertex_count == 0) {
|
||||
max_vertex_count = m_max_vertex_count;
|
||||
}
|
||||
|
||||
unsigned int layout_index = 0;
|
||||
|
||||
layout_map_type::iterator l = m_layout_map.find (si);
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ public:
|
|||
* into parts satisfying the area ratio (bounding box vs. polygon area)
|
||||
* and maximum vertex count constraints.
|
||||
*/
|
||||
DeepLayer create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio = 3.0, size_t max_vertex_count = 16);
|
||||
DeepLayer create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio = 0.0, size_t max_vertex_count = 0);
|
||||
|
||||
/**
|
||||
* @brief Inserts the deep layer's shapes into some target layout
|
||||
|
|
@ -240,6 +240,40 @@ public:
|
|||
return m_threads;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the maximum vertex count default value
|
||||
*
|
||||
* This parameter is used to simplify complex polygons. It is used by
|
||||
* create_polygon_layer with the default parameters. It's also used by
|
||||
* boolean operations when they deliver their output.
|
||||
*/
|
||||
void set_max_vertex_count (size_t n);
|
||||
|
||||
/**
|
||||
* @brief Gets the maximum vertex count
|
||||
*/
|
||||
size_t max_vertex_count () const
|
||||
{
|
||||
return m_max_vertex_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the max. area ratio for bounding box vs. polygon area
|
||||
*
|
||||
* This parameter is used to simplify complex polygons. It is used by
|
||||
* create_polygon_layer with the default parameters. It's also used by
|
||||
* boolean operations when they deliver their output.
|
||||
*/
|
||||
void set_max_area_ratio (double ar);
|
||||
|
||||
/**
|
||||
* @brief Gets the max. area ratio
|
||||
*/
|
||||
double max_area_ratio () const
|
||||
{
|
||||
return m_max_area_ratio;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class DeepLayer;
|
||||
|
||||
|
|
@ -259,6 +293,8 @@ private:
|
|||
std::vector<LayoutHolder *> m_layouts;
|
||||
layout_map_type m_layout_map;
|
||||
int m_threads;
|
||||
double m_max_area_ratio;
|
||||
size_t m_max_vertex_count;
|
||||
tl::Mutex m_lock;
|
||||
|
||||
struct DeliveryMappingCacheKey
|
||||
|
|
|
|||
|
|
@ -101,14 +101,14 @@ public:
|
|||
template <class Trans>
|
||||
Ref operator() (const Ref &ref, const Trans &tr) const
|
||||
{
|
||||
shape_type sh = ref.obj ().transformed (Trans (ref_trans_type (tr).inverted ()) * tr);
|
||||
shape_type sh = ref.obj ().transformed (tr * Trans (ref.trans ()));
|
||||
ref_trans_type red_trans;
|
||||
sh.reduce (red_trans);
|
||||
|
||||
typename std::unordered_map<shape_type, std::pair<const shape_type *, ref_trans_type> >::const_iterator m = m_cache_by_shape.find (sh);
|
||||
typename std::unordered_map<shape_type, const shape_type *>::const_iterator m = m_cache_by_shape.find (sh);
|
||||
if (m != m_cache_by_shape.end ()) {
|
||||
|
||||
return Ref (m->second.first, ref_trans_type (tr * Trans (ref.trans ())) * m->second.second);
|
||||
return Ref (m->second, red_trans);
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -118,8 +118,8 @@ public:
|
|||
ptr = mp_layout->shape_repository ().repository (typename shape_type::tag ()).insert (sh);
|
||||
}
|
||||
|
||||
m_cache_by_shape[sh] = std::make_pair (ptr, red_trans);
|
||||
return Ref (ptr, ref_trans_type (tr * Trans (ref.trans ())) * red_trans);
|
||||
m_cache_by_shape[sh] = ptr;
|
||||
return Ref (ptr, red_trans);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -127,7 +127,7 @@ public:
|
|||
private:
|
||||
db::Layout *mp_layout;
|
||||
mutable std::unordered_map<const shape_type *, const shape_type *> m_cache;
|
||||
mutable std::unordered_map<shape_type, std::pair<const shape_type *, ref_trans_type> > m_cache_by_shape;
|
||||
mutable std::unordered_map<shape_type, const shape_type *> m_cache_by_shape;
|
||||
};
|
||||
|
||||
template <class Ref, class Trans>
|
||||
|
|
@ -494,9 +494,9 @@ private:
|
|||
unsigned int m_intruder_layer;
|
||||
db::Coord m_dist;
|
||||
ShapeInteractions *mp_result;
|
||||
std::unordered_map<std::pair<unsigned int, const db::PolygonRef *>, unsigned int> m_inst_shape_ids;
|
||||
std::unordered_map<db::PolygonRef, unsigned int> m_inst_shape_ids;
|
||||
|
||||
void add_shapes_from_intruder_inst (unsigned int id1, const db::Cell &intruder_cell, const db::ICplxTrans &tn, unsigned int inst_id, const db::Box ®ion)
|
||||
void add_shapes_from_intruder_inst (unsigned int id1, const db::Cell &intruder_cell, const db::ICplxTrans &tn, unsigned int /*inst_id*/, const db::Box ®ion)
|
||||
{
|
||||
db::shape_reference_translator<db::PolygonRef> rt (mp_subject_layout);
|
||||
|
||||
|
|
@ -507,18 +507,17 @@ private:
|
|||
si.shape_flags (polygon_ref_flags ());
|
||||
while (! si.at_end ()) {
|
||||
|
||||
const db::PolygonRef *ref2 = si.shape ().basic_ptr (db::PolygonRef::tag ());
|
||||
// NOTE: we intentionally rewrite to the *subject* layout - this way polygon refs in the context come from the
|
||||
// subject, not from the intruder.
|
||||
db::PolygonRef ref2 = rt (*si.shape ().basic_ptr (db::PolygonRef::tag ()), tn * si.trans ());
|
||||
|
||||
// reuse the same id for shapes from the same instance -> this avoid duplicates with different IDs on
|
||||
// the intruder side.
|
||||
std::unordered_map<std::pair<unsigned int, const db::PolygonRef *>, unsigned int>::const_iterator k = m_inst_shape_ids.find (std::make_pair (inst_id, ref2));
|
||||
std::unordered_map<db::PolygonRef, unsigned int>::const_iterator k = m_inst_shape_ids.find (ref2);
|
||||
if (k == m_inst_shape_ids.end ()) {
|
||||
|
||||
k = m_inst_shape_ids.insert (std::make_pair (std::make_pair (inst_id, ref2), mp_result->next_id ())).first;
|
||||
|
||||
// NOTE: we intentionally rewrite to the *subject* layout - this way polygon refs in the context come from the
|
||||
// subject, not from the intruder.
|
||||
mp_result->add_shape (k->second, rt (*ref2, tn * si.trans ()));
|
||||
k = m_inst_shape_ids.insert (std::make_pair (ref2, mp_result->next_id ())).first;
|
||||
mp_result->add_shape (k->second, ref2);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -887,6 +886,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts,
|
|||
}
|
||||
}
|
||||
|
||||
// @@@ can we shortcut this if interactions is empty?
|
||||
{
|
||||
db::box_scanner2<db::CellInstArray, int, db::CellInstArray, int> scanner;
|
||||
InteractionRegistrationInst2Inst rec (mp_subject_layout, contexts.subject_layer (), mp_intruder_layout, contexts.intruder_layer (), dist, &interactions);
|
||||
|
|
@ -935,6 +935,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts,
|
|||
scanner.process (rec, dist, inst_bcs, inst_bci);
|
||||
}
|
||||
|
||||
// @@@ can we shortcut this if interactions is empty?
|
||||
{
|
||||
db::box_scanner2<db::CellInstArray, int, db::PolygonRef, int> scanner;
|
||||
InteractionRegistrationInst2Shape rec (mp_subject_layout, contexts.subject_layer (), dist, &interactions);
|
||||
|
|
@ -1136,6 +1137,7 @@ LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db::
|
|||
scanner.insert (ref, id++);
|
||||
}
|
||||
|
||||
// @@@ TODO: can we confine this search to the subject's (sized) bounding box?
|
||||
for (std::unordered_set<db::PolygonRef>::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) {
|
||||
scanner.insert (i.operator-> (), interactions.next_id ());
|
||||
}
|
||||
|
|
@ -1153,11 +1155,13 @@ LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db::
|
|||
scanner.insert1 (ref, id++);
|
||||
}
|
||||
|
||||
// @@@ TODO: can we confine this search to the subject's (sized) bounding box?
|
||||
for (std::unordered_set<db::PolygonRef>::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) {
|
||||
scanner.insert2 (i.operator-> (), interactions.next_id ());
|
||||
}
|
||||
|
||||
if (intruder_shapes) {
|
||||
// @@@ TODO: can we confine this search to the subject's (sized) bounding box?
|
||||
for (db::Shapes::shape_iterator i = intruder_shapes->begin (polygon_ref_flags ()); !i.at_end (); ++i) {
|
||||
scanner.insert2 (i->basic_ptr (db::PolygonRef::tag ()), interactions.next_id ());
|
||||
}
|
||||
|
|
@ -1188,6 +1192,7 @@ LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db::
|
|||
// interactions low in the hierarchy.
|
||||
|
||||
} else if (intruder_cell) {
|
||||
// @@@ TODO: can we confine this search to the subject's (sized) bounding box?
|
||||
for (db::Cell::const_iterator i = intruder_cell->begin (); !i.at_end (); ++i) {
|
||||
if (! inst_bci (i->cell_inst ()).empty ()) {
|
||||
scanner.insert2 (&i->cell_inst (), ++inst_id);
|
||||
|
|
@ -1195,6 +1200,7 @@ LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db::
|
|||
}
|
||||
}
|
||||
|
||||
// @@@ TODO: can we confine this search to the subject's (sized) bounding box?
|
||||
for (std::unordered_set<db::CellInstArray>::const_iterator i = intruders.first.begin (); i != intruders.first.end (); ++i) {
|
||||
if (! inst_bci (*i).empty ()) {
|
||||
scanner.insert2 (i.operator-> (), ++inst_id);
|
||||
|
|
|
|||
|
|
@ -474,20 +474,10 @@ ReducingHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, const db:
|
|||
reduce (shape, region, complex_region, target);
|
||||
}
|
||||
|
||||
static double area_ratio (const db::Polygon &poly)
|
||||
{
|
||||
return double (poly.box ().area ()) / double (poly.area ());
|
||||
}
|
||||
|
||||
void
|
||||
ReducingHierarchyBuilderShapeReceiver::reduce (const db::Polygon &poly, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
{
|
||||
size_t npoints = 0;
|
||||
for (unsigned int c = 0; c < poly.holes () + 1; ++c) {
|
||||
npoints += poly.contour (c).size ();
|
||||
}
|
||||
|
||||
if (npoints > m_max_vertex_count || area_ratio (poly) > m_area_ratio) {
|
||||
if (poly.vertices () > m_max_vertex_count || poly.area_ratio () > m_area_ratio) {
|
||||
|
||||
std::vector <db::Polygon> split_polygons;
|
||||
db::split_polygon (poly, split_polygons);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "dbBoxConvert.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
#include "dbPolygonGenerators.h"
|
||||
#include "dbPolygonTools.h"
|
||||
#include "tlLog.h"
|
||||
#include "tlTimer.h"
|
||||
#include "tlInternational.h"
|
||||
|
|
@ -65,12 +66,46 @@ private:
|
|||
std::unordered_set<db::PolygonRef> *mp_polyrefs;
|
||||
};
|
||||
|
||||
class PolygonSplitter
|
||||
: public PolygonSink
|
||||
{
|
||||
public:
|
||||
PolygonSplitter (PolygonSink &sink, double max_area_ratio, size_t max_vertex_count)
|
||||
: mp_sink (&sink), m_max_area_ratio (max_area_ratio), m_max_vertex_count (max_vertex_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void put (const db::Polygon &poly)
|
||||
{
|
||||
if ((m_max_vertex_count > 0 && poly.vertices () > m_max_vertex_count) || (m_max_area_ratio > 0.0 && poly.area_ratio () > m_max_area_ratio)) {
|
||||
|
||||
std::vector <db::Polygon> split_polygons;
|
||||
db::split_polygon (poly, split_polygons);
|
||||
for (std::vector <db::Polygon>::const_iterator sp = split_polygons.begin (); sp != split_polygons.end (); ++sp) {
|
||||
put (*sp);
|
||||
}
|
||||
|
||||
} else {
|
||||
mp_sink->put (poly);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void start () { mp_sink->start (); }
|
||||
virtual void flush () { mp_sink->flush (); }
|
||||
|
||||
private:
|
||||
PolygonSink *mp_sink;
|
||||
double m_max_area_ratio;
|
||||
size_t m_max_vertex_count;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
BoolAndOrNotLocalOperation::BoolAndOrNotLocalOperation (bool is_and)
|
||||
: m_is_and (is_and)
|
||||
BoolAndOrNotLocalOperation::BoolAndOrNotLocalOperation (bool is_and, double max_area_ratio, size_t max_vertex_count)
|
||||
: m_is_and (is_and), m_max_area_ratio (max_area_ratio), m_max_vertex_count (max_vertex_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -133,7 +168,8 @@ BoolAndOrNotLocalOperation::compute_local (db::Layout *layout, const ShapeIntera
|
|||
|
||||
db::BooleanOp op (m_is_and ? db::BooleanOp::And : db::BooleanOp::ANotB);
|
||||
db::PolygonRefGenerator pr (layout, result);
|
||||
db::PolygonGenerator pg (pr, true, true);
|
||||
db::PolygonSplitter splitter (pr, m_max_area_ratio, m_max_vertex_count);
|
||||
db::PolygonGenerator pg (splitter, true, true);
|
||||
ep.process (pg, op);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ class DB_PUBLIC BoolAndOrNotLocalOperation
|
|||
: public LocalOperation
|
||||
{
|
||||
public:
|
||||
BoolAndOrNotLocalOperation (bool is_and);
|
||||
BoolAndOrNotLocalOperation (bool is_and, double max_area_ratio = 0.0, size_t max_vertex_count = 0);
|
||||
|
||||
virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::unordered_set<db::PolygonRef> &result) const;
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const;
|
||||
|
|
@ -122,6 +122,8 @@ public:
|
|||
|
||||
private:
|
||||
bool m_is_and;
|
||||
double m_max_area_ratio;
|
||||
size_t m_max_vertex_count;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1662,7 +1662,7 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Return the number of points in the polygon
|
||||
* @brief Returns the number of points in the polygon
|
||||
*/
|
||||
size_t vertices () const
|
||||
{
|
||||
|
|
@ -1673,6 +1673,18 @@ public:
|
|||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the area ratio between the polygon's bounding box and actual area
|
||||
*
|
||||
* This number is a measure how well the polygon is approximated by the bounding box.
|
||||
* Values are bigger than 1 for well-formed polygons. Bigger values mean worse
|
||||
* approximation.
|
||||
*/
|
||||
double area_ratio () const
|
||||
{
|
||||
return double (box ().area ()) / double (area ());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The hull "begin" point iterator
|
||||
*
|
||||
|
|
@ -2956,6 +2968,18 @@ public:
|
|||
return m_hull.size ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the area ratio between the polygon's bounding box and actual area
|
||||
*
|
||||
* This number is a measure how well the polygon is approximated by the bounding box.
|
||||
* Values are bigger than 1 for well-formed polygons. Bigger values mean worse
|
||||
* approximation.
|
||||
*/
|
||||
double area_ratio () const
|
||||
{
|
||||
return double (box ().area ()) / double (area ());
|
||||
}
|
||||
|
||||
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const
|
||||
{
|
||||
db::mem_stat (stat, purpose, cat, m_hull, no_self, parent);
|
||||
|
|
|
|||
|
|
@ -288,3 +288,54 @@ TEST(5_BoolXOR)
|
|||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au5.gds");
|
||||
}
|
||||
|
||||
TEST(6_Reduction)
|
||||
{
|
||||
db::Layout ly;
|
||||
{
|
||||
std::string fn (tl::testsrc ());
|
||||
fn += "/testdata/algo/deep_region_l1.gds";
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly);
|
||||
}
|
||||
|
||||
db::cell_index_type top_cell_index = *ly.begin_top_down ();
|
||||
db::Cell &top_cell = ly.cell (top_cell_index);
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
dss.set_max_vertex_count (4);
|
||||
dss.set_threads (0);
|
||||
|
||||
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
|
||||
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
|
||||
unsigned int l42 = ly.get_layer (db::LayerProperties (42, 0));
|
||||
unsigned int lbox = ly.insert_layer ();
|
||||
|
||||
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
|
||||
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);
|
||||
db::Region r42 (db::RecursiveShapeIterator (ly, top_cell, l42), dss);
|
||||
|
||||
top_cell.shapes (lbox).insert (db::Box (2000, -1000, 6000, 4000));
|
||||
db::Region box (db::RecursiveShapeIterator (ly, top_cell, lbox), dss);
|
||||
|
||||
db::Region r2xor3 = r2 ^ r3;
|
||||
db::Region r2xorbox = r2 ^ box;
|
||||
db::Region r2xor42 = r2 ^ r42;
|
||||
db::Region rboxxor3 = box ^ r3;
|
||||
db::Region r42xor3 = r42 ^ r3;
|
||||
db::Region r42xor42 = r42 ^ r42;
|
||||
|
||||
db::Layout target;
|
||||
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r2xor3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2xorbox);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2xor42);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), rboxxor3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r42xor3);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r42xor42);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au6.gds");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1061,3 +1061,12 @@ TEST(BasicSelfOverlapWithSize10)
|
|||
run_test_bool_with_size (_this, "hlp10.oas", TMSelfOverlap, 150, 111);
|
||||
}
|
||||
|
||||
TEST(TopWithBelow1)
|
||||
{
|
||||
run_test_bool (_this, "hlp12.oas", TMNot, 100);
|
||||
}
|
||||
|
||||
TEST(TopWithBelow2)
|
||||
{
|
||||
run_test_bool (_this, "hlp12.oas", TMNotSwapped, 101);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ TEST(2)
|
|||
v = e.parse ("var b=B.new; b.bx(-1)").execute ();
|
||||
EXPECT_EQ (v.to_string (), std::string ("xz"));
|
||||
/*
|
||||
@@@ No detailed type analysis for ambiguity resolution so far:
|
||||
TODO: No detailed type analysis for ambiguity resolution so far:
|
||||
v = e.parse ("var b=B.new; b.bx('hello', 1)").execute ();
|
||||
EXPECT_EQ (v.to_string (), std::string ("20.5"));
|
||||
*/
|
||||
|
|
@ -297,10 +297,8 @@ TEST(2)
|
|||
v = e.parse ("b.amember_ref.a5(177)").execute ();
|
||||
EXPECT_EQ (v.to_string (), std::string ("nil"));
|
||||
|
||||
// @@@
|
||||
v = e.parse ("b.amember_or_nil(true)").execute ();
|
||||
EXPECT_EQ (v.to_string (), std::string ("A: 177"));
|
||||
// @@@
|
||||
|
||||
bool error = false;
|
||||
try {
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue