Defer DRC rule function eval to make use of short-circuit bools.

The lemon parser doesn't lend itself to short-circuiting booleans,
but if we defer processing until we fetch the second value when
processing the TR_OP_BOOLEAN opcode then we get to piggy-back on
C++'s boolean short-circuiting.
This commit is contained in:
Jeff Young 2021-08-21 15:24:20 +01:00
parent 1e23ce1c95
commit 048e13f423
2 changed files with 332 additions and 280 deletions

View File

@ -187,20 +187,23 @@ public:
VALUE() : VALUE() :
m_type( VT_UNDEFINED ), m_type( VT_UNDEFINED ),
m_valueDbl( 0 ), m_valueDbl( 0 ),
m_stringIsWildcard( false ) m_stringIsWildcard( false ),
m_isDeferredDbl( false )
{}; {};
VALUE( const wxString& aStr, bool aIsWildcard = false ) : VALUE( const wxString& aStr, bool aIsWildcard = false ) :
m_type( VT_STRING ), m_type( VT_STRING ),
m_valueDbl( 0 ), m_valueDbl( 0 ),
m_valueStr( aStr ), m_valueStr( aStr ),
m_stringIsWildcard( aIsWildcard ) m_stringIsWildcard( aIsWildcard ),
m_isDeferredDbl( false )
{}; {};
VALUE( const double aVal ) : VALUE( const double aVal ) :
m_type( VT_NUMERIC ), m_type( VT_NUMERIC ),
m_valueDbl( aVal ), m_valueDbl( aVal ),
m_stringIsWildcard( false ) m_stringIsWildcard( false ),
m_isDeferredDbl( false )
{}; {};
virtual ~VALUE() virtual ~VALUE()
@ -208,6 +211,12 @@ public:
virtual double AsDouble() const virtual double AsDouble() const
{ {
if( m_isDeferredDbl )
{
m_valueDbl = m_lambdaDbl();
m_isDeferredDbl = false;
}
return m_valueDbl; return m_valueDbl;
} }
@ -229,6 +238,13 @@ public:
m_valueDbl = aValue; m_valueDbl = aValue;
} }
void SetDeferredEval( std::function<double()> aLambda )
{
m_type = VT_NUMERIC;
m_lambdaDbl = aLambda;
m_isDeferredDbl = true;
}
void Set( const wxString& aValue ) void Set( const wxString& aValue )
{ {
m_type = VT_STRING; m_type = VT_STRING;
@ -246,9 +262,12 @@ public:
private: private:
VAR_TYPE_T m_type; VAR_TYPE_T m_type;
double m_valueDbl; mutable double m_valueDbl;
wxString m_valueStr; wxString m_valueStr;
bool m_stringIsWildcard; bool m_stringIsWildcard;
mutable bool m_isDeferredDbl;
std::function<double()> m_lambdaDbl;
}; };
class VAR_REF class VAR_REF

View File

