KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcbexpr_evaluator.h
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, see <https://www.gnu.org/licenses/>.
18 */
19
20
21#ifndef PCBEXPR_EVALUATOR_H
22#define PCBEXPR_EVALUATOR_H
23
24#include <set>
25#include <map>
26#include <unordered_map>
27#include <core/typeinfo.h>
28
29#include <layer_ids.h>
30
31#include <properties/property.h>
33
35
36class BOARD;
37class BOARD_ITEM;
38
39class PCBEXPR_VAR_REF;
40
41
42// A navigation step applied to a variable reference before its property or method is resolved.
43// "A.Parent.getField('x')" resolves item A, then steps to its parent before calling getField().
45{
47};
48
64
65class PCBEXPR_UCODE final : public LIBEVAL::UCODE
66{
67public:
69 virtual ~PCBEXPR_UCODE() {};
70
71 virtual std::unique_ptr<LIBEVAL::VAR_REF> CreateVarRef( const wxString& aVar,
72 const wxString& aField ) override;
73 virtual LIBEVAL::FUNC_CALL_REF CreateFuncCall( const wxString& aName ) override;
74
76 bool RequiresPairItems() const { return m_requiresPairItems; }
77 bool ReferencesItemB() const { return m_referencesItemB; }
78
79private:
81 bool m_requiresPairItems = false;
82 bool m_referencesItemB = false;
83};
84
85
87{
88public:
89 PCBEXPR_CONTEXT( int aConstraint = 0, PCB_LAYER_ID aLayer = F_Cu ) :
90 m_constraint( aConstraint ),
91 m_layer( aLayer )
92 {
93 m_items[0] = nullptr;
94 m_items[1] = nullptr;
95 }
96
97 void SetItems( BOARD_ITEM* a, BOARD_ITEM* b = nullptr )
98 {
99 m_items[0] = a;
100 m_items[1] = b;
101 }
102
103 void SetConstraint( int aConstraint ) { m_constraint = aConstraint; }
104 void SetLayer( PCB_LAYER_ID aLayer ) { m_layer = aLayer; }
105
107 void Reset() override
108 {
110 m_constraint = 0;
111 m_layer = F_Cu;
112 m_items[0] = nullptr;
113 m_items[1] = nullptr;
114 m_typeOverrides.clear();
115 }
116
117 void SetTypeOverride( const BOARD_ITEM* aItem, KICAD_T aType ) { m_typeOverrides[aItem] = aType; }
118
119 KICAD_T GetEffectiveType( const BOARD_ITEM* aItem ) const;
120
121 BOARD* GetBoard() const;
122
123 int GetConstraint() const { return m_constraint; }
124 BOARD_ITEM* GetItem( int index ) const { return m_items[index]; }
125 PCB_LAYER_ID GetLayer() const { return m_layer; }
126
127private:
131 std::map<const BOARD_ITEM*, KICAD_T> m_typeOverrides;
132};
133
134
136{
137public:
138 PCBEXPR_VAR_REF( int aItemIndex ) :
139 m_itemIndex( aItemIndex ),
140 m_type( LIBEVAL::VT_UNDEFINED )
141 {
142 }
143
144 ~PCBEXPR_VAR_REF() override = default;
145
146 static PCBEXPR_PROPERTY_KIND ClassifyProperty( const PROPERTY_BASE* aProperty );
148
149 void SetType( LIBEVAL::VAR_TYPE_T type ) { m_type = type; }
150 LIBEVAL::VAR_TYPE_T GetType() const override { return m_type; }
151
152 void AddAllowedClass( TYPE_ID aTypeHash, PROPERTY_BASE* aProperty, PCBEXPR_PROPERTY_KIND aKind )
153 {
154 m_matchingTypes[aTypeHash] = { aProperty, aKind };
155 }
156
157 // Navigation steps walked from the base item before the property/method is resolved.
158 // An empty chain (the default) resolves the base item directly, as before.
159 void SetNavigation( std::vector<PCBEXPR_NAV_STEP> aNavigation )
160 {
161 m_navigation = std::move( aNavigation );
162 }
163
164 LIBEVAL::VALUE* GetValue( LIBEVAL::CONTEXT* aCtx ) override;
165
166 BOARD_ITEM* GetObject( const LIBEVAL::CONTEXT* aCtx ) const;
167
168private:
174
175 std::unordered_map<TYPE_ID, MATCHED_PROPERTY> m_matchingTypes;
178 std::vector<PCBEXPR_NAV_STEP> m_navigation;
179};
180
181
182// "Object code" version of a netclass reference (for performance).
184{
185public:
186 PCBEXPR_NETCLASS_REF( int aItemIndex ) :
187 PCBEXPR_VAR_REF( aItemIndex )
188 {
190 }
191
192 LIBEVAL::VALUE* GetValue( LIBEVAL::CONTEXT* aCtx ) override;
193};
194
195
196// "Object code" version of a component class reference (for performance).
198{
199public:
200 PCBEXPR_COMPONENT_CLASS_REF( int aItemIndex ) : PCBEXPR_VAR_REF( aItemIndex )
201 {
203 }
204
205 LIBEVAL::VALUE* GetValue( LIBEVAL::CONTEXT* aCtx ) override;
206};
207
208
209// "Object code" version of a netname reference (for performance).
211{
212public:
213 PCBEXPR_NETNAME_REF( int aItemIndex ) :
214 PCBEXPR_VAR_REF( aItemIndex )
215 {
217 }
218
219 LIBEVAL::VALUE* GetValue( LIBEVAL::CONTEXT* aCtx ) override;
220};
221
222
224{
225public:
226 PCBEXPR_TYPE_REF( int aItemIndex ) :
227 PCBEXPR_VAR_REF( aItemIndex )
228 {
230 }
231
232 LIBEVAL::VALUE* GetValue( LIBEVAL::CONTEXT* aCtx ) override;
233};
234
235
237{
238public:
240
242 {
243 static PCBEXPR_BUILTIN_FUNCTIONS self;
244 return self;
245 }
246
247 LIBEVAL::FUNC_CALL_REF Get( const wxString& name )
248 {
249 return m_funcs[ name ];
250 }
251
252 bool IsGeometryDependent( const wxString& name ) const
253 {
254 return m_geometryDependentFuncs.count( name ) > 0;
255 }
256
257 const wxArrayString GetSignatures() const
258 {
259 return m_funcSigs;
260 }
261
262 void RegisterFunc( const wxString& funcSignature, LIBEVAL::FUNC_CALL_REF funcPtr,
263 bool aIsGeometryDependent = false )
264 {
265 wxString funcName = funcSignature.BeforeFirst( '(' );
266 wxString lower = funcName.Lower();
267 m_funcs[std::string( lower )] = std::move( funcPtr );
268 m_funcSigs.Add( funcSignature );
269
270 if( aIsGeometryDependent )
271 m_geometryDependentFuncs.insert( lower );
272 }
273
275
276private:
277 std::map<wxString, LIBEVAL::FUNC_CALL_REF> m_funcs;
278 std::set<wxString> m_geometryDependentFuncs;
279
280 wxArrayString m_funcSigs;
281};
282
283
285{
286public:
287 const std::vector<wxString>& GetSupportedUnits() const override;
288 const std::vector<EDA_UNITS>& GetSupportedUnitsTypes() const override;
289
290 wxString GetSupportedUnitsMessage() const override;
291
292 double Convert( const wxString& aString, int unitId ) const override;
293};
294
295
297{
298public:
299 const std::vector<wxString>& GetSupportedUnits() const override;
300 const std::vector<EDA_UNITS>& GetSupportedUnitsTypes() const override;
301
302 double Convert( const wxString& aString, int unitId ) const override;
303};
304
305
307{
308public:
310};
311
312
314{
315public:
318
319 bool Evaluate( const wxString& aExpr );
320 int Result() const { return m_result; }
321
323 double ResultAsDouble() const { return m_resultAsDouble; }
324 EDA_UNITS Units() const { return m_units; }
325
326 void SetErrorCallback( std::function<void( const wxString& aMessage, int aOffset )> aCallback )
327 {
328 m_compiler.SetErrorCallback( std::move( aCallback ) );
329 }
330
331 bool IsErrorPending() const { return m_errorStatus.pendingError; }
333
334private:
338
342};
343
344#endif
int index
const char * name
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:409
virtual void Reset()
Release every value allocated by the previous evaluation and rewind the stack so the same CONTEXT can...
bool IsGeometryDependent(const wxString &name) const
const wxArrayString GetSignatures() const
LIBEVAL::FUNC_CALL_REF Get(const wxString &name)
std::map< wxString, LIBEVAL::FUNC_CALL_REF > m_funcs
static PCBEXPR_BUILTIN_FUNCTIONS & Instance()
void RegisterFunc(const wxString &funcSignature, LIBEVAL::FUNC_CALL_REF funcPtr, bool aIsGeometryDependent=false)
std::set< wxString > m_geometryDependentFuncs
PCBEXPR_COMPILER(LIBEVAL::UNIT_RESOLVER *aUnitResolver)
PCBEXPR_COMPONENT_CLASS_REF(int aItemIndex)
LIBEVAL::VALUE * GetValue(LIBEVAL::CONTEXT *aCtx) override
void SetConstraint(int aConstraint)
void SetLayer(PCB_LAYER_ID aLayer)
BOARD_ITEM * m_items[2]
void SetItems(BOARD_ITEM *a, BOARD_ITEM *b=nullptr)
PCBEXPR_CONTEXT(int aConstraint=0, PCB_LAYER_ID aLayer=F_Cu)
BOARD * GetBoard() const
int GetConstraint() const
void Reset() override
Rewind for reuse on the next evaluation (see LIBEVAL::CONTEXT::Reset()).
KICAD_T GetEffectiveType(const BOARD_ITEM *aItem) const
PCB_LAYER_ID GetLayer() const
void SetTypeOverride(const BOARD_ITEM *aItem, KICAD_T aType)
std::map< const BOARD_ITEM *, KICAD_T > m_typeOverrides
BOARD_ITEM * GetItem(int index) const
LIBEVAL::ERROR_STATUS m_errorStatus
bool IsErrorPending() const
double ResultAsDouble() const
Unrounded result, for constraints whose value is a ratio rather than a count or a length.
PCBEXPR_EVALUATOR(LIBEVAL::UNIT_RESOLVER *aUnitResolver)
PCBEXPR_COMPILER m_compiler
const LIBEVAL::ERROR_STATUS & GetError() const
bool Evaluate(const wxString &aExpr)
void SetErrorCallback(std::function< void(const wxString &aMessage, int aOffset)> aCallback)
EDA_UNITS Units() const
LIBEVAL::VALUE * GetValue(LIBEVAL::CONTEXT *aCtx) override
PCBEXPR_NETCLASS_REF(int aItemIndex)
LIBEVAL::VALUE * GetValue(LIBEVAL::CONTEXT *aCtx) override
PCBEXPR_NETNAME_REF(int aItemIndex)
PCBEXPR_TYPE_REF(int aItemIndex)
LIBEVAL::VALUE * GetValue(LIBEVAL::CONTEXT *aCtx) override
virtual std::unique_ptr< LIBEVAL::VAR_REF > CreateVarRef(const wxString &aVar, const wxString &aField) override
bool HasGeometryDependentFunctions() const
virtual LIBEVAL::FUNC_CALL_REF CreateFuncCall(const wxString &aName) override
virtual ~PCBEXPR_UCODE()
bool ReferencesItemB() const
bool m_hasGeometryDependentFunctions
bool RequiresPairItems() const
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::vector< PCBEXPR_NAV_STEP > m_navigation
void AddAllowedClass(TYPE_ID aTypeHash, PROPERTY_BASE *aProperty, PCBEXPR_PROPERTY_KIND aKind)
static PCBEXPR_PROPERTY_KIND ClassifyProperty(const PROPERTY_BASE *aProperty)
LIBEVAL::VALUE * GetValue(LIBEVAL::CONTEXT *aCtx) override
LIBEVAL::VAR_TYPE_T GetType() const override
void SetType(LIBEVAL::VAR_TYPE_T type)
std::unordered_map< TYPE_ID, MATCHED_PROPERTY > m_matchingTypes
PCBEXPR_VAR_REF(int aItemIndex)
void SetNavigation(std::vector< PCBEXPR_NAV_STEP > aNavigation)
~PCBEXPR_VAR_REF() override=default
static LIBEVAL::VAR_TYPE_T ExpressionType(PCBEXPR_PROPERTY_KIND aKind)
LIBEVAL::VAR_TYPE_T m_type
BOARD_ITEM * GetObject(const LIBEVAL::CONTEXT *aCtx) const
EDA_UNITS
Definition eda_units.h:44
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ F_Cu
Definition layer_ids.h:60
std::function< void(CONTEXT *, void *)> FUNC_CALL_REF
PCBEXPR_PROPERTY_KIND
PCBEXPR_NAV_STEP
size_t TYPE_ID
Unique type identifier.
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:70