Tag geometry-dependent DRC functions at registration

The geometry-dependent function set in CreateFuncCall was a
hardcoded copy of names that had to be manually synchronized
with RegisterAllFunctions. Adding a new geometry-dependent
function without updating both lists would silently skip
per-segment DRC evaluation for rules using that function.

Add an isGeometryDependent flag to RegisterFunc and query it
from CreateFuncCall so there is a single source of truth.
This commit is contained in:
Seth Hillbrand
2026-02-27 19:13:03 -08:00
parent d3d2f0e0dd
commit 8dce8aa786
3 changed files with 28 additions and 25 deletions
+3 -11
View File
@@ -530,21 +530,13 @@ LIBEVAL::VALUE* PCBEXPR_TYPE_REF::GetValue( LIBEVAL::CONTEXT* aCtx )
LIBEVAL::FUNC_CALL_REF PCBEXPR_UCODE::CreateFuncCall( const wxString& aName )
{
static const std::set<wxString> geometryFunctions = {
wxT( "intersectscourtyard" ), wxT( "intersectsfrontcourtyard" ),
wxT( "intersectsbackcourtyard" ), wxT( "intersectsarea" ),
wxT( "enclosedbyarea" ),
wxT( "insidecourtyard" ), wxT( "insidefrontcourtyard" ),
wxT( "insidebackcourtyard" ), wxT( "insidearea" )
};
wxString nameLower = aName.Lower();
if( geometryFunctions.count( nameLower ) )
m_hasGeometryDependentFunctions = true;
PCBEXPR_BUILTIN_FUNCTIONS& registry = PCBEXPR_BUILTIN_FUNCTIONS::Instance();
if( registry.IsGeometryDependent( nameLower ) )
m_hasGeometryDependentFunctions = true;
return registry.Get( nameLower );
}
+14 -2
View File
@@ -25,6 +25,7 @@
#ifndef PCBEXPR_EVALUATOR_H
#define PCBEXPR_EVALUATOR_H
#include <set>
#include <unordered_map>
#include <layer_ids.h>
@@ -195,22 +196,33 @@ public:
return m_funcs[ name ];
}
bool IsGeometryDependent( const wxString& name ) const
{
return m_geometryDependentFuncs.count( name ) > 0;
}
const wxArrayString GetSignatures() const
{
return m_funcSigs;
}
void RegisterFunc( const wxString& funcSignature, LIBEVAL::FUNC_CALL_REF funcPtr )
void RegisterFunc( const wxString& funcSignature, LIBEVAL::FUNC_CALL_REF funcPtr,
bool aIsGeometryDependent = false )
{
wxString funcName = funcSignature.BeforeFirst( '(' );
m_funcs[std::string( funcName.Lower() )] = std::move( funcPtr );
wxString lower = funcName.Lower();
m_funcs[std::string( lower )] = std::move( funcPtr );
m_funcSigs.Add( funcSignature );
if( aIsGeometryDependent )
m_geometryDependentFuncs.insert( lower );
}
void RegisterAllFunctions();
private:
std::map<wxString, LIBEVAL::FUNC_CALL_REF> m_funcs;
std::set<wxString> m_geometryDependentFuncs;
wxArrayString m_funcSigs;
};
+11 -12
View File
@@ -1505,19 +1505,18 @@ void PCBEXPR_BUILTIN_FUNCTIONS::RegisterAllFunctions()
RegisterFunc( wxT( "isPlated()" ), isPlatedFunc );
// When adding new geometry-dependent functions (functions whose result depends on item
// position/shape rather than item properties), also add the function name to the
// geometryFunctions set in PCBEXPR_UCODE::CreateFuncCall() (pcbexpr_evaluator.cpp).
RegisterFunc( wxT( "insideCourtyard('x') DEPRECATED" ), intersectsCourtyardFunc );
RegisterFunc( wxT( "insideFrontCourtyard('x') DEPRECATED" ), intersectsFrontCourtyardFunc );
RegisterFunc( wxT( "insideBackCourtyard('x') DEPRECATED" ), intersectsBackCourtyardFunc );
RegisterFunc( wxT( "intersectsCourtyard('x')" ), intersectsCourtyardFunc );
RegisterFunc( wxT( "intersectsFrontCourtyard('x')" ), intersectsFrontCourtyardFunc );
RegisterFunc( wxT( "intersectsBackCourtyard('x')" ), intersectsBackCourtyardFunc );
// Geometry-dependent functions depend on item position/shape rather than item properties.
// The third argument marks them so that CreateFuncCall() can detect them automatically.
RegisterFunc( wxT( "insideCourtyard('x') DEPRECATED" ), intersectsCourtyardFunc, true );
RegisterFunc( wxT( "insideFrontCourtyard('x') DEPRECATED" ), intersectsFrontCourtyardFunc, true );
RegisterFunc( wxT( "insideBackCourtyard('x') DEPRECATED" ), intersectsBackCourtyardFunc, true );
RegisterFunc( wxT( "intersectsCourtyard('x')" ), intersectsCourtyardFunc, true );
RegisterFunc( wxT( "intersectsFrontCourtyard('x')" ), intersectsFrontCourtyardFunc, true );
RegisterFunc( wxT( "intersectsBackCourtyard('x')" ), intersectsBackCourtyardFunc, true );
RegisterFunc( wxT( "insideArea('x') DEPRECATED" ), intersectsAreaFunc );
RegisterFunc( wxT( "intersectsArea('x')" ), intersectsAreaFunc );
RegisterFunc( wxT( "enclosedByArea('x')" ), enclosedByAreaFunc );
RegisterFunc( wxT( "insideArea('x') DEPRECATED" ), intersectsAreaFunc, true );
RegisterFunc( wxT( "intersectsArea('x')" ), intersectsAreaFunc, true );
RegisterFunc( wxT( "enclosedByArea('x')" ), enclosedByAreaFunc, true );
RegisterFunc( wxT( "isMicroVia()" ), isMicroVia );
RegisterFunc( wxT( "isBlindVia()" ), isBlindVia );