@ -98,10 +98,13 @@ static void existsOnLayer( LIBEVAL::CONTEXT* aCtx, void *self )
return; return;
} }
result->SetDeferredEval(
[item, arg, &aCtx]() -> double
{
const wxString& layerName = arg->AsString(); const wxString& layerName = arg->AsString();
wxPGChoices& layerMap = ENUM_MAP<PCB_LAYER_ID>::Instance().Choices(); wxPGChoices& layerMap = ENUM_MAP<PCB_LAYER_ID>::Instance().Choices();
if( aCtx->HasErrorCallback() ) if( aCtx->HasErrorCallback())
{ {
/* /*
* Interpreted version * Interpreted version
@ -111,22 +114,22 @@ static void existsOnLayer( LIBEVAL::CONTEXT* aCtx, void *self )
for( unsigned ii = 0; ii < layerMap.GetCount(); ++ii ) for( unsigned ii = 0; ii < layerMap.GetCount(); ++ii )
{ {
wxPGChoiceEntry& entry = layerMap[ii]; wxPGChoiceEntry& entry = layerMap[ ii ];
if( entry.GetText().Matches( layerName ) ) if( entry.GetText().Matches( layerName ))
{ {
anyMatch = true; anyMatch = true;
if( item->IsOnLayer( ToLAYER_ID( entry.GetValue() ) ) ) if( item->IsOnLayer( ToLAYER_ID( entry.GetValue())))
{ return 1.0;
result->Set( 1.0 );
return;
}
} }
} }
if( !anyMatch ) if( !anyMatch )
aCtx->ReportError( wxString::Format( _( "Unrecognized layer '%s'" ), layerName ) ); {
aCtx->ReportError( wxString::Format( _( "Unrecognized layer '%s'" ),
layerName ) );
}
} }
else else
{ {
@ -143,7 +146,7 @@ static void existsOnLayer( LIBEVAL::CONTEXT* aCtx, void *self )
{ {
for( unsigned ii = 0; ii < layerMap.GetCount(); ++ii ) for( unsigned ii = 0; ii < layerMap.GetCount(); ++ii )
{ {
wxPGChoiceEntry& entry = layerMap[ii]; wxPGChoiceEntry& entry = layerMap[ ii ];
if( entry.GetText().Matches( layerName ) ) if( entry.GetText().Matches( layerName ) )
mask.set( ToLAYER_ID( entry.GetValue() ) ); mask.set( ToLAYER_ID( entry.GetValue() ) );
@ -157,8 +160,11 @@ static void existsOnLayer( LIBEVAL::CONTEXT* aCtx, void *self )
} }
if( ( item->GetLayerSet() & mask ).any() ) if( ( item->GetLayerSet() & mask ).any() )
result->Set( 1.0 ); return 1.0;
} }
return 0.0;
} );
} }
@ -183,7 +189,7 @@ static void isPlated( LIBEVAL::CONTEXT* aCtx, void* self )
static bool insideFootprintCourtyard( BOARD_ITEM* aItem, const EDA_RECT& aItemBBox, static bool insideFootprintCourtyard( BOARD_ITEM* aItem, const EDA_RECT& aItemBBox,
std::shared_ptr<SHAPE> aItemShape, PCB_EXPR_CONTEXT* aCtx, std::shared_ptr<SHAPE>& aItemShape, PCB_EXPR_CONTEXT* aCtx,
FOOTPRINT* aFootprint, PCB_LAYER_ID aSide = UNDEFINED_LAYER ) FOOTPRINT* aFootprint, PCB_LAYER_ID aSide = UNDEFINED_LAYER )
{ {
SHAPE_POLY_SET footprintCourtyard; SHAPE_POLY_SET footprintCourtyard;
@ -235,21 +241,14 @@ static void insideCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
if( !item ) if( !item )
return; return;
BOARD* board = item->GetBoard();
EDA_RECT itemBBox;
std::shared_ptr<SHAPE> shape;
if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
itemBBox = static_cast<ZONE*>( item )->GetCachedBoundingBox();
else
itemBBox = item->GetBoundingBox();
auto insideFootprint = auto insideFootprint =
[&]( FOOTPRINT* footprint ) -> bool [&context]( BOARD_ITEM* item, const EDA_RECT& itemBBox,
std::shared_ptr<SHAPE>& itemShape, FOOTPRINT* footprint ) -> bool
{ {
if( !footprint ) if( !footprint )
return false; return false;
BOARD* board = item->GetBoard();
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex ); std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
std::pair<BOARD_ITEM*, BOARD_ITEM*> key( footprint, item ); std::pair<BOARD_ITEM*, BOARD_ITEM*> key( footprint, item );
auto i = board->m_InsideCourtyardCache.find( key ); auto i = board->m_InsideCourtyardCache.find( key );
@ -257,21 +256,34 @@ static void insideCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
if( i != board->m_InsideCourtyardCache.end() ) if( i != board->m_InsideCourtyardCache.end() )
return i->second; return i->second;
bool res = insideFootprintCourtyard( item, itemBBox, shape, context, footprint ); bool res = insideFootprintCourtyard( item, itemBBox, itemShape, context,
footprint );
board->m_InsideCourtyardCache[ key ] = res; board->m_InsideCourtyardCache[ key ] = res;
return res; return res;
}; };
result->SetDeferredEval(
[item, arg, &context, &insideFootprint]() -> double
{
BOARD* board = item->GetBoard();
EDA_RECT itemBBox;
std::shared_ptr<SHAPE> itemShape;
if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
itemBBox = static_cast<ZONE*>( item )->GetCachedBoundingBox();
else
itemBBox = item->GetBoundingBox();
if( arg->AsString() == "A" ) if( arg->AsString() == "A" )
{ {
if( insideFootprint( dynamic_cast<FOOTPRINT*>( context->GetItem( 0 ) ) ) ) FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( context->GetItem( 0 ) );
result->Set( 1.0 ); return insideFootprint( item, itemBBox, itemShape, footprint ) ? 1.0 : 0.0;
} }
else if( arg->AsString() == "B" ) else if( arg->AsString() == "B" )
{ {
if( insideFootprint( dynamic_cast<FOOTPRINT*>( context->GetItem( 1 ) ) ) ) FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( context->GetItem( 1 ) );
result->Set( 1.0 ); return insideFootprint( item, itemBBox, itemShape, footprint ) ? 1.0 : 0.0;
} }
else else
{ {
@ -279,14 +291,14 @@ static void insideCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
{ {
if( candidate->GetReference().Matches( arg->AsString() ) ) if( candidate->GetReference().Matches( arg->AsString() ) )
{ {
if( insideFootprint( candidate ) ) if( insideFootprint( item, itemBBox, itemShape, candidate ) )
{ return 1.0;
result->Set( 1.0 );
return;
}
} }
} }
} }
return 0.0;
} );
} }
@ -316,21 +328,14 @@ static void insideFrontCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
if( !item ) if( !item )
return; return;
BOARD* board = item->GetBoard();
EDA_RECT itemBBox;
std::shared_ptr<SHAPE> shape;
if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
itemBBox = static_cast<ZONE*>( item )->GetCachedBoundingBox();
else
itemBBox = item->GetBoundingBox();
auto insideFootprint = auto insideFootprint =
[&]( FOOTPRINT* footprint ) -> bool [&context]( BOARD_ITEM* item, const EDA_RECT& itemBBox,
std::shared_ptr<SHAPE>& itemShape, FOOTPRINT* footprint ) -> bool
{ {
if( !footprint ) if( !footprint )
return false; return false;
BOARD* board = item->GetBoard();
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex ); std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
std::pair<BOARD_ITEM*, BOARD_ITEM*> key( footprint, item ); std::pair<BOARD_ITEM*, BOARD_ITEM*> key( footprint, item );
auto i = board->m_InsideFCourtyardCache.find( key ); auto i = board->m_InsideFCourtyardCache.find( key );
@ -338,22 +343,34 @@ static void insideFrontCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
if( i != board->m_InsideFCourtyardCache.end() ) if( i != board->m_InsideFCourtyardCache.end() )
return i->second; return i->second;
bool res = insideFootprintCourtyard( item, itemBBox, shape, context, footprint, bool res = insideFootprintCourtyard( item, itemBBox, itemShape, context,
F_Cu ); footprint, F_Cu );
board->m_InsideFCourtyardCache[ key ] = res; board->m_InsideFCourtyardCache[ key ] = res;
return res; return res;
}; };
result->SetDeferredEval(
[item, arg, &context, &insideFootprint]() -> double
{
BOARD* board = item->GetBoard();
EDA_RECT itemBBox;
std::shared_ptr<SHAPE> itemShape;
if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
itemBBox = static_cast<ZONE*>( item )->GetCachedBoundingBox();
else
itemBBox = item->GetBoundingBox();
if( arg->AsString() == "A" ) if( arg->AsString() == "A" )
{ {
if( insideFootprint( dynamic_cast<FOOTPRINT*>( context->GetItem( 0 ) ) ) ) FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( context->GetItem( 0 ) );
result->Set( 1.0 ); return insideFootprint( item, itemBBox, itemShape, footprint ) ? 1.0 : 0.0;
} }
else if( arg->AsString() == "B" ) else if( arg->AsString() == "B" )
{ {
if( insideFootprint( dynamic_cast<FOOTPRINT*>( context->GetItem( 1 ) ) ) ) FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( context->GetItem( 1 ) );
result->Set( 1.0 ); return insideFootprint( item, itemBBox, itemShape, footprint ) ? 1.0 : 0.0;
} }
else else
{ {
@ -361,14 +378,14 @@ static void insideFrontCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
{ {
if( candidate->GetReference().Matches( arg->AsString() ) ) if( candidate->GetReference().Matches( arg->AsString() ) )
{ {
if( insideFootprint( candidate ) ) if( insideFootprint( item, itemBBox, itemShape, candidate ) )
{ return 1.0;
result->Set( 1.0 );
return;
}
} }
} }
} }
return 0.0;
} );
} }
@ -397,21 +414,14 @@ static void insideBackCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
if( !item ) if( !item )
return; return;
BOARD* board = item->GetBoard();
EDA_RECT itemBBox;
std::shared_ptr<SHAPE> shape;
if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
itemBBox = static_cast<ZONE*>( item )->GetCachedBoundingBox();
else
itemBBox = item->GetBoundingBox();
auto insideFootprint = auto insideFootprint =
[&]( FOOTPRINT* footprint ) -> bool [&context]( BOARD_ITEM* item, const EDA_RECT& itemBBox,
std::shared_ptr<SHAPE>& itemShape, FOOTPRINT* footprint ) -> bool
{ {
if( !footprint ) if( !footprint )
return false; return false;
BOARD* board = item->GetBoard();
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex ); std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
std::pair<BOARD_ITEM*, BOARD_ITEM*> key( footprint, item ); std::pair<BOARD_ITEM*, BOARD_ITEM*> key( footprint, item );
auto i = board->m_InsideBCourtyardCache.find( key ); auto i = board->m_InsideBCourtyardCache.find( key );
@ -419,22 +429,34 @@ static void insideBackCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
if( i != board->m_InsideBCourtyardCache.end() ) if( i != board->m_InsideBCourtyardCache.end() )
return i->second; return i->second;
bool res = insideFootprintCourtyard( item, itemBBox, shape, context, footprint, bool res = insideFootprintCourtyard( item, itemBBox, itemShape, context,
B_Cu ); footprint, B_Cu );
board->m_InsideBCourtyardCache[ key ] = res; board->m_InsideBCourtyardCache[ key ] = res;
return res; return res;
}; };
result->SetDeferredEval(
[item, arg, &context, &insideFootprint]() -> double
{
BOARD* board = item->GetBoard();
EDA_RECT itemBBox;
std::shared_ptr<SHAPE> itemShape;
if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
itemBBox = static_cast<ZONE*>( item )->GetCachedBoundingBox();
else
itemBBox = item->GetBoundingBox();
if( arg->AsString() == "A" ) if( arg->AsString() == "A" )
{ {
if( insideFootprint( dynamic_cast<FOOTPRINT*>( context->GetItem( 0 ) ) ) ) FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( context->GetItem( 0 ) );
result->Set( 1.0 ); return insideFootprint( item, itemBBox, itemShape, footprint ) ? 1.0 : 0.0;
} }
else if( arg->AsString() == "B" ) else if( arg->AsString() == "B" )
{ {
if( insideFootprint( dynamic_cast<FOOTPRINT*>( context->GetItem( 1 ) ) ) ) FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( context->GetItem( 1 ) );
result->Set( 1.0 ); return insideFootprint( item, itemBBox, itemShape, footprint ) ? 1.0 : 0.0;
} }
else else
{ {
@ -442,14 +464,14 @@ static void insideBackCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
{ {
if( candidate->GetReference().Matches( arg->AsString() ) ) if( candidate->GetReference().Matches( arg->AsString() ) )
{ {
if( insideFootprint( candidate ) ) if( insideFootprint( item, itemBBox, itemShape, candidate ) )
{ return 1.0;
result->Set( 1.0 );
return;
}
} }
} }
} }
return 0.0;
} );
} }
@ -479,19 +501,12 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
if( !item ) if( !item )
return; return;
BOARD* board = item->GetBoard(); auto itemIsInsideArea =
BOARD_DESIGN_SETTINGS& bds = board->GetDesignSettings(); [&context]( BOARD_ITEM* item, ZONE* area, const EDA_RECT& itemBBox ) -> bool
EDA_RECT itemBBox; {
BOARD* board = area->GetBoard();
std::shared_ptr<SHAPE> shape; std::shared_ptr<SHAPE> shape;
if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
itemBBox = static_cast<ZONE*>( item )->GetCachedBoundingBox();
else
itemBBox = item->GetBoundingBox();
auto itemIsInsideArea =
[&]( ZONE* area ) -> bool
{
if( !area->GetCachedBoundingBox().Intersects( itemBBox ) ) if( !area->GetCachedBoundingBox().Intersects( itemBBox ) )
return false; return false;
@ -499,7 +514,8 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
// exclude touching. This is particularly important for detecting copper fills // exclude touching. This is particularly important for detecting copper fills
// as they will be exactly touching along the entire border. // as they will be exactly touching along the entire border.
SHAPE_POLY_SET areaOutline = *area->Outline(); SHAPE_POLY_SET areaOutline = *area->Outline();
areaOutline.Deflate( bds.GetDRCEpsilon(), 0, SHAPE_POLY_SET::ALLOW_ACUTE_CORNERS ); areaOutline.Deflate( board->GetDesignSettings().GetDRCEpsilon(), 0,
SHAPE_POLY_SET::ALLOW_ACUTE_CORNERS );
if( item->GetFlags() & HOLE_PROXY ) if( item->GetFlags() & HOLE_PROXY )
{ {
@ -527,8 +543,11 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
if( ( footprint->GetFlags() & MALFORMED_COURTYARDS ) != 0 ) if( ( footprint->GetFlags() & MALFORMED_COURTYARDS ) != 0 )
{ {
if( aCtx->HasErrorCallback() ) if( context->HasErrorCallback() )
aCtx->ReportError( _( "Footprint's courtyard is not a single, closed shape." ) ); {
context->ReportError( _( "Footprint's courtyard is not a single, "
"closed shape." ) );
}
return false; return false;
} }
@ -539,8 +558,8 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
if( courtyard.OutlineCount() == 0 ) if( courtyard.OutlineCount() == 0 )
{ {
if( aCtx->HasErrorCallback() ) if( context->HasErrorCallback() )
aCtx->ReportError( _( "Footprint has no front courtyard." ) ); context->ReportError( _( "Footprint has no front courtyard." ) );
return false; return false;
} }
@ -556,8 +575,8 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
if( courtyard.OutlineCount() == 0 ) if( courtyard.OutlineCount() == 0 )
{ {
if( aCtx->HasErrorCallback() ) if( context->HasErrorCallback() )
aCtx->ReportError( _( "Footprint has no back courtyard." ) ); context->ReportError( _( "Footprint has no back courtyard." ) );
return false; return false;
} }
@ -602,11 +621,12 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
}; };
auto checkArea = auto checkArea =
[&]( ZONE* area ) -> bool [&itemIsInsideArea]( BOARD_ITEM* item, const EDA_RECT& itemBBox, ZONE* area ) -> bool
{ {
if( !area || area == item || area->GetParent() == item ) if( !area || area == item || area->GetParent() == item )
return false; return false;
BOARD* board = area->GetBoard();
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex ); std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
std::pair<BOARD_ITEM*, BOARD_ITEM*> key( area, item ); std::pair<BOARD_ITEM*, BOARD_ITEM*> key( area, item );
auto i = board->m_InsideAreaCache.find( key ); auto i = board->m_InsideAreaCache.find( key );
@ -614,67 +634,67 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
if( i != board->m_InsideAreaCache.end() ) if( i != board->m_InsideAreaCache.end() )
return i->second; return i->second;
bool isInside = itemIsInsideArea( area ); bool isInside = itemIsInsideArea( item, area, itemBBox );
board->m_InsideAreaCache[ key ] = isInside; board->m_InsideAreaCache[ key ] = isInside;
return isInside; return isInside;
}; };
result->SetDeferredEval(
[item, arg, &context, &checkArea]() -> double
{
BOARD* board = item->GetBoard();
EDA_RECT itemBBox;
if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
itemBBox = static_cast<ZONE*>( item )->GetCachedBoundingBox();
else
itemBBox = item->GetBoundingBox();
if( arg->AsString() == "A" ) if( arg->AsString() == "A" )
{ {
if( checkArea( dynamic_cast<ZONE*>( context->GetItem( 0 ) ) ) ) ZONE* zone = dynamic_cast<ZONE*>( context->GetItem( 0 ) );
result->Set( 1.0 ); return checkArea( item, itemBBox, zone ) ? 1.0 : 0.0;
} }
else if( arg->AsString() == "B" ) else if( arg->AsString() == "B" )
{ {
if( checkArea( dynamic_cast<ZONE*>( context->GetItem( 1 ) ) ) ) ZONE* zone = dynamic_cast<ZONE*>( context->GetItem( 1 ) );
result->Set( 1.0 ); return checkArea( item, itemBBox, zone ) ? 1.0 : 0.0;
} }
else if( KIID::SniffTest( arg->AsString() ) ) else if( KIID::SniffTest( arg->AsString() ) )
{ {
KIID target( arg->AsString() ); KIID target( arg->AsString());
for( ZONE* area : board->Zones() ) for( ZONE* area : board->Zones() )
{ {
// Only a single zone can match the UUID; exit once we find a match whether // Only a single zone can match the UUID; exit once we find a match whether
// "inside" or not // "inside" or not
if( area->m_Uuid == target ) if( area->m_Uuid == target )
{ return checkArea( item, itemBBox, area ) ? 1.0 : 0.0;
if( checkArea( area ) )
result->Set( 1.0 );
return;
}
} }
for( FOOTPRINT* footprint : board->Footprints() ) for( FOOTPRINT* footprint : board->Footprints() )
{ {
for( ZONE* area : footprint->Zones() ) for( ZONE* area : footprint->Zones() )
{ {
// Only a single zone can match the UUID; exit once we find a match whether // Only a single zone can match the UUID; exit once we find a match
// "inside" or not // whether "inside" or not
if( area->m_Uuid == target ) if( area->m_Uuid == target )
{ return checkArea( item, itemBBox, area ) ? 1.0 : 0.0;
if( checkArea( area ) ) }
result->Set( 1.0 ); }
return; return 0.0;
}
}
}
} }
else // Match on zone name else // Match on zone name
{ {
for( ZONE* area : board->Zones() ) for( ZONE* area : board->Zones())
{ {
if( area->GetZoneName().Matches( arg->AsString() ) ) if( area->GetZoneName().Matches( arg->AsString() ) )
{ {
// Many zones can match the name; exit only when we find an "inside" // Many zones can match the name; exit only when we find an "inside"
if( checkArea( area ) ) if( checkArea( item, itemBBox, area ) )
{ return 1.0;
result->Set( 1.0 );
return;
}
} }
} }
@ -685,15 +705,15 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
// Many zones can match the name; exit only when we find an "inside" // Many zones can match the name; exit only when we find an "inside"
if( area->GetZoneName().Matches( arg->AsString() ) ) if( area->GetZoneName().Matches( arg->AsString() ) )
{ {
if( checkArea( area ) ) if( checkArea( item, itemBBox, area ) )
{ return 1.0;
result->Set( 1.0 );
return;
}
} }
} }
} }
return 0.0;
} }
} );
} }
@ -721,6 +741,9 @@ static void memberOf( LIBEVAL::CONTEXT* aCtx, void* self )
if( !item ) if( !item )
return; return;
result->SetDeferredEval(
[item, arg]() -> double
{
PCB_GROUP* group = item->GetParentGroup(); PCB_GROUP* group = item->GetParentGroup();
if( !group && item->GetParent() && item->GetParent()->Type() == PCB_FOOTPRINT_T ) if( !group && item->GetParent() && item->GetParent()->Type() == PCB_FOOTPRINT_T )
@ -729,13 +752,13 @@ static void memberOf( LIBEVAL::CONTEXT* aCtx, void* self )
while( group ) while( group )
{ {
if( group->GetName().Matches( arg->AsString() ) ) if( group->GetName().Matches( arg->AsString() ) )
{ return 1.0;
result->Set( 1.0 );
return;
}
group = group->GetParentGroup(); group = group->GetParentGroup();
} }
return 0.0;
} );
} }
@ -781,17 +804,24 @@ static void isCoupledDiffPair( LIBEVAL::CONTEXT* aCtx, void* self )
result->Set( 0.0 ); result->Set( 0.0 );
aCtx->Push( result ); aCtx->Push( result );
result->SetDeferredEval(
[a, b]() -> double
{
if( a && b ) if( a && b )
{ {
NETINFO_ITEM* netinfo = a->GetNet(); NETINFO_ITEM* netinfo = a->GetNet();
wxString coupledNet, dummy; wxString coupledNet, dummy;
if( netinfo && DRC_ENGINE::MatchDpSuffix( netinfo->GetNetname(), coupledNet, dummy ) != 0 ) if( netinfo
&& DRC_ENGINE::MatchDpSuffix( netinfo->GetNetname(), coupledNet, dummy )
&& b->GetNetname() == coupledNet )
{ {
if( b->GetNetname() == coupledNet ) return 1.0;
result->Set( 1.0 );
} }
} }
return 0.0;
} );
} }
@ -805,6 +835,9 @@ static void inDiffPair( LIBEVAL::CONTEXT* aCtx, void* self )
result->Set( 0.0 ); result->Set( 0.0 );
aCtx->Push( result ); aCtx->Push( result );
if( !item || !item->GetBoard() )
return;
if( !arg ) if( !arg )
{ {
if( aCtx->HasErrorCallback() ) if( aCtx->HasErrorCallback() )
@ -816,27 +849,27 @@ static void inDiffPair( LIBEVAL::CONTEXT* aCtx, void* self )
return; return;
} }
result->SetDeferredEval(
[item, arg]() -> double
{
if( item && item->IsConnected() ) if( item && item->IsConnected() )
{ {
NETINFO_ITEM* netinfo = static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNet(); NETINFO_ITEM* netinfo = static_cast<BOARD_CONNECTED_ITEM*>( item )->GetNet();
wxString refName = netinfo->GetNetname(); wxString refName = netinfo->GetNetname();
wxString baseName, coupledNet; wxString baseName, coupledNet;
int polarity = DRC_ENGINE::MatchDpSuffix( refName, coupledNet, baseName ); int polarity = DRC_ENGINE::MatchDpSuffix( refName, coupledNet, baseName );
if( polarity == 0 ) if( polarity != 0
return; && item->GetBoard()->FindNet( coupledNet )
&& baseName.Matches( arg->AsString() ) )
if( BOARD* board = item->GetBoard() )
{ {
if( !board->FindNet( coupledNet ) ) return 1.0;
return; }
} }
if( baseName.Matches( arg->AsString() ) ) return 0.0;
result->Set( 1.0 ); } );
}
} }