dummyRules;
DRC_RULES_PARSER parser( m_frame->GetBoard(), m_textEditor->GetText(), _( "DRC rules" ) );
- parser.Parse( dummySelectors, dummyRules );
+ parser.Parse( dummyRules );
}
catch( PARSE_ERROR& pe )
{
@@ -249,7 +248,7 @@ void PANEL_SETUP_RULES::OnSyntaxHelp( wxHyperlinkEvent& aEvent )
""
"(rule \"copper keepout\"\r"
" (disallow track) (disallow via) (disallow zone)\r"
- " (condition \"A.name == no_copper\"))\r"
+ " (condition \"A.name == 'no_copper'\"))\r"
"\r"
"(rule \"BGA neckdown\"\r"
" (constraint track_width (min 0.2mm) (opt 0.25mm))\r"
@@ -258,11 +257,11 @@ void PANEL_SETUP_RULES::OnSyntaxHelp( wxHyperlinkEvent& aEvent )
"\r"
"(rule HV\r"
" (constraint clearance (min 1.5mm))\r"
- " (condition \"A.netclass == HV\"))\r"
+ " (condition \"A.netclass == 'HV'\"))\r"
"\r"
"(rule HV_HV\r"
" (constraint clearance (min 2.0mm))\r"
- " (condition \"A.netclass == HV && B.netclass == HV\"))\r"
+ " (condition \"A.netclass == 'HV' && B.netclass == 'HV'\"))\r"
"
";
HTML_MESSAGE_BOX dlg( m_parent, _( "Syntax Help" ) );
diff --git a/pcbnew/drc/drc.cpp b/pcbnew/drc/drc.cpp
index 412437e325..320ce03be0 100644
--- a/pcbnew/drc/drc.cpp
+++ b/pcbnew/drc/drc.cpp
@@ -187,7 +187,6 @@ bool DRC::LoadRules()
if( rulesFile.FileExists() )
{
- m_ruleSelectors.clear();
m_rules.clear();
FILE* fp = wxFopen( rulesFilepath, wxT( "rt" ) );
@@ -197,12 +196,11 @@ bool DRC::LoadRules()
try
{
DRC_RULES_PARSER parser( m_pcb, fp, rulesFilepath );
- parser.Parse( m_ruleSelectors, m_rules );
+ parser.Parse( m_rules );
}
catch( PARSE_ERROR& pe )
{
// Don't leave possibly malformed stuff around for us to trip over
- m_ruleSelectors.clear();
m_rules.clear();
wxSafeYield( m_editFrame );
@@ -214,10 +212,9 @@ bool DRC::LoadRules()
}
}
- std::reverse( std::begin( m_ruleSelectors ), std::end( m_ruleSelectors ) );
+ std::reverse( std::begin( m_rules ), std::end( m_rules ) );
BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings();
- bds.m_DRCRuleSelectors = m_ruleSelectors;
bds.m_DRCRules = m_rules;
return true;
diff --git a/pcbnew/drc/drc.h b/pcbnew/drc/drc.h
index 6330a84d56..10f88b15c5 100644
--- a/pcbnew/drc/drc.h
+++ b/pcbnew/drc/drc.h
@@ -132,7 +132,6 @@ private:
bool m_drcRun; // indicates DRC has been run at least once
bool m_footprintsTested; // indicates footprints were tested in last run
- std::vector m_ruleSelectors;
std::vector m_rules;
// Temp variables for performance during a single DRC run
diff --git a/pcbnew/drc/drc_rule.cpp b/pcbnew/drc/drc_rule.cpp
index 36fb938177..35511f3458 100644
--- a/pcbnew/drc/drc_rule.cpp
+++ b/pcbnew/drc/drc_rule.cpp
@@ -27,6 +27,8 @@
#include
#include
#include
+#include
+
/*
* Rule tokens:
@@ -52,8 +54,17 @@
* hole
*
*
- * (rule "HV" (constraint clearance (min 200)))
- * (rule "HV_external" (constraint clearance (min 400)))
+ * (rule "HV"
+ * (constraint clearance (min 200))
+ * (condition "A.Netclass == 'HV' || B.Netclass == 'HV'")
+ * )
+ *
+ * (rule "HV_external"
+ * (constraint clearance (min 400))
+ * (condition "(A.Netclass == 'HV' && (A.onLayer('F.Cu') || A.onLayer('B.Cu'))
+ * || (B.Netclass == 'HV' && (B.onLayer('F.Cu') || B.onLayer('B.Cu'))")
+ * )
+ *
* (rule "HV2HV" (constraint clearance (min 200)))
* (rule "HV2HV_external" (constraint clearance (min 500)))
* (rule "pad2padHV" (constraint clearance (min 500)))
@@ -62,99 +73,83 @@
* (rule "neckdown" (constraint clearance (min 15)))
*
* (rule "disallowMicrovias" (disallow micro_via))
+ *
+ *
+ testEvalExpr( "A.type == \"Pad\" && B.type == \"Pad\" && (A.onLayer(\"F.Cu\"))",VAL(0.0), false, &trackA, &trackB );
+ return 0;
+ testEvalExpr( "A.Width > B.Width", VAL(0.0), false, &trackA, &trackB );
+ testEvalExpr( "A.Width + B.Width", VAL(Mils2iu(10) + Mils2iu(20)), false, &trackA, &trackB );
+
+ testEvalExpr( "A.Netclass", VAL( (const char*) trackA.GetNetClassName().c_str() ), false, &trackA, &trackB );
+ testEvalExpr( "(A.Netclass == \"HV\") && (B.netclass == \"otherClass\") && (B.netclass != \"F.Cu\")", VAL( 1.0 ), false, &trackA, &trackB );
+ testEvalExpr( "A.Netclass + 1.0", VAL( 1.0 ), false, &trackA, &trackB );
+ testEvalExpr( "A.type == \"Track\" && B.type == \"Track\" && A.layer == \"F.Cu\"", VAL(0.0), false, &trackA, &trackB );
+ testEvalExpr( "(A.type == \"Track\") && (B.type == \"Track\") && (A.layer == \"F.Cu\")", VAL(0.0), false, &trackA, &trackB );
*/
DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstraint )
{
- // JEY TODO: the bulk of this will be replaced by Tom's expression evaluator
-
BOARD* board = aItem->GetBoard();
if( !board )
return nullptr;
- NETCLASS* aNetclass = nullptr;
- NETCLASS* bNetclass = nullptr;
-
- if( aItem->IsConnected() )
- aNetclass = static_cast( aItem )->GetEffectiveNetclass();
-
- if( bItem && bItem->IsConnected() )
- bNetclass = static_cast( bItem )->GetEffectiveNetclass();
-
- for( DRC_SELECTOR* candidate : board->GetDesignSettings().m_DRCRuleSelectors )
+ for( DRC_RULE* rule : board->GetDesignSettings().m_DRCRules )
{
- if( candidate->m_MatchNetclasses.size() == 2 )
+ if( ( rule->m_ConstraintFlags & aConstraint ) > 0 )
{
- if( !bItem )
- continue;
-
- NETCLASS* firstNetclass = candidate->m_MatchNetclasses[0].get();
- NETCLASS* secondNetclass = candidate->m_MatchNetclasses[1].get();
-
- if( !( aNetclass == firstNetclass && bNetclass == secondNetclass )
- && !( aNetclass == secondNetclass && bNetclass == firstNetclass ) )
- {
- continue;
- }
+ if( rule->m_Condition.EvaluateFor( aItem, bItem ) )
+ return rule;
}
- else if( candidate->m_MatchNetclasses.size() == 1 )
- {
- NETCLASS* matchNetclass = candidate->m_MatchNetclasses[0].get();
-
- if( matchNetclass != aNetclass && !( bItem && matchNetclass == bNetclass ) )
- continue;
- }
-
- if( candidate->m_MatchTypes.size() == 2 )
- {
- if( !bItem )
- continue;
-
- KICAD_T firstType[2] = { candidate->m_MatchTypes[0], EOT };
- KICAD_T secondType[2] = { candidate->m_MatchTypes[1], EOT };
-
- if( !( aItem->IsType( firstType ) && bItem->IsType( secondType ) )
- && !( aItem->IsType( secondType ) && bItem->IsType( firstType ) ) )
- {
- continue;
- }
- }
- else if( candidate->m_MatchTypes.size() == 1 )
- {
- KICAD_T matchType[2] = { candidate->m_MatchTypes[0], EOT };
-
- if( !aItem->IsType( matchType ) && !( bItem && bItem->IsType( matchType ) ) )
- continue;
- }
-
- if( candidate->m_MatchLayers.size() )
- {
- PCB_LAYER_ID matchLayer = candidate->m_MatchLayers[0];
-
- if( !aItem->GetLayerSet().test( matchLayer ) )
- continue;
- }
-
- if( candidate->m_MatchAreas.size() )
- {
- if( candidate->m_MatchAreas[0] == "$board" )
- {
- // matches everything
- }
- else
- {
- // TODO: area/room matches...
- }
- }
-
- // All tests done; if we're still here then it matches
-
- if( ( candidate->m_Rule->m_ConstraintFlags & aConstraint ) > 0 )
- return candidate->m_Rule;
}
return nullptr;
}
+DRC_RULE_CONDITION::DRC_RULE_CONDITION()
+{
+ m_ucode = nullptr;
+}
+
+
+DRC_RULE_CONDITION::~DRC_RULE_CONDITION()
+{
+ delete m_ucode;
+}
+
+
+bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB )
+{
+ BOARD_ITEM* a = const_cast( aItemA );
+ BOARD_ITEM* b = aItemB ? const_cast( aItemB ) : DELETED_BOARD_ITEM::GetInstance();
+
+ m_ucode->SetItems( a, b );
+
+// fixme: handle error conditions
+ return m_ucode->Run()->AsDouble() != 0.0;
+}
+
+
+bool DRC_RULE_CONDITION::Compile()
+{
+ PCB_EXPR_COMPILER compiler;
+
+ if (!m_ucode)
+ m_ucode = new PCB_EXPR_UCODE;
+
+ bool ok = compiler.Compile( (const char*) m_Expression.c_str(), m_ucode );
+
+ if( ok )
+ return true;
+
+ m_compileError = compiler.GetErrorStatus();
+
+ return false;
+}
+
+
+LIBEVAL::ERROR_STATUS DRC_RULE_CONDITION::GetCompilationError()
+{
+ return m_compileError;
+}
diff --git a/pcbnew/drc/drc_rule.h b/pcbnew/drc/drc_rule.h
index 03cbaa1947..05ebac687b 100644
--- a/pcbnew/drc/drc_rule.h
+++ b/pcbnew/drc/drc_rule.h
@@ -27,9 +27,11 @@
#include
#include
#include
+#include
class BOARD_ITEM;
+class PCB_EXPR_UCODE;
#define CLEARANCE_CONSTRAINT (1 << 0)
@@ -50,6 +52,52 @@ class BOARD_ITEM;
#define DISALLOW_FOOTPRINTS (1 << 9)
+template
+class MINOPTMAX
+{
+public:
+ T Min() const { assert( m_hasMin ); return m_min; };
+ T Max() const { assert( m_hasMax ); return m_max; };
+ T Opt() const { assert( m_hasOpt ); return m_opt; };
+
+ bool HasMin() const { return m_hasMin; }
+ bool HasMax() const { return m_hasMax; }
+ bool HasOpt() const { return m_hasOpt; }
+
+ void SetMin( T v ) { m_min = v; m_hasMin = true; }
+ void SetMax( T v ) { m_max = v; m_hasMax = true; }
+ void SetOpt( T v ) { m_opt = v; m_hasOpt = true; }
+
+private:
+ T m_min;
+ T m_opt;
+ T m_max;
+ bool m_hasMin = false;
+ bool m_hasOpt = false;
+ bool m_hasMax = false;
+};
+
+
+class DRC_RULE_CONDITION
+{
+public:
+ DRC_RULE_CONDITION();
+ ~DRC_RULE_CONDITION();
+
+ bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB );
+ bool Compile();
+ LIBEVAL::ERROR_STATUS GetCompilationError();
+
+public:
+ wxString m_Expression;
+ wxString m_TargetRuleName;
+
+private:
+ LIBEVAL::ERROR_STATUS m_compileError;
+ PCB_EXPR_UCODE* m_ucode;
+};
+
+
class DRC_RULE
{
public:
@@ -81,31 +129,11 @@ public:
MINOPTMAX m_TrackConstraint;
int m_MinHole;
- wxString m_Condition;
-};
-
-
-class DRC_SELECTOR
-{
-public:
- DRC_SELECTOR() :
- m_Priority( 1 ),
- m_Rule( nullptr )
- { }
-
-public:
- std::vector m_MatchNetclasses;
- std::vector m_MatchTypes;
- std::vector m_MatchLayers;
- std::vector m_MatchAreas;
-
- int m_Priority; // 0 indicates automatic priority generation
- DRC_RULE* m_Rule;
+ DRC_RULE_CONDITION m_Condition;
};
DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstraint );
-
#endif // DRC_RULE_H
diff --git a/pcbnew/drc/drc_rule_parser.cpp b/pcbnew/drc/drc_rule_parser.cpp
index f4b92b90df..c41176573c 100644
--- a/pcbnew/drc/drc_rule_parser.cpp
+++ b/pcbnew/drc/drc_rule_parser.cpp
@@ -65,10 +65,8 @@ void DRC_RULES_PARSER::initLayerMap()
}
-void DRC_RULES_PARSER::Parse( std::vector& aSelectors,
- std::vector& aRules )
+void DRC_RULES_PARSER::Parse( std::vector& aRules )
{
- std::vector< std::pair > selectorRules;
bool haveVersion = false;
for( T token = NextTok(); token != T_EOF; token = NextTok() )
@@ -91,15 +89,6 @@ void DRC_RULES_PARSER::Parse( std::vector& aSelectors,
NeedRIGHT();
break;
- case T_selector:
- {
- wxString ruleName;
-
- aSelectors.push_back( parseDRC_SELECTOR( &ruleName ) );
- selectorRules.emplace_back( aSelectors.back(), ruleName );
- }
- break;
-
case T_rule:
aRules.push_back( parseDRC_RULE() );
break;
@@ -108,118 +97,6 @@ void DRC_RULES_PARSER::Parse( std::vector& aSelectors,
Expecting( "selector or rule" );
}
}
-
- // Hook up the selectors to their rules
- std::map ruleMap;
-
- for( DRC_RULE* rule : aRules )
- ruleMap[ rule->m_Name ] = rule;
-
- for( const std::pair& entry : selectorRules )
- {
- if( ruleMap.count( entry.second ) )
- {
- entry.first->m_Rule = ruleMap[ entry.second ];
- }
- else
- {
- wxString errText = wxString::Format( _( "Rule \"%s\" not found." ), entry.second );
- THROW_PARSE_ERROR( errText, CurSource(), "", 0, 0 );
- }
- }
-}
-
-
-DRC_SELECTOR* DRC_RULES_PARSER::parseDRC_SELECTOR( wxString* aRuleName )
-{
- NETCLASSES& netclasses = m_board->GetDesignSettings().GetNetClasses();
- DRC_SELECTOR* selector = new DRC_SELECTOR();
- T token;
-
- for( token = NextTok(); token != T_RIGHT; token = NextTok() )
- {
- if( token != T_LEFT )
- Expecting( T_LEFT );
-
- token = NextTok();
-
- switch( token )
- {
- case T_match_netclass:
- {
- NeedSYMBOL();
- NETCLASSPTR netclass = netclasses.Find( FromUTF8() );
-
- if( netclass )
- {
- selector->m_MatchNetclasses.push_back( std::move( netclass ) );
- }
- else
- {
- // Interesting situation here: if we don't inform the user they may have a typo
- // and can't figure out why their rules don't work.
- // If we do tell them then it gets really noisy if they're using a single rule
- // file for a class of board.
- }
-
- NeedRIGHT();
- }
- break;
-
- case T_match_type:
- switch( NextTok() )
- {
- case T_track: selector->m_MatchTypes.push_back( PCB_TRACE_T ); break;
- case T_via: selector->m_MatchTypes.push_back( PCB_LOCATE_STDVIA_T ); break;
- case T_micro_via: selector->m_MatchTypes.push_back( PCB_LOCATE_UVIA_T ); break;
- case T_buried_via: selector->m_MatchTypes.push_back( PCB_LOCATE_BBVIA_T ); break;
- case T_pad: selector->m_MatchTypes.push_back( PCB_PAD_T ); break;
- case T_zone: selector->m_MatchTypes.push_back( PCB_ZONE_AREA_T ); break;
- case T_text: selector->m_MatchTypes.push_back( PCB_LOCATE_TEXT_T ); break;
- case T_graphic: selector->m_MatchTypes.push_back( PCB_LOCATE_GRAPHIC_T ); break;
- case T_hole: selector->m_MatchTypes.push_back( PCB_LOCATE_HOLE_T ); break;
- case T_npth: selector->m_MatchTypes.push_back( PCB_LOCATE_NPTH_T ); break;
- case T_pth: selector->m_MatchTypes.push_back( PCB_LOCATE_PTH_T ); break;
- case T_board_edge: selector->m_MatchTypes.push_back( PCB_LOCATE_BOARD_EDGE_T ); break;
- default: Expecting( "track, via, micro_via, buried_via, pad, zone, text, "
- "graphic, hole, npth, pth, or board_edge" );
- }
- NeedRIGHT();
- break;
-
- case T_match_layer:
- NeedSYMBOL();
-
- if( m_layerMap.count( curText ) )
- {
- selector->m_MatchLayers.push_back( m_layerMap[ curText ] );
- }
- else
- {
- wxString errText = wxString::Format( _( "Layer \"%s\" not found." ),
- wxString( curText ) );
- THROW_PARSE_ERROR( errText, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
- }
-
- NeedRIGHT();
- break;
-
- case T_match_area:
- // TODO
- break;
-
- case T_rule:
- NeedSYMBOL();
- *aRuleName = FromUTF8();
- NeedRIGHT();
- break;
-
- default:
- Expecting( "match_netclass, match_type, match_layer, match_area, or rule" );
- }
- }
-
- return selector;
}
@@ -269,7 +146,15 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE()
case T_condition:
NeedSYMBOL();
- rule->m_Condition = FromUTF8();
+ rule->m_Condition.m_Expression = FromUTF8();
+
+ if( !rule->m_Condition.Compile() )
+ {
+ LIBEVAL::ERROR_STATUS error = rule->m_Condition.GetCompilationError();
+ THROW_PARSE_ERROR( error.message, CurSource(), CurLine(), CurLineNumber(),
+ CurOffset() + error.srcPos );
+ }
+
NeedRIGHT();
break;
diff --git a/pcbnew/drc/drc_rule_parser.h b/pcbnew/drc/drc_rule_parser.h
index a8d4c80025..8a7864d4cf 100644
--- a/pcbnew/drc/drc_rule_parser.h
+++ b/pcbnew/drc/drc_rule_parser.h
@@ -43,13 +43,11 @@ public:
DRC_RULES_PARSER( BOARD* aBoard, const wxString& aSource, const wxString& aSourceDescr );
DRC_RULES_PARSER( BOARD* aBoard, FILE* aFile, const wxString& aFilename );
- void Parse( std::vector& aSelectors, std::vector& aRules );
+ void Parse( std::vector& aRules );
private:
void initLayerMap();
- DRC_SELECTOR* parseDRC_SELECTOR( wxString* aRuleName );
-
DRC_RULE* parseDRC_RULE();
void parseConstraint( DRC_RULE* aRule );
diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp
index e4667371db..2eed0b4c2c 100644
--- a/pcbnew/pcb_edit_frame.cpp
+++ b/pcbnew/pcb_edit_frame.cpp
@@ -653,7 +653,7 @@ void PCB_EDIT_FRAME::ShowBoardSetupDialog( const wxString& aInitialPage, const w
if( dlg.ShowQuasiModal() == wxID_OK )
{
- Prj().GetProjectFile().NetSettings().ResolveNetClassAssignments();
+ Prj().GetProjectFile().NetSettings().ResolveNetClassAssignments( true );
GetBoard()->SynchronizeNetsAndNetClasses();
GetBoard()->GetDesignSettings().SetCurrentNetClass( NETCLASS::Default );
diff --git a/pcbnew/pcb_expr_evaluator.cpp b/pcbnew/pcb_expr_evaluator.cpp
index a99b43aed7..bb9246f0d7 100644
--- a/pcbnew/pcb_expr_evaluator.cpp
+++ b/pcbnew/pcb_expr_evaluator.cpp
@@ -23,92 +23,94 @@
#include
-
+#include
#include "class_board.h"
#include "pcb_expr_evaluator.h"
class PCB_EXPR_BUILTIN_FUNCTIONS
{
- public:
+public:
- using FPTR = LIBEVAL::UCODE::FUNC_PTR;
+ using FPTR = LIBEVAL::UCODE::FUNC_PTR;
- PCB_EXPR_BUILTIN_FUNCTIONS();
+ PCB_EXPR_BUILTIN_FUNCTIONS();
- static PCB_EXPR_BUILTIN_FUNCTIONS& Instance()
+ static PCB_EXPR_BUILTIN_FUNCTIONS& Instance()
+ {
+ static PCB_EXPR_BUILTIN_FUNCTIONS self;
+ return self;
+ }
+
+ std::string tolower( const std::string& str ) const
+ {
+ std::string rv;
+ std::transform( str.begin(), str.end(), rv.begin(), ::tolower );
+ return rv;
+ }
+
+ FPTR Get( const std::string &name ) const
+ {
+ auto it = m_funcs.find( name );
+
+ if( it == m_funcs.end() )
+ return nullptr;
+
+ return it->second;
+ }
+
+private:
+ std::map m_funcs;
+
+ static void onLayer( LIBEVAL::UCODE* aUcode, LIBEVAL::UCODE::CONTEXT* aCtx, void *self )
+ {
+ LIBEVAL::VALUE* arg = aCtx->Pop();
+ PCB_EXPR_VAR_REF* vref = static_cast( self );
+ PCB_LAYER_ID layer = ENUM_MAP::Instance().ToEnum( arg->AsString() );
+ BOARD_ITEM* item = vref->GetObject( aUcode );
+ LIBEVAL::VALUE* rv = aCtx->AllocValue();
+
+ rv->Set( item->IsOnLayer( layer ) ? 1.0 : 0.0 );
+ aCtx->Push( rv );
+ }
+
+ static void isPlated( LIBEVAL::UCODE* aUcode, LIBEVAL::UCODE::CONTEXT* aCtx, void *self )
+ {
+ PCB_EXPR_VAR_REF* vref = static_cast( self );
+ BOARD_ITEM* item = vref->GetObject( aUcode );
+ bool result = false;
+
+ if( item->Type() == PCB_PAD_T )
{
- static PCB_EXPR_BUILTIN_FUNCTIONS self;
- return self;
+ D_PAD* pad = static_cast( item );
+ result = pad->GetAttribute() == PAD_ATTRIB_STANDARD;
}
- std::string tolower( const std::string str ) const
- {
- std::string rv;
- std::transform(str.begin(),
- str.end(),
- rv.begin(),
- ::tolower);
- return rv;
- }
-
- FPTR Get( const std::string &name ) const
- {
- auto it = m_funcs.find( name );
-
- if( it == m_funcs.end() )
- return nullptr;
-
- return it->second;
- }
-
- private:
-
- std::map m_funcs;
-
- static void onLayer( LIBEVAL::UCODE* aUcode, LIBEVAL::UCODE::CONTEXT* aCtx, void *self )
- {
- auto arg = aCtx->Pop();
- auto vref = static_cast( self );
- auto conv = ENUM_MAP::Instance();
- bool value = vref->GetObject(aUcode)->IsOnLayer( conv.ToEnum( arg->AsString() ) );
- auto rv = aCtx->AllocValue();
- rv->Set( value ? 1.0 : 0.0 );
- aCtx->Push( rv );
- }
-
- static void isPlated( LIBEVAL::UCODE* aUcode, LIBEVAL::UCODE::CONTEXT* aCtx, void *self )
- {
- auto vref = static_cast( self );
- auto item = vref->GetObject(aUcode);
- bool result = false;
- if( item->Type() == PCB_PAD_T )
- {
- auto pad = static_cast( item );
- result = pad->GetAttribute() == PAD_ATTRIB_STANDARD;
- }
- auto rv = aCtx->AllocValue();
- rv->Set( result ? 1.0 : 0.0 );
- aCtx->Push( rv );
- }
+ LIBEVAL::VALUE* rv = aCtx->AllocValue();
+ rv->Set( result ? 1.0 : 0.0 );
+ aCtx->Push( rv );
+ }
};
+
PCB_EXPR_BUILTIN_FUNCTIONS::PCB_EXPR_BUILTIN_FUNCTIONS()
{
m_funcs[ "onlayer" ] = onLayer;
m_funcs[ "isplated" ] = isPlated;
}
+
BOARD_ITEM* PCB_EXPR_VAR_REF::GetObject( LIBEVAL::UCODE* aUcode ) const
{
- auto ucode = static_cast( aUcode );
- auto item = ucode->GetItem( m_itemIndex );
+ const PCB_EXPR_UCODE* ucode = static_cast( aUcode );
+ BOARD_ITEM* item = ucode->GetItem( m_itemIndex );
return item;
}
+
LIBEVAL::VALUE PCB_EXPR_VAR_REF::GetValue( LIBEVAL::UCODE* aUcode )
{
- auto item = GetObject( aUcode );
- auto it = m_matchingTypes.find( TYPE_HASH( *item ) );
+ BOARD_ITEM* item = const_cast( GetObject( aUcode ) );
+ auto it = m_matchingTypes.find( TYPE_HASH( *item ) );
if( it == m_matchingTypes.end() )
{
@@ -128,7 +130,9 @@ LIBEVAL::VALUE PCB_EXPR_VAR_REF::GetValue( LIBEVAL::UCODE* aUcode )
{
//printf("item %p Get string '%s'\n", item, (const char*) it->second->Name().c_str() );
str = item->Get( it->second );
- } else {
+ }
+ else
+ {
const auto& any = item->Get( it->second );
any.GetAs( &str );
//printf("item %p get enum: '%s'\n", item , (const char*) str.c_str() );
@@ -138,26 +142,42 @@ LIBEVAL::VALUE PCB_EXPR_VAR_REF::GetValue( LIBEVAL::UCODE* aUcode )
}
}
-LIBEVAL::UCODE::FUNC_PTR PCB_EXPR_UCODE::createFuncCall( LIBEVAL::COMPILER* aCompiler, const std::string& name )
+
+LIBEVAL::UCODE::FUNC_PTR PCB_EXPR_UCODE::createFuncCall( LIBEVAL::COMPILER* aCompiler,
+ const std::string& name )
{
- auto registry = PCB_EXPR_BUILTIN_FUNCTIONS::Instance();
- auto f = registry.Get( name );
+ PCB_EXPR_BUILTIN_FUNCTIONS& registry = PCB_EXPR_BUILTIN_FUNCTIONS::Instance();
+
+ auto f = registry.Get( boost::to_lower_copy( name ) );
return f;
}
+
LIBEVAL::VAR_REF* PCB_EXPR_UCODE::createVarRef( LIBEVAL::COMPILER *aCompiler,
- const std::string& var, const std::string& field )
+ const std::string& var, const std::string& field )
{
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
+ PCB_EXPR_VAR_REF* vref = nullptr;
- auto classes = propMgr.GetAllClasses();
- auto vref = new PCB_EXPR_VAR_REF( var == "A" ? 0 : 1 );
+ if( var == "A" )
+ {
+ vref = new PCB_EXPR_VAR_REF( 0 );
+ }
+ else if( var == "B" )
+ {
+ vref = new PCB_EXPR_VAR_REF( 1 );
+ }
+ else
+ {
+ aCompiler->ReportError( "var" );
+ return vref;
+ }
if( field.empty() ) // return reference to base object
return vref;
- for( auto cls : classes )
+ for( const PROPERTY_MANAGER::CLASS_INFO& cls : propMgr.GetAllClasses() )
{
if( propMgr.IsOfType( cls.type, TYPE_HASH( BOARD_ITEM ) ) )
{
@@ -167,10 +187,15 @@ LIBEVAL::VAR_REF* PCB_EXPR_UCODE::createVarRef( LIBEVAL::COMPILER *aCompiler,
{
//printf("Field '%s' class %s ptr %p haschoices %d typeid %s\n", field.c_str(), (const char *) cls.name.c_str(), prop, !!prop->HasChoices(), typeid(*prop).name() );
vref->AddAllowedClass( cls.type, prop );
+
if( prop->TypeHash() == TYPE_HASH( int ) )
+ {
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 );
@@ -186,6 +211,9 @@ LIBEVAL::VAR_REF* PCB_EXPR_UCODE::createVarRef( LIBEVAL::COMPILER *aCompiler,
}
}
+ if( vref->GetType() == LIBEVAL::VT_UNDEFINED )
+ aCompiler->ReportError( "field" );
+
return vref;
}
@@ -204,19 +232,16 @@ public:
return pcbUnits;
}
- virtual double Convert( const std::string aString, int unitId ) const override
+ virtual double Convert( const std::string& aString, int unitId ) const override
{
double v = atof( aString.c_str() );
+
switch( unitId )
{
- case 0:
- return Mils2iu( v );
- case 1:
- return Millimeter2iu( v );
- case 2:
- return Mils2iu( v * 1000.0 );
- default:
- return v;
+ case 0: return Mils2iu( v );
+ case 1: return Millimeter2iu( v );
+ case 2: return Mils2iu( v * 1000.0 );
+ default: return v;
}
};
};
diff --git a/pcbnew/pcb_expr_evaluator.h b/pcbnew/pcb_expr_evaluator.h
index b124b35ab3..6e94fae92d 100644
--- a/pcbnew/pcb_expr_evaluator.h
+++ b/pcbnew/pcb_expr_evaluator.h
@@ -66,6 +66,7 @@ class PCB_EXPR_VAR_REF : public LIBEVAL::VAR_REF
public:
PCB_EXPR_VAR_REF( int aItemIndex ) :
m_itemIndex( aItemIndex ),
+ m_type( LIBEVAL::VT_UNDEFINED ),
m_isEnum( false )
{
//printf("*** createVarRef %p %d\n", this, aItemIndex );
@@ -84,7 +85,7 @@ public:
m_matchingTypes[type_hash] = prop;
}
- virtual LIBEVAL::VAR_TYPE_T GetType( LIBEVAL::UCODE* aUcode ) override
+ virtual LIBEVAL::VAR_TYPE_T GetType() override
{
return m_type;
}
@@ -98,7 +99,7 @@ private:
std::unordered_map m_matchingTypes;
int m_itemIndex;
LIBEVAL::VAR_TYPE_T m_type;
- bool m_isEnum;
+ bool m_isEnum;
};
@@ -116,10 +117,7 @@ public:
~PCB_EXPR_EVALUATOR();
bool Evaluate( const wxString& aExpr );
- int Result() const
- {
- return m_result;
- }
+ int Result() const { return m_result; }
wxString GetErrorString();
private:
diff --git a/qa/drc_proto/drc.cpp b/qa/drc_proto/drc.cpp
index 055aaac81d..0a8de43e97 100644
--- a/qa/drc_proto/drc.cpp
+++ b/qa/drc_proto/drc.cpp
@@ -186,7 +186,6 @@ bool DRC::LoadRules()
if( rulesFile.FileExists() )
{
- m_ruleSelectors.clear();
m_rules.clear();
FILE* fp = wxFopen( rulesFilepath, wxT( "rt" ) );
@@ -196,12 +195,11 @@ bool DRC::LoadRules()
try
{
DRC_RULES_PARSER parser( m_pcb, fp, rulesFilepath );
- parser.Parse( m_ruleSelectors, m_rules );
+ parser.Parse( m_rules );
}
catch( PARSE_ERROR& pe )
{
// Don't leave possibly malformed stuff around for us to trip over
- m_ruleSelectors.clear();
m_rules.clear();
wxSafeYield( m_editFrame );
diff --git a/qa/drc_proto/drc_rule.cpp b/qa/drc_proto/drc_rule.cpp
index 5302d73767..c321e78a48 100644
--- a/qa/drc_proto/drc_rule.cpp
+++ b/qa/drc_proto/drc_rule.cpp
@@ -47,23 +47,26 @@ test::DRC_RULE_CONDITION::DRC_RULE_CONDITION()
m_ucode = nullptr;
}
+
test::DRC_RULE_CONDITION::~DRC_RULE_CONDITION()
{
- if( m_ucode )
- delete m_ucode;
+ delete m_ucode;
}
-bool test::DRC_RULE_CONDITION::EvaluateFor( BOARD_ITEM* aItemA, BOARD_ITEM* aItemB )
+
+bool test::DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB )
{
- m_ucode->SetItems( aItemA, aItemB );
+ m_ucode->SetItems( const_cast( aItemA ), const_cast( aItemB ) );
// fixme: handle error conditions
return m_ucode->Run()->AsDouble() != 0.0;
}
+
bool test::DRC_RULE_CONDITION::Compile()
{
PCB_EXPR_COMPILER compiler;
+
if (!m_ucode)
m_ucode = new PCB_EXPR_UCODE;
@@ -74,11 +77,12 @@ bool test::DRC_RULE_CONDITION::Compile()
m_compileError = compiler.GetErrorStatus();
- printf("Fail: %s", m_compileError.Format().c_str() );
+ printf( "Fail: %s", m_compileError.Format().c_str() );
return false;
}
+
LIBEVAL::ERROR_STATUS test::DRC_RULE_CONDITION::GetCompilationError()
{
return m_compileError;
diff --git a/qa/drc_proto/drc_rule.h b/qa/drc_proto/drc_rule.h
index 669178576d..7b1da87a8d 100644
--- a/qa/drc_proto/drc_rule.h
+++ b/qa/drc_proto/drc_rule.h
@@ -130,7 +130,7 @@ public:
DRC_RULE_CONDITION();
~DRC_RULE_CONDITION();
- bool EvaluateFor( BOARD_ITEM* aItemA, BOARD_ITEM* aItemB );
+ bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB );
bool Compile();
LIBEVAL::ERROR_STATUS GetCompilationError();
@@ -140,7 +140,7 @@ public:
private:
LIBEVAL::ERROR_STATUS m_compileError;
- PCB_EXPR_UCODE* m_ucode;
+ PCB_EXPR_UCODE* m_ucode;
};
diff --git a/qa/libeval_compiler/libeval_compiler_test.cpp b/qa/libeval_compiler/libeval_compiler_test.cpp
index f729743bf8..0c3c9890cd 100644
--- a/qa/libeval_compiler/libeval_compiler_test.cpp
+++ b/qa/libeval_compiler/libeval_compiler_test.cpp
@@ -118,20 +118,20 @@ int main( int argc, char *argv[] )
trackA.SetWidth( Mils2iu( 10 ));
trackB.SetWidth( Mils2iu( 20 ));
- printf("TrkA %p netclass '%s'\n", &trackA, (const char*) trackA.GetNetClassName().c_str() );
- printf("TrkB %p netclass '%s'\n", &trackB, (const char*) trackB.GetNetClassName().c_str() );
+ printf( "TrkA %p netclass '%s'\n", &trackA, (const char*) trackA.GetNetClassName().c_str() );
+ printf( "TrkB %p netclass '%s'\n", &trackB, (const char*) trackB.GetNetClassName().c_str() );
-// testEvalExpr( "A.onlayer(\"F.Cu\") || A.onlayer(\"B.Cu\")", VAL(1.0), false, &trackA, &trackB );
- testEvalExpr( "A.type == \"Pad\" && B.type == \"Pad\" && (A.onLayer(\"F.Cu\"))",VAL(0.0), false, &trackA, &trackB );
+// testEvalExpr( "A.onlayer('F.Cu') || A.onlayer('B.Cu')", VAL( 1.0 ), false, &trackA, &trackB );
+ testEvalExpr( "A.type == 'Pad' && B.type == 'Pad' && (A.onLayer('F.Cu'))", VAL( 0.0 ), false, &trackA, &trackB );
return 0;
- testEvalExpr( "A.Width > B.Width", VAL(0.0), false, &trackA, &trackB );
- testEvalExpr( "A.Width + B.Width", VAL(Mils2iu(10) + Mils2iu(20)), false, &trackA, &trackB );
+ testEvalExpr( "A.Width > B.Width", VAL( 0.0 ), false, &trackA, &trackB );
+ testEvalExpr( "A.Width + B.Width", VAL( Mils2iu(10) + Mils2iu(20) ), false, &trackA, &trackB );
testEvalExpr( "A.Netclass", VAL( (const char*) trackA.GetNetClassName().c_str() ), false, &trackA, &trackB );
- testEvalExpr( "(A.Netclass == \"HV\") && (B.netclass == \"otherClass\") && (B.netclass != \"F.Cu\")", VAL( 1.0 ), false, &trackA, &trackB );
+ testEvalExpr( "(A.Netclass == 'HV') && (B.netclass == 'otherClass') && (B.netclass != 'F.Cu')", VAL( 1.0 ), false, &trackA, &trackB );
testEvalExpr( "A.Netclass + 1.0", VAL( 1.0 ), false, &trackA, &trackB );
- testEvalExpr( "A.type == \"Track\" && B.type == \"Track\" && A.layer == \"F.Cu\"", VAL(0.0), false, &trackA, &trackB );
- testEvalExpr( "(A.type == \"Track\") && (B.type == \"Track\") && (A.layer == \"F.Cu\")", VAL(0.0), false, &trackA, &trackB );
+ testEvalExpr( "A.type == 'Track' && B.type == 'Track' && A.layer == 'F.Cu'", VAL( 0.0 ), false, &trackA, &trackB );
+ testEvalExpr( "(A.type == 'Track') && (B.type == 'Track') && (A.layer == 'F.Cu')", VAL( 0.0 ), false, &trackA, &trackB );
return 0;
}