Fix source comment/doc typos (follow-up)
Found via `codespell -q 3 -S *.po,./thirdparty -L aactual,acount,aline,alocation,alog,anormal,anumber,aother,apoints,aparent,aray,dout,einstance,modul,ot,overide,serie,te,,tesselate,tesselator,tht` 4 years ago |
|
/*
* This program source code file is part of KiCad, a free EDA CAD application. * * Copyright The KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you may find one here: * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
#include <cstdio>
#include <memory>
#include <mutex>
#include <board.h>
#include <footprint.h>
#include <lset.h>
#include <board_connected_item.h>
#include <pcbexpr_evaluator.h>
#include <drc/drc_engine.h>
#include <component_classes/component_class.h>
/* --------------------------------------------------------------------------------------------
* Specialized Expression References */
BOARD_ITEM* PCBEXPR_VAR_REF::GetObject( const LIBEVAL::CONTEXT* aCtx ) const{ wxASSERT( dynamic_cast<const PCBEXPR_CONTEXT*>( aCtx ) );
const PCBEXPR_CONTEXT* ctx = static_cast<const PCBEXPR_CONTEXT*>( aCtx ); BOARD_ITEM* item = ctx->GetItem( m_itemIndex ); return item;}
class PCBEXPR_LAYER_VALUE : public LIBEVAL::VALUE{public: PCBEXPR_LAYER_VALUE( PCB_LAYER_ID aLayer ) : LIBEVAL::VALUE( LayerName( aLayer ) ), m_layer( aLayer ) {};
virtual bool EqualTo( LIBEVAL::CONTEXT* aCtx, const VALUE* b ) const override { // For boards with user-defined layer names there will be 2 entries for each layer
// in the ENUM_MAP: one for the canonical layer name and one for the user layer name.
// We need to check against both.
wxPGChoices& layerMap = ENUM_MAP<PCB_LAYER_ID>::Instance().Choices(); const wxString& layerName = b->AsString(); BOARD* board = static_cast<PCBEXPR_CONTEXT*>( aCtx )->GetBoard();
{ std::shared_lock<std::shared_mutex> readLock( board->m_CachesMutex );
auto i = board->m_LayerExpressionCache.find( layerName );
if( i != board->m_LayerExpressionCache.end() ) return i->second.Contains( m_layer ); }
LSET mask;
for( unsigned ii = 0; ii < layerMap.GetCount(); ++ii ) { wxPGChoiceEntry& entry = layerMap[ii];
if( entry.GetText().Matches( layerName ) ) mask.set( ToLAYER_ID( entry.GetValue() ) ); }
{ std::unique_lock<std::shared_mutex> writeLock( board->m_CachesMutex ); board->m_LayerExpressionCache[ layerName ] = mask; }
return mask.Contains( m_layer ); }
protected: PCB_LAYER_ID m_layer;};
class PCBEXPR_PINTYPE_VALUE : public LIBEVAL::VALUE{public: PCBEXPR_PINTYPE_VALUE( const wxString& aPinTypeName ) : LIBEVAL::VALUE( aPinTypeName ) {};
bool EqualTo( LIBEVAL::CONTEXT* aCtx, const VALUE* b ) const override { const wxString& thisStr = AsString(); const wxString& otherStr = b->AsString();
// Case insensitive
if( thisStr.IsSameAs( otherStr, false ) ) return true;
// Wildcards
if( thisStr.Matches( otherStr ) ) return true;
// Handle cases where the netlist token is different from the EEschema token
wxString altStr;
if( thisStr == wxT( "tri_state" ) ) altStr = wxT( "Tri-state" ); else if( thisStr == wxT( "power_in" ) ) altStr = wxT( "Power input" ); else if( thisStr == wxT( "power_out" ) ) altStr = wxT( "Power output" ); else if( thisStr == wxT( "no_connect" ) ) altStr = wxT( "Unconnected" );
if( !altStr.IsEmpty() ) { // Case insensitive
if( altStr.IsSameAs( otherStr, false ) ) return true;
// Wildcards
if( altStr.Matches( otherStr ) ) return true; }
return false; }};
class PCBEXPR_NETCLASS_VALUE : public LIBEVAL::VALUE{public: PCBEXPR_NETCLASS_VALUE( BOARD_CONNECTED_ITEM* aItem ) : LIBEVAL::VALUE( wxEmptyString ), m_item( aItem ) {};
const wxString& AsString() const override { const_cast<PCBEXPR_NETCLASS_VALUE*>( this )->Set( m_item->GetEffectiveNetClass()->GetName() ); return LIBEVAL::VALUE::AsString(); }
bool EqualTo( LIBEVAL::CONTEXT* aCtx, const VALUE* b ) const override { if( const PCBEXPR_NETCLASS_VALUE* bValue = dynamic_cast<const PCBEXPR_NETCLASS_VALUE*>( b ) ) { return *( m_item->GetEffectiveNetClass() ) == *( bValue->m_item->GetEffectiveNetClass() ); }
if( b->GetType() == LIBEVAL::VT_STRING ) { if( m_item->GetEffectiveNetClass()->ContainsNetclassWithName( b->AsString() ) ) return true;
return m_item->GetEffectiveNetClass()->GetName() == b->AsString(); }
return LIBEVAL::VALUE::EqualTo( aCtx, b ); }
bool NotEqualTo( LIBEVAL::CONTEXT* aCtx, const LIBEVAL::VALUE* b ) const override { if( const PCBEXPR_NETCLASS_VALUE* bValue = dynamic_cast<const PCBEXPR_NETCLASS_VALUE*>( b ) ) { return *( m_item->GetEffectiveNetClass() ) != *( bValue->m_item->GetEffectiveNetClass() ); }
if( b->GetType() == LIBEVAL::VT_STRING ) { const bool isInConstituents = m_item->GetEffectiveNetClass()->ContainsNetclassWithName( b->AsString() ); const bool isFullName = m_item->GetEffectiveNetClass()->GetName() == b->AsString();
return !isInConstituents && !isFullName; }
return LIBEVAL::VALUE::NotEqualTo( aCtx, b ); }
protected: BOARD_CONNECTED_ITEM* m_item;};
class PCBEXPR_COMPONENT_CLASS_VALUE : public LIBEVAL::VALUE{public: PCBEXPR_COMPONENT_CLASS_VALUE( BOARD_ITEM* aItem ) : LIBEVAL::VALUE( wxEmptyString ), m_item( dynamic_cast<FOOTPRINT*>( aItem ) ) {};
const wxString& AsString() const override { if( !m_item ) return LIBEVAL::VALUE::AsString();
if( const COMPONENT_CLASS* compClass = m_item->GetComponentClass() ) const_cast<PCBEXPR_COMPONENT_CLASS_VALUE*>( this )->Set( compClass->GetName() );
return LIBEVAL::VALUE::AsString(); }
bool EqualTo( LIBEVAL::CONTEXT* aCtx, const VALUE* b ) const override { if( const PCBEXPR_COMPONENT_CLASS_VALUE* bValue = dynamic_cast<const PCBEXPR_COMPONENT_CLASS_VALUE*>( b ) ) { if( !m_item || !bValue->m_item ) return LIBEVAL::VALUE::EqualTo( aCtx, b );
const COMPONENT_CLASS* aClass = m_item->GetComponentClass(); const COMPONENT_CLASS* bClass = bValue->m_item->GetComponentClass();
return *aClass == *bClass; }
if( b->GetType() == LIBEVAL::VT_STRING ) { if( m_item->GetComponentClass()->ContainsClassName( b->AsString() ) ) return true;
return m_item->GetComponentClass()->GetName() == b->AsString(); }
return LIBEVAL::VALUE::EqualTo( aCtx, b ); }
bool NotEqualTo( LIBEVAL::CONTEXT* aCtx, const LIBEVAL::VALUE* b ) const override { if( const PCBEXPR_COMPONENT_CLASS_VALUE* bValue = dynamic_cast<const PCBEXPR_COMPONENT_CLASS_VALUE*>( b ) ) { if( !m_item || !bValue->m_item ) return LIBEVAL::VALUE::NotEqualTo( aCtx, b );
const COMPONENT_CLASS* aClass = m_item->GetComponentClass(); const COMPONENT_CLASS* bClass = bValue->m_item->GetComponentClass();
return *aClass != *bClass; }
if( b->GetType() == LIBEVAL::VT_STRING ) { const bool isInConstituents = m_item->GetComponentClass()->ContainsClassName( b->AsString() ); const bool isFullName = m_item->GetComponentClass()->GetName() == b->AsString();
return !isInConstituents && !isFullName; }
return LIBEVAL::VALUE::NotEqualTo( aCtx, b ); }
protected: FOOTPRINT* m_item;};
class PCBEXPR_NET_VALUE : public LIBEVAL::VALUE{public: PCBEXPR_NET_VALUE( BOARD_CONNECTED_ITEM* aItem ) : LIBEVAL::VALUE( wxEmptyString ), m_item( aItem ) {};
const wxString& AsString() const override { const_cast<PCBEXPR_NET_VALUE*>( this )->Set( m_item->GetNetname() ); return LIBEVAL::VALUE::AsString(); }
bool EqualTo( LIBEVAL::CONTEXT* aCtx, const VALUE* b ) const override { if( const PCBEXPR_NET_VALUE* bValue = dynamic_cast<const PCBEXPR_NET_VALUE*>( b ) ) return m_item->GetNetCode() == bValue->m_item->GetNetCode(); else return LIBEVAL::VALUE::EqualTo( aCtx, b ); }
bool NotEqualTo( LIBEVAL::CONTEXT* aCtx, const LIBEVAL::VALUE* b ) const override { if( const PCBEXPR_NET_VALUE* bValue = dynamic_cast<const PCBEXPR_NET_VALUE*>( b ) ) return m_item->GetNetCode() != bValue->m_item->GetNetCode(); else return LIBEVAL::VALUE::NotEqualTo( aCtx, b ); }
protected: BOARD_CONNECTED_ITEM* m_item;};
LIBEVAL::VALUE* PCBEXPR_VAR_REF::GetValue( LIBEVAL::CONTEXT* aCtx ){ PCBEXPR_CONTEXT* context = static_cast<PCBEXPR_CONTEXT*>( aCtx );
if( m_type == LIBEVAL::VT_NULL ) return LIBEVAL::VALUE::MakeNullValue();
if( m_itemIndex == 2 ) return new PCBEXPR_LAYER_VALUE( context->GetLayer() );
BOARD_ITEM* item = GetObject( aCtx );
if( !item ) return new LIBEVAL::VALUE();
auto it = m_matchingTypes.find( TYPE_HASH( *item ) );
if( it == m_matchingTypes.end() ) { // Don't force user to type "A.Type == 'via' && A.Via_Type == 'buried'" when the
// simpler "A.Via_Type == 'buried'" is perfectly clear. Instead, return an undefined
// value when the property doesn't appear on a particular object.
return new LIBEVAL::VALUE(); } else { if( m_type == LIBEVAL::VT_NUMERIC ) { if( m_isOptional ) { auto val = item->Get<std::optional<int>>( it->second );
if( val.has_value() ) return new LIBEVAL::VALUE( static_cast<double>( val.value() ) );
return LIBEVAL::VALUE::MakeNullValue(); }
return new LIBEVAL::VALUE( static_cast<double>( item->Get<int>( it->second ) ) ); } else if( m_type == LIBEVAL::VT_NUMERIC_DOUBLE ) { if( m_isOptional ) { auto val = item->Get<std::optional<double>>( it->second );
if( val.has_value() ) return new LIBEVAL::VALUE( val.value() );
return LIBEVAL::VALUE::MakeNullValue(); }
return new LIBEVAL::VALUE( item->Get<double>( it->second ) ); } else { wxString str;
if( !m_isEnum ) { str = item->Get<wxString>( it->second );
if( it->second->Name() == wxT( "Pin Type" ) ) return new PCBEXPR_PINTYPE_VALUE( str ); else return new LIBEVAL::VALUE( str ); } else { const wxAny& any = item->Get( it->second ); PCB_LAYER_ID layer;
if( it->second->Name() == wxT( "Layer" ) || it->second->Name() == wxT( "Layer Top" ) || it->second->Name() == wxT( "Layer Bottom" ) ) { if( any.GetAs<PCB_LAYER_ID>( &layer ) ) return new PCBEXPR_LAYER_VALUE( layer ); else if( any.GetAs<wxString>( &str ) ) return new PCBEXPR_LAYER_VALUE( context->GetBoard()->GetLayerID( str ) ); } else { if( any.GetAs<wxString>( &str ) ) return new LIBEVAL::VALUE( str ); } }
return new LIBEVAL::VALUE(); } }}
LIBEVAL::VALUE* PCBEXPR_NETCLASS_REF::GetValue( LIBEVAL::CONTEXT* aCtx ){ BOARD_CONNECTED_ITEM* item = dynamic_cast<BOARD_CONNECTED_ITEM*>( GetObject( aCtx ) );
if( !item ) return new LIBEVAL::VALUE();
return new PCBEXPR_NETCLASS_VALUE( item );}
LIBEVAL::VALUE* PCBEXPR_COMPONENT_CLASS_REF::GetValue( LIBEVAL::CONTEXT* aCtx ){ BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( GetObject( aCtx ) );
if( !item || item->Type() != PCB_FOOTPRINT_T ) return new LIBEVAL::VALUE();
return new PCBEXPR_COMPONENT_CLASS_VALUE( item );}
LIBEVAL::VALUE* PCBEXPR_NETNAME_REF::GetValue( LIBEVAL::CONTEXT* aCtx ){ BOARD_CONNECTED_ITEM* item = dynamic_cast<BOARD_CONNECTED_ITEM*>( GetObject( aCtx ) );
if( !item ) return new LIBEVAL::VALUE();
return new PCBEXPR_NET_VALUE( item );}
LIBEVAL::VALUE* PCBEXPR_TYPE_REF::GetValue( LIBEVAL::CONTEXT* aCtx ){ BOARD_ITEM* item = GetObject( aCtx );
if( !item ) return new LIBEVAL::VALUE();
return new LIBEVAL::VALUE( ENUM_MAP<KICAD_T>::Instance().ToString( item->Type() ) );}
LIBEVAL::FUNC_CALL_REF PCBEXPR_UCODE::CreateFuncCall( const wxString& aName ){ PCBEXPR_BUILTIN_FUNCTIONS& registry = PCBEXPR_BUILTIN_FUNCTIONS::Instance();
return registry.Get( aName.Lower() );}
std::unique_ptr<LIBEVAL::VAR_REF> PCBEXPR_UCODE::CreateVarRef( const wxString& aVar, const wxString& aField ){ PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); std::unique_ptr<PCBEXPR_VAR_REF> vref;
if( aVar.IsSameAs( wxT( "null" ), false ) ) { vref = std::make_unique<PCBEXPR_VAR_REF>( 0 ); vref->SetType( LIBEVAL::VT_NULL ); return vref; }
// Check for a couple of very common cases and compile them straight to "object code".
if( aField.CmpNoCase( wxT( "NetClass" ) ) == 0 ) { if( aVar == wxT( "A" ) ) return std::make_unique<PCBEXPR_NETCLASS_REF>( 0 ); else if( aVar == wxT( "B" ) ) return std::make_unique<PCBEXPR_NETCLASS_REF>( 1 ); else return nullptr; } else if( aField.CmpNoCase( wxT( "ComponentClass" ) ) == 0 ) { if( aVar == wxT( "A" ) ) return std::make_unique<PCBEXPR_COMPONENT_CLASS_REF>( 0 ); else if( aVar == wxT( "B" ) ) return std::make_unique<PCBEXPR_COMPONENT_CLASS_REF>( 1 ); else return nullptr; } else if( aField.CmpNoCase( wxT( "NetName" ) ) == 0 ) { if( aVar == wxT( "A" ) ) return std::make_unique<PCBEXPR_NETNAME_REF>( 0 ); else if( aVar == wxT( "B" ) ) return std::make_unique<PCBEXPR_NETNAME_REF>( 1 ); else return nullptr; } else if( aField.CmpNoCase( wxT( "Type" ) ) == 0 ) { if( aVar == wxT( "A" ) ) return std::make_unique<PCBEXPR_TYPE_REF>( 0 ); else if( aVar == wxT( "B" ) ) return std::make_unique<PCBEXPR_TYPE_REF>( 1 ); else return nullptr; }
if( aVar == wxT( "A" ) || aVar == wxT( "AB" ) ) vref = std::make_unique<PCBEXPR_VAR_REF>( 0 ); else if( aVar == wxT( "B" ) ) vref = std::make_unique<PCBEXPR_VAR_REF>( 1 ); else if( aVar == wxT( "L" ) ) vref = std::make_unique<PCBEXPR_VAR_REF>( 2 ); else return nullptr;
if( aField.length() == 0 ) // return reference to base object
return vref;
wxString field( aField ); field.Replace( wxT( "_" ), wxT( " " ) );
for( const PROPERTY_MANAGER::CLASS_INFO& cls : propMgr.GetAllClasses() ) { if( propMgr.IsOfType( cls.type, TYPE_HASH( BOARD_ITEM ) ) ) { PROPERTY_BASE* prop = propMgr.GetProperty( cls.type, field );
if( prop ) { vref->AddAllowedClass( cls.type, prop );
if( prop->TypeHash() == TYPE_HASH( int ) ) { vref->SetType( LIBEVAL::VT_NUMERIC ); } else if( prop->TypeHash() == TYPE_HASH( std::optional<int> ) ) { vref->SetType( LIBEVAL::VT_NUMERIC ); vref->SetIsOptional(); } else if( prop->TypeHash() == TYPE_HASH( double ) ) { vref->SetType( LIBEVAL::VT_NUMERIC_DOUBLE ); } else if( prop->TypeHash() == TYPE_HASH( std::optional<double> ) ) { vref->SetType( LIBEVAL::VT_NUMERIC_DOUBLE ); vref->SetIsOptional(); } else if( prop->TypeHash() == TYPE_HASH( bool ) ) { vref->SetType( LIBEVAL::VT_NUMERIC ); } else if( prop->TypeHash() == TYPE_HASH( wxString ) ) { vref->SetType( LIBEVAL::VT_STRING ); } else if ( prop->HasChoices() ) { // it's an enum, we treat it as string
vref->SetType( LIBEVAL::VT_STRING ); vref->SetIsEnum( true ); } else { wxString msg = wxString::Format( wxT( "PCBEXPR_UCODE::createVarRef: Unknown " "property type %s from %s." ), cls.name, field ); wxFAIL_MSG( msg ); } } } }
if( vref->GetType() == LIBEVAL::VT_UNDEFINED ) vref->SetType( LIBEVAL::VT_PARSE_ERROR );
return vref;}
BOARD* PCBEXPR_CONTEXT::GetBoard() const{ if( m_items[0] ) return m_items[0]->GetBoard();
return nullptr;}
/* --------------------------------------------------------------------------------------------
* Unit Resolvers */
const std::vector<wxString>& PCBEXPR_UNIT_RESOLVER::GetSupportedUnits() const{ static const std::vector<wxString> pcbUnits = { wxT( "mil" ), wxT( "mm" ), wxT( "in" ), wxT( "deg" ) };
return pcbUnits;}
wxString PCBEXPR_UNIT_RESOLVER::GetSupportedUnitsMessage() const{ return _( "must be mm, in, mil, or deg" );}
double PCBEXPR_UNIT_RESOLVER::Convert( const wxString& aString, int unitId ) const{ double v = wxAtof( aString );
switch( unitId ) { case 0: return EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, EDA_UNITS::MILS, aString ); case 1: return EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, EDA_UNITS::MM, aString ); case 2: return EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, EDA_UNITS::INCH, aString ); default: return v; }};
const std::vector<wxString>& PCBEXPR_UNITLESS_RESOLVER::GetSupportedUnits() const{ static const std::vector<wxString> emptyUnits;
return emptyUnits;}
double PCBEXPR_UNITLESS_RESOLVER::Convert( const wxString& aString, int unitId ) const{ return wxAtof( aString );};
PCBEXPR_COMPILER::PCBEXPR_COMPILER( LIBEVAL::UNIT_RESOLVER* aUnitResolver ){ m_unitResolver.reset( aUnitResolver );}
/* --------------------------------------------------------------------------------------------
* PCB Expression Evaluator */
PCBEXPR_EVALUATOR::PCBEXPR_EVALUATOR( LIBEVAL::UNIT_RESOLVER* aUnitResolver ) : m_result( 0 ), m_compiler( aUnitResolver ), m_ucode(), m_errorStatus(){}
PCBEXPR_EVALUATOR::~PCBEXPR_EVALUATOR(){}
bool PCBEXPR_EVALUATOR::Evaluate( const wxString& aExpr ){ PCBEXPR_UCODE ucode; PCBEXPR_CONTEXT preflightContext( NULL_CONSTRAINT, F_Cu );
if( !m_compiler.Compile( aExpr.ToUTF8().data(), &ucode, &preflightContext ) ) return false;
PCBEXPR_CONTEXT evaluationContext( NULL_CONSTRAINT, F_Cu ); LIBEVAL::VALUE* result = ucode.Run( &evaluationContext );
if( result->GetType() == LIBEVAL::VT_NUMERIC ) m_result = KiROUND( result->AsDouble() );
return true;}
|