KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcbexpr_evaluator.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include "pcbexpr_evaluator.h"
25
26#include <inspectable_impl.h>
27
28#include <cstdio>
29#include <memory>
30#include <mutex>
31
32#include <board.h>
33#include <footprint.h>
34#include <lset.h>
36#include <drc/drc_engine.h>
38#include <string_utils.h>
39
40
41/* --------------------------------------------------------------------------------------------
42 * Specialized Expression References
43 */
44
46{
47 wxASSERT( dynamic_cast<const PCBEXPR_CONTEXT*>( aCtx ) );
48
49 const PCBEXPR_CONTEXT* ctx = static_cast<const PCBEXPR_CONTEXT*>( aCtx );
50 BOARD_ITEM* item = ctx->GetItem( m_itemIndex );
51 return item;
52}
53
54
56{
57public:
59 LIBEVAL::VALUE( LayerName( aLayer ) ),
60 m_layer( aLayer )
61 {};
62
63 virtual bool EqualTo( LIBEVAL::CONTEXT* aCtx, const VALUE* b ) const override
64 {
65 // For boards with user-defined layer names there will be 2 entries for each layer
66 // in the ENUM_MAP: one for the canonical layer name and one for the user layer name.
67 // We need to check against both.
68
69 wxPGChoices& layerMap = ENUM_MAP<PCB_LAYER_ID>::Instance().Choices();
70 const wxString& layerName = b->AsString();
71 BOARD* board = static_cast<PCBEXPR_CONTEXT*>( aCtx )->GetBoard();
72
73 {
74 std::shared_lock<std::shared_mutex> readLock( board->m_CachesMutex );
75
76 auto i = board->m_LayerExpressionCache.find( layerName );
77
78 if( i != board->m_LayerExpressionCache.end() )
79 return i->second.Contains( m_layer );
80 }
81
82 LSET mask;
83
84 for( unsigned ii = 0; ii < layerMap.GetCount(); ++ii )
85 {
86 wxPGChoiceEntry& entry = layerMap[ii];
87
88 if( entry.GetText().Matches( layerName ) )
89 mask.set( ToLAYER_ID( entry.GetValue() ) );
90 }
91
92 {
93 std::unique_lock<std::shared_mutex> writeLock( board->m_CachesMutex );
94 board->m_LayerExpressionCache[ layerName ] = mask;
95 }
96
97 return mask.Contains( m_layer );
98 }
99
100protected:
102};
103
104
106{
107public:
108 PCBEXPR_PINTYPE_VALUE( const wxString& aPinTypeName ) :
109 LIBEVAL::VALUE( aPinTypeName )
110 {};
111
112 bool EqualTo( LIBEVAL::CONTEXT* aCtx, const VALUE* b ) const override
113 {
114 const wxString& thisStr = AsString();
115 const wxString& otherStr = b->AsString();
116
117 // Case insensitive
118 if( thisStr.IsSameAs( otherStr, false ) )
119 return true;
120
121 // Wildcards
122 if( thisStr.Matches( otherStr ) )
123 return true;
124
125 // Handle cases where the netlist token is different from the EEschema token
126 wxString altStr;
127
128 if( thisStr == wxT( "tri_state" ) )
129 altStr = wxT( "Tri-state" );
130 else if( thisStr == wxT( "power_in" ) )
131 altStr = wxT( "Power input" );
132 else if( thisStr == wxT( "power_out" ) )
133 altStr = wxT( "Power output" );
134 else if( thisStr == wxT( "no_connect" ) )
135 altStr = wxT( "Unconnected" );
136
137 if( !altStr.IsEmpty() )
138 {
139 // Case insensitive
140 if( altStr.IsSameAs( otherStr, false ) )
141 return true;
142
143 // Wildcards
144 if( altStr.Matches( otherStr ) )
145 return true;
146 }
147
148 return false;
149 }
150};
151
152
154{
155public:
157 LIBEVAL::VALUE( wxEmptyString ),
158 m_item( aItem )
159 {};
160
161 const wxString& AsString() const override
162 {
163 const_cast<PCBEXPR_NETCLASS_VALUE*>( this )->Set( m_item->GetEffectiveNetClass()->GetName() );
165 }
166
167 bool EqualTo( LIBEVAL::CONTEXT* aCtx, const VALUE* b ) const override
168 {
169 if( const PCBEXPR_NETCLASS_VALUE* bValue = dynamic_cast<const PCBEXPR_NETCLASS_VALUE*>( b ) )
170 return *( m_item->GetEffectiveNetClass() ) == *( bValue->m_item->GetEffectiveNetClass() );
171
172 if( b->GetType() == LIBEVAL::VT_STRING )
173 {
174 // Test constituent net class names. The effective net class name (e.g. CLASS1,CLASS2,OTHER_CLASS) is
175 // tested in the fallthrough condition.
176 for( const NETCLASS* nc : m_item->GetEffectiveNetClass()->GetConstituentNetclasses() )
177 {
178 const wxString& ncName = nc->GetName();
179
180 if( b->StringIsWildcard() )
181 {
182 if( WildCompareString( b->AsString(), ncName, false ) )
183 return true;
184 }
185 else
186 {
187 if( ncName.IsSameAs( b->AsString(), false ) )
188 return true;
189 }
190 }
191 }
192
193 return LIBEVAL::VALUE::EqualTo( aCtx, b );
194 }
195
196 bool NotEqualTo( LIBEVAL::CONTEXT* aCtx, const LIBEVAL::VALUE* b ) const override
197 {
198 if( const PCBEXPR_NETCLASS_VALUE* bValue = dynamic_cast<const PCBEXPR_NETCLASS_VALUE*>( b ) )
199 return *( m_item->GetEffectiveNetClass() ) != *( bValue->m_item->GetEffectiveNetClass() );
200
201 if( b->GetType() == LIBEVAL::VT_STRING )
202 {
203 // Test constituent net class names
204 bool isInConstituents = false;
205
206 for( const NETCLASS* nc : m_item->GetEffectiveNetClass()->GetConstituentNetclasses() )
207 {
208 const wxString& ncName = nc->GetName();
209
210 if( b->StringIsWildcard() )
211 {
212 if( WildCompareString( b->AsString(), ncName, false ) )
213 {
214 isInConstituents = true;
215 break;
216 }
217 }
218 else
219 {
220 if( ncName.IsSameAs( b->AsString(), false ) )
221 {
222 isInConstituents = true;
223 break;
224 }
225 }
226 }
227
228 // Test effective net class name
229 const bool isFullName = LIBEVAL::VALUE::EqualTo( aCtx, b );
230
231 return !isInConstituents && !isFullName;
232 }
233
234 return LIBEVAL::VALUE::NotEqualTo( aCtx, b );
235 }
236
237protected:
239};
240
241
243{
244public:
246 LIBEVAL::VALUE( wxEmptyString ),
247 m_item( dynamic_cast<FOOTPRINT*>( aItem ) )
248 {};
249
250 const wxString& AsString() const override
251 {
252 if( !m_item )
254
255 if( const COMPONENT_CLASS* compClass = m_item->GetComponentClass() )
256 const_cast<PCBEXPR_COMPONENT_CLASS_VALUE*>( this )->Set( compClass->GetName() );
257
259 }
260
261 bool EqualTo( LIBEVAL::CONTEXT* aCtx, const VALUE* b ) const override
262 {
263 if( const PCBEXPR_COMPONENT_CLASS_VALUE* bValue = dynamic_cast<const PCBEXPR_COMPONENT_CLASS_VALUE*>( b ) )
264 {
265 if( !m_item || !bValue->m_item )
266 return LIBEVAL::VALUE::EqualTo( aCtx, b );
267
268 const COMPONENT_CLASS* aClass = m_item->GetComponentClass();
269 const COMPONENT_CLASS* bClass = bValue->m_item->GetComponentClass();
270
271 return *aClass == *bClass;
272 }
273
274 if( b->GetType() == LIBEVAL::VT_STRING )
275 {
276 // Test constituent component class names. The effective component class name
277 // (e.g. CLASS1,CLASS2,OTHER_CLASS) is tested in the fallthrough condition.
278 for( const COMPONENT_CLASS* cc : m_item->GetComponentClass()->GetConstituentClasses() )
279 {
280 const wxString& ccName = cc->GetName();
281
282 if( b->StringIsWildcard() )
283 {
284 if( WildCompareString( b->AsString(), ccName, false ) )
285 return true;
286 }
287 else
288 {
289 if( ccName.IsSameAs( b->AsString(), false ) )
290 return true;
291 }
292 }
293 }
294
295 return LIBEVAL::VALUE::EqualTo( aCtx, b );
296 }
297
298 bool NotEqualTo( LIBEVAL::CONTEXT* aCtx, const LIBEVAL::VALUE* b ) const override
299 {
300 if( const PCBEXPR_COMPONENT_CLASS_VALUE* bValue = dynamic_cast<const PCBEXPR_COMPONENT_CLASS_VALUE*>( b ) )
301 {
302 if( !m_item || !bValue->m_item )
303 return LIBEVAL::VALUE::NotEqualTo( aCtx, b );
304
305 const COMPONENT_CLASS* aClass = m_item->GetComponentClass();
306 const COMPONENT_CLASS* bClass = bValue->m_item->GetComponentClass();
307
308 return *aClass != *bClass;
309 }
310
311 if( b->GetType() == LIBEVAL::VT_STRING )
312 {
313 // Test constituent component class names
314 bool isInConstituents = false;
315
316 for( const COMPONENT_CLASS* cc : m_item->GetComponentClass()->GetConstituentClasses() )
317 {
318 const wxString& ccName = cc->GetName();
319
320 if( b->StringIsWildcard() )
321 {
322 if( WildCompareString( b->AsString(), ccName, false ) )
323 {
324 isInConstituents = true;
325 break;
326 }
327 }
328 else
329 {
330 if( ccName.IsSameAs( b->AsString(), false ) )
331 {
332 isInConstituents = true;
333 break;
334 }
335 }
336 }
337
338 // Test effective component class name
339 const bool isFullName = LIBEVAL::VALUE::EqualTo( aCtx, b );
340
341 return !isInConstituents && !isFullName;
342 }
343
344 return LIBEVAL::VALUE::NotEqualTo( aCtx, b );
345 }
346
347protected:
349};
350
351
353{
354public:
356 LIBEVAL::VALUE( wxEmptyString ),
357 m_item( aItem )
358 {};
359
360 const wxString& AsString() const override
361 {
362 const_cast<PCBEXPR_NET_VALUE*>( this )->Set( m_item->GetNetname() );
364 }
365
366 bool EqualTo( LIBEVAL::CONTEXT* aCtx, const VALUE* b ) const override
367 {
368 if( const PCBEXPR_NET_VALUE* bValue = dynamic_cast<const PCBEXPR_NET_VALUE*>( b ) )
369 return m_item->GetNetCode() == bValue->m_item->GetNetCode();
370 else
371 return LIBEVAL::VALUE::EqualTo( aCtx, b );
372 }
373
374 bool NotEqualTo( LIBEVAL::CONTEXT* aCtx, const LIBEVAL::VALUE* b ) const override
375 {
376 if( const PCBEXPR_NET_VALUE* bValue = dynamic_cast<const PCBEXPR_NET_VALUE*>( b ) )
377 return m_item->GetNetCode() != bValue->m_item->GetNetCode();
378 else
379 return LIBEVAL::VALUE::NotEqualTo( aCtx, b );
380 }
381
382protected:
384};
385
386
388{
389 auto it = m_typeOverrides.find( aItem );
390 return it != m_typeOverrides.end() ? it->second : aItem->Type();
391}
392
393
395{
396 PCBEXPR_CONTEXT* context = static_cast<PCBEXPR_CONTEXT*>( aCtx );
397
398 if( m_type == LIBEVAL::VT_NULL )
400
401 if( m_itemIndex == 2 )
402 return new PCBEXPR_LAYER_VALUE( context->GetLayer() );
403
404 BOARD_ITEM* item = GetObject( aCtx );
405
406 if( !item )
407 return new LIBEVAL::VALUE();
408
409 auto it = m_matchingTypes.find( TYPE_HASH( *item ) );
410
411 if( it == m_matchingTypes.end() )
412 {
413 // Don't force user to type "A.Type == 'via' && A.Via_Type == 'buried'" when the
414 // simpler "A.Via_Type == 'buried'" is perfectly clear. Instead, return an undefined
415 // value when the property doesn't appear on a particular object.
416
417 return new LIBEVAL::VALUE();
418 }
419 else
420 {
422 {
423 if( m_isOptional )
424 {
425 std::optional<int> val = item->Get<std::optional<int>>( it->second );
426
427 if( val.has_value() )
428 return new LIBEVAL::VALUE( static_cast<double>( val.value() ) );
429
431 }
432
433 return new LIBEVAL::VALUE( static_cast<double>( item->Get<int>( it->second ) ) );
434 }
436 {
437 if( m_isOptional )
438 {
439 std::optional<double> val = item->Get<std::optional<double>>( it->second );
440
441 if( val.has_value() )
442 return new LIBEVAL::VALUE( val.value() );
443
445 }
446
447 return new LIBEVAL::VALUE( item->Get<double>( it->second ) );
448 }
449 else
450 {
451 wxString str;
452
453 if( !m_isEnum )
454 {
455 str = item->Get<wxString>( it->second );
456
457 if( it->second->Name() == wxT( "Pin Type" ) )
458 return new PCBEXPR_PINTYPE_VALUE( str );
459
460 // If it quacks like a duck, it is a duck
461 double doubleVal;
462
464 return new LIBEVAL::VALUE( doubleVal );
465
466 return new LIBEVAL::VALUE( str );
467 }
468 else if( it->second->Name() == wxT( "Layer" )
469 || it->second->Name() == wxT( "Layer Top" )
470 || it->second->Name() == wxT( "Layer Bottom" ) )
471 {
472 const wxAny& any = item->Get( it->second );
473 PCB_LAYER_ID layer;
474
475 if( any.GetAs<PCB_LAYER_ID>( &layer ) )
476 return new PCBEXPR_LAYER_VALUE( layer );
477 else if( any.GetAs<wxString>( &str ) )
478 return new PCBEXPR_LAYER_VALUE( context->GetBoard()->GetLayerID( str ) );
479 }
480 else
481 {
482 const wxAny& any = item->Get( it->second );
483
484 if( any.GetAs<wxString>( &str ) )
485 return new LIBEVAL::VALUE( str );
486 }
487
488 return new LIBEVAL::VALUE();
489 }
490 }
491}
492
493
495{
496 BOARD_CONNECTED_ITEM* item = dynamic_cast<BOARD_CONNECTED_ITEM*>( GetObject( aCtx ) );
497
498 if( !item )
499 return new LIBEVAL::VALUE();
500
501 return new PCBEXPR_NETCLASS_VALUE( item );
502}
503
504
506{
507 BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( GetObject( aCtx ) );
508
509 if( !item || item->Type() != PCB_FOOTPRINT_T )
510 return new LIBEVAL::VALUE();
511
512 return new PCBEXPR_COMPONENT_CLASS_VALUE( item );
513}
514
515
517{
518 BOARD_CONNECTED_ITEM* item = dynamic_cast<BOARD_CONNECTED_ITEM*>( GetObject( aCtx ) );
519
520 if( !item )
521 return new LIBEVAL::VALUE();
522
523 return new PCBEXPR_NET_VALUE( item );
524}
525
526
528{
529 BOARD_ITEM* item = GetObject( aCtx );
530
531 if( !item )
532 return new LIBEVAL::VALUE();
533
534 PCBEXPR_CONTEXT* ctx = static_cast<PCBEXPR_CONTEXT*>( aCtx );
535 KICAD_T type = ctx->GetEffectiveType( item );
536
537 return new LIBEVAL::VALUE( ENUM_MAP<KICAD_T>::Instance().ToString( type ) );
538}
539
540
542{
543 wxString nameLower = aName.Lower();
544
546
547 if( registry.IsGeometryDependent( nameLower ) )
549
550 return registry.Get( nameLower );
551}
552
553
554std::unique_ptr<LIBEVAL::VAR_REF> PCBEXPR_UCODE::CreateVarRef( const wxString& aVar,
555 const wxString& aField )
556{
558 std::unique_ptr<PCBEXPR_VAR_REF> vref;
559
560 if( aVar.IsSameAs( wxT( "null" ), false ) )
561 {
562 vref = std::make_unique<PCBEXPR_VAR_REF>( 0 );
563 vref->SetType( LIBEVAL::VT_NULL );
564 return vref;
565 }
566
567 // Check for a couple of very common cases and compile them straight to "object code".
568
569 if( aField.CmpNoCase( wxT( "NetClass" ) ) == 0 )
570 {
571 if( aVar == wxT( "A" ) )
572 return std::make_unique<PCBEXPR_NETCLASS_REF>( 0 );
573 else if( aVar == wxT( "B" ) )
574 return std::make_unique<PCBEXPR_NETCLASS_REF>( 1 );
575 else
576 return nullptr;
577 }
578 else if( aField.CmpNoCase( wxT( "ComponentClass" ) ) == 0 )
579 {
580 if( aVar == wxT( "A" ) )
581 return std::make_unique<PCBEXPR_COMPONENT_CLASS_REF>( 0 );
582 else if( aVar == wxT( "B" ) )
583 return std::make_unique<PCBEXPR_COMPONENT_CLASS_REF>( 1 );
584 else
585 return nullptr;
586 }
587 else if( aField.CmpNoCase( wxT( "NetName" ) ) == 0 )
588 {
589 if( aVar == wxT( "A" ) )
590 return std::make_unique<PCBEXPR_NETNAME_REF>( 0 );
591 else if( aVar == wxT( "B" ) )
592 return std::make_unique<PCBEXPR_NETNAME_REF>( 1 );
593 else
594 return nullptr;
595 }
596 else if( aField.CmpNoCase( wxT( "Type" ) ) == 0 )
597 {
598 if( aVar == wxT( "A" ) )
599 return std::make_unique<PCBEXPR_TYPE_REF>( 0 );
600 else if( aVar == wxT( "B" ) )
601 return std::make_unique<PCBEXPR_TYPE_REF>( 1 );
602 else
603 return nullptr;
604 }
605
606 if( aVar == wxT( "A" ) || aVar == wxT( "AB" ) )
607 vref = std::make_unique<PCBEXPR_VAR_REF>( 0 );
608 else if( aVar == wxT( "B" ) )
609 vref = std::make_unique<PCBEXPR_VAR_REF>( 1 );
610 else if( aVar == wxT( "L" ) )
611 vref = std::make_unique<PCBEXPR_VAR_REF>( 2 );
612 else
613 return nullptr;
614
615 if( aField.length() == 0 ) // return reference to base object
616 return vref;
617
618 wxString field( aField );
619 field.Replace( wxT( "_" ), wxT( " " ) );
620
621 for( const PROPERTY_MANAGER::CLASS_INFO& cls : propMgr.GetAllClasses() )
622 {
623 if( propMgr.IsOfType( cls.type, TYPE_HASH( BOARD_ITEM ) ) )
624 {
625 PROPERTY_BASE* prop = propMgr.GetProperty( cls.type, field );
626
627 if( prop )
628 {
629 vref->AddAllowedClass( cls.type, prop );
630
631 if( prop->TypeHash() == TYPE_HASH( int ) )
632 {
633 vref->SetType( LIBEVAL::VT_NUMERIC );
634 }
635 else if( prop->TypeHash() == TYPE_HASH( std::optional<int> ) )
636 {
637 vref->SetType( LIBEVAL::VT_NUMERIC );
638 vref->SetIsOptional();
639 }
640 else if( prop->TypeHash() == TYPE_HASH( double ) )
641 {
642 vref->SetType( LIBEVAL::VT_NUMERIC_DOUBLE );
643 }
644 else if( prop->TypeHash() == TYPE_HASH( std::optional<double> ) )
645 {
646 vref->SetType( LIBEVAL::VT_NUMERIC_DOUBLE );
647 vref->SetIsOptional();
648 }
649 else if( prop->TypeHash() == TYPE_HASH( bool ) )
650 {
651 vref->SetType( LIBEVAL::VT_NUMERIC );
652 }
653 else if( prop->TypeHash() == TYPE_HASH( wxString ) )
654 {
655 vref->SetType( LIBEVAL::VT_STRING );
656 }
657 else if ( prop->HasChoices() )
658 { // it's an enum, we treat it as string
659 vref->SetType( LIBEVAL::VT_STRING );
660 vref->SetIsEnum( true );
661 }
662 else
663 {
664 wxString msg = wxString::Format( wxT( "PCBEXPR_UCODE::createVarRef: Unknown "
665 "property type %s from %s." ),
666 cls.name,
667 field );
668 wxFAIL_MSG( msg );
669 }
670 }
671 }
672 }
673
674 if( vref->GetType() == LIBEVAL::VT_UNDEFINED )
675 vref->SetType( LIBEVAL::VT_PARSE_ERROR );
676
677 return vref;
678}
679
680
682{
683 if( m_items[0] )
684 return m_items[0]->GetBoard();
685
686 return nullptr;
687}
688
689
690/* --------------------------------------------------------------------------------------------
691 * Unit Resolvers
692 */
693
694const std::vector<wxString>& PCBEXPR_UNIT_RESOLVER::GetSupportedUnits() const
695{
696 static const std::vector<wxString> pcbUnits = { wxT( "mil" ), wxT( "mm" ), wxT( "in" ),
697 wxT( "deg" ), wxT( "fs" ), wxT( "ps" ) };
698
699
700 return pcbUnits;
701}
702
703
705{
706 return _( "must be mm, in, mil, deg, fs, or ps" );
707}
708
709
710const std::vector<EDA_UNITS>& PCBEXPR_UNIT_RESOLVER::GetSupportedUnitsTypes() const
711{
712 static const std::vector<EDA_UNITS> pcbUnits = { EDA_UNITS::MILS, EDA_UNITS::MM, EDA_UNITS::INCH,
714
715 return pcbUnits;
716}
717
718
719double PCBEXPR_UNIT_RESOLVER::Convert( const wxString& aString, int unitId ) const
720{
721 double v = wxAtof( aString );
722
723 switch( unitId )
724 {
728 case 3: return v;
731 default: return v;
732 }
733};
734
735
736const std::vector<wxString>& PCBEXPR_UNITLESS_RESOLVER::GetSupportedUnits() const
737{
738 static const std::vector<wxString> emptyUnits;
739
740 return emptyUnits;
741}
742
743
744const std::vector<EDA_UNITS>& PCBEXPR_UNITLESS_RESOLVER::GetSupportedUnitsTypes() const
745{
746 static const std::vector<EDA_UNITS> emptyUnits;
747
748 return emptyUnits;
749}
750
751
752double PCBEXPR_UNITLESS_RESOLVER::Convert( const wxString& aString, int unitId ) const
753{
754 return wxAtof( aString );
755};
756
757
759{
760 m_unitResolver.reset( aUnitResolver );
761}
762
763
764/* --------------------------------------------------------------------------------------------
765 * PCB Expression Evaluator
766 */
767
769 m_result( 0 ),
770 m_units( EDA_UNITS::MM ),
771 m_compiler( aUnitResolver ),
772 m_ucode(),
774{
775}
776
777
781
782
783bool PCBEXPR_EVALUATOR::Evaluate( const wxString& aExpr )
784{
785 PCBEXPR_UCODE ucode;
786 PCBEXPR_CONTEXT preflightContext( NULL_CONSTRAINT, F_Cu );
787
788 if( !m_compiler.Compile( aExpr.ToUTF8().data(), &ucode, &preflightContext ) )
789 return false;
790
791 PCBEXPR_CONTEXT evaluationContext( NULL_CONSTRAINT, F_Cu );
792 LIBEVAL::VALUE* result = ucode.Run( &evaluationContext );
793
794 if( result->GetType() == LIBEVAL::VT_NUMERIC )
795 {
796 m_result = KiROUND( result->AsDouble() );
797 m_units = result->GetUnits();
798 }
799
800 return true;
801}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
BASE_SET & set(size_t pos)
Definition base_set.h:116
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:323
PCB_LAYER_ID GetLayerID(const wxString &aLayerName) const
Return the ID of a layer.
Definition board.cpp:717
std::unordered_map< wxString, LSET > m_LayerExpressionCache
Definition board.h:1545
std::shared_mutex m_CachesMutex
Definition board.h:1539
A lightweight representation of a component class.
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:112
static ENUM_MAP< T > & Instance()
Definition property.h:721
wxAny Get(PROPERTY_BASE *aProperty) const
std::unique_ptr< UNIT_RESOLVER > m_unitResolver
VALUE * Run(CONTEXT *ctx)
void Set(double aValue)
virtual const wxString & AsString() const
bool StringIsWildcard() const
static VALUE * MakeNullValue()
virtual bool NotEqualTo(CONTEXT *aCtx, const VALUE *b) const
VAR_TYPE_T GetType() const
virtual bool EqualTo(CONTEXT *aCtx, const VALUE *b) const
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Definition lset.h:63
A collection of nets and the parameters used to route or test these nets.
Definition netclass.h:42
bool IsGeometryDependent(const wxString &name) const
LIBEVAL::FUNC_CALL_REF Get(const wxString &name)
static PCBEXPR_BUILTIN_FUNCTIONS & Instance()
PCBEXPR_COMPILER(LIBEVAL::UNIT_RESOLVER *aUnitResolver)
LIBEVAL::VALUE * GetValue(LIBEVAL::CONTEXT *aCtx) override
bool NotEqualTo(LIBEVAL::CONTEXT *aCtx, const LIBEVAL::VALUE *b) const override
const wxString & AsString() const override
PCBEXPR_COMPONENT_CLASS_VALUE(BOARD_ITEM *aItem)
bool EqualTo(LIBEVAL::CONTEXT *aCtx, const VALUE *b) const override
BOARD_ITEM * m_items[2]
BOARD * GetBoard() const
KICAD_T GetEffectiveType(const BOARD_ITEM *aItem) const
PCB_LAYER_ID GetLayer() const
std::map< const BOARD_ITEM *, KICAD_T > m_typeOverrides
BOARD_ITEM * GetItem(int index) const
LIBEVAL::ERROR_STATUS m_errorStatus
PCBEXPR_EVALUATOR(LIBEVAL::UNIT_RESOLVER *aUnitResolver)
PCBEXPR_COMPILER m_compiler
bool Evaluate(const wxString &aExpr)
PCBEXPR_LAYER_VALUE(PCB_LAYER_ID aLayer)
virtual bool EqualTo(LIBEVAL::CONTEXT *aCtx, const VALUE *b) const override
LIBEVAL::VALUE * GetValue(LIBEVAL::CONTEXT *aCtx) override
bool EqualTo(LIBEVAL::CONTEXT *aCtx, const VALUE *b) const override
BOARD_CONNECTED_ITEM * m_item
PCBEXPR_NETCLASS_VALUE(BOARD_CONNECTED_ITEM *aItem)
const wxString & AsString() const override
bool NotEqualTo(LIBEVAL::CONTEXT *aCtx, const LIBEVAL::VALUE *b) const override
LIBEVAL::VALUE * GetValue(LIBEVAL::CONTEXT *aCtx) override
bool EqualTo(LIBEVAL::CONTEXT *aCtx, const VALUE *b) const override
BOARD_CONNECTED_ITEM * m_item
PCBEXPR_NET_VALUE(BOARD_CONNECTED_ITEM *aItem)
bool NotEqualTo(LIBEVAL::CONTEXT *aCtx, const LIBEVAL::VALUE *b) const override
const wxString & AsString() const override
bool EqualTo(LIBEVAL::CONTEXT *aCtx, const VALUE *b) const override
PCBEXPR_PINTYPE_VALUE(const wxString &aPinTypeName)
LIBEVAL::VALUE * GetValue(LIBEVAL::CONTEXT *aCtx) override
virtual std::unique_ptr< LIBEVAL::VAR_REF > CreateVarRef(const wxString &aVar, const wxString &aField) override
virtual LIBEVAL::FUNC_CALL_REF CreateFuncCall(const wxString &aName) override
bool m_hasGeometryDependentFunctions
const std::vector< wxString > & GetSupportedUnits() const override
const std::vector< EDA_UNITS > & GetSupportedUnitsTypes() const override
double Convert(const wxString &aString, int unitId) const override
double Convert(const wxString &aString, int unitId) const override
const std::vector< EDA_UNITS > & GetSupportedUnitsTypes() const override
wxString GetSupportedUnitsMessage() const override
const std::vector< wxString > & GetSupportedUnits() const override
std::unordered_map< TYPE_ID, PROPERTY_BASE * > m_matchingTypes
LIBEVAL::VALUE * GetValue(LIBEVAL::CONTEXT *aCtx) override
LIBEVAL::VAR_TYPE_T m_type
BOARD_ITEM * GetObject(const LIBEVAL::CONTEXT *aCtx) const
virtual size_t TypeHash() const =0
Return type-id of the property type.
virtual bool HasChoices() const
Return true if this PROPERTY has a limited set of possible values.
Definition property.h:246
Provide class metadata.Helper macro to map type hashes to names.
CLASSES_INFO GetAllClasses()
static PROPERTY_MANAGER & Instance()
PROPERTY_BASE * GetProperty(TYPE_ID aType, const wxString &aProperty) const
Return a property for a specific type.
bool IsOfType(TYPE_ID aDerived, TYPE_ID aBase) const
Return true if aDerived is inherited from aBase.
A type-safe container of any type.
Definition ki_any.h:93
@ NULL_CONSTRAINT
Definition drc_rule.h:54
#define _(s)
EDA_UNITS
Definition eda_units.h:48
wxString LayerName(int aLayer)
Returns the default display name for a given layer.
Definition layer_id.cpp:31
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ F_Cu
Definition layer_ids.h:64
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:754
KICOMMON_API double DoubleValueFromString(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Convert aTextValue to a double.
std::function< void(CONTEXT *, void *)> FUNC_CALL_REF
#define TYPE_HASH(x)
Definition property.h:74
bool WildCompareString(const wxString &pattern, const wxString &string_to_tst, bool case_sensitive)
Compare a string against wild card (* and ?) pattern using the usual rules.
wxString result
Test unit parsing edge cases and error handling.
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:75
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition typeinfo.h:83