diff --git a/common/libeval_compiler/libeval_compiler.cpp b/common/libeval_compiler/libeval_compiler.cpp index e51a78929e..8cb2060295 100644 --- a/common/libeval_compiler/libeval_compiler.cpp +++ b/common/libeval_compiler/libeval_compiler.cpp @@ -1038,7 +1038,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext ) reportError( CST_CODEGEN, msg, node->srcPos - (int) node->value.str->length() ); } - node->SetUop( TR_UOP_PUSH_VALUE, std::move( vref ) ); + node->SetUop( TR_UOP_PUSH_VAR, std::move( vref ) ); node->isTerminal = true; break; } @@ -1090,10 +1090,12 @@ void UOP::Exec( CONTEXT* ctx ) { case TR_UOP_PUSH_VAR: { - VALUE* value = ctx->AllocValue(); + VALUE* value = nullptr; if( m_ref ) - value->Set( m_ref->GetValue( ctx ) ); + value = ctx->StoreValue( m_ref->GetValue( ctx ) ); + else + value = ctx->AllocValue(); ctx->Push( value ); } @@ -1162,10 +1164,20 @@ void UOP::Exec( CONTEXT* ctx ) result = arg1Value > arg2Value ? 1 : 0; break; case TR_OP_EQUAL: - result = arg1 && arg2 && arg1->EqualTo( ctx, arg2 ) ? 1 : 0; + if( !arg1 || !arg2 ) + result = arg1 == arg2 ? 1 : 0; + else if( arg2->GetType() == VT_UNDEFINED ) + result = arg2->EqualTo( ctx, arg1 ) ? 1 : 0; + else + result = arg1->EqualTo( ctx, arg2 ) ? 1 : 0; break; case TR_OP_NOT_EQUAL: - result = arg1 && arg2 && arg1->NotEqualTo( ctx, arg2 ) ? 1 : 0; + if( !arg1 || !arg2 ) + result = arg1 != arg2 ? 1 : 0; + else if( arg2->GetType() == VT_UNDEFINED ) + result = arg2->NotEqualTo( ctx, arg1 ) ? 1 : 0; + else + result = arg1->NotEqualTo( ctx, arg2 ) ? 1 : 0; break; case TR_OP_BOOL_AND: result = arg1Value != 0.0 && arg2Value != 0.0 ? 1 : 0; diff --git a/include/libeval_compiler/libeval_compiler.h b/include/libeval_compiler/libeval_compiler.h index 1edf34373f..3fd1ed0ba1 100644 --- a/include/libeval_compiler/libeval_compiler.h +++ b/include/libeval_compiler/libeval_compiler.h @@ -296,7 +296,7 @@ public: virtual ~VAR_REF() {}; virtual VAR_TYPE_T GetType() const = 0; - virtual VALUE GetValue( CONTEXT* aCtx ) = 0; + virtual VALUE* GetValue( CONTEXT* aCtx ) = 0; }; @@ -312,7 +312,7 @@ public: virtual ~CONTEXT() { - for( auto &v : m_ownedValues ) + for( VALUE* v : m_ownedValues ) { delete v; } @@ -324,6 +324,12 @@ public: return m_ownedValues.back(); } + VALUE* StoreValue( VALUE* aValue ) + { + m_ownedValues.emplace_back( aValue ); + return m_ownedValues.back(); + } + void Push( VALUE* v ) { m_stack[ m_stackPtr++ ] = v; diff --git a/pcbnew/dialogs/panel_setup_rules_help.md b/pcbnew/dialogs/panel_setup_rules_help.md index fd6c53771b..f0ce53e3d4 100644 --- a/pcbnew/dialogs/panel_setup_rules_help.md +++ b/pcbnew/dialogs/panel_setup_rules_help.md @@ -48,6 +48,14 @@ * zone\_connection Note: `clearance` and `hole_clearance` rules are not run against items of the same net; `physical_clearance` and `physical_hole_clearance` rules are. +

+ +### Items + + * `A`    _the first (or only) item under test_ + * `B`    _the second item under test (for binary tests)_ + * `L`    _the layer currently under test_ +
### Item Types diff --git a/pcbnew/dialogs/panel_setup_rules_help_md.h b/pcbnew/dialogs/panel_setup_rules_help_md.h index dbdeb61019..2b56161f09 100644 --- a/pcbnew/dialogs/panel_setup_rules_help_md.h +++ b/pcbnew/dialogs/panel_setup_rules_help_md.h @@ -49,6 +49,14 @@ _HKI( "### Top-level Clauses\n" " * zone\\_connection\n" "\n" "Note: `clearance` and `hole_clearance` rules are not run against items of the same net; `physical_clearance` and `physical_hole_clearance` rules are.\n" +"

\n" +"\n" +"### Items\n" +"\n" +" * `A`    _the first (or only) item under test_\n" +" * `B`    _the second item under test (for binary tests)_\n" +" * `L`    _the layer currently under test_\n" +"\n" "
\n" "\n" "### Item Types\n" diff --git a/pcbnew/pcb_expr_evaluator.cpp b/pcbnew/pcb_expr_evaluator.cpp index c5a5af095a..5442b2dcdc 100644 --- a/pcbnew/pcb_expr_evaluator.cpp +++ b/pcbnew/pcb_expr_evaluator.cpp @@ -992,7 +992,8 @@ class PCB_LAYER_VALUE : public LIBEVAL::VALUE { public: PCB_LAYER_VALUE( PCB_LAYER_ID aLayer ) : - LIBEVAL::VALUE( double( aLayer ) ) + LIBEVAL::VALUE( LayerName( aLayer ) ), + m_layer( aLayer ) {}; virtual bool EqualTo( LIBEVAL::CONTEXT* aCtx, const VALUE* b ) const override @@ -1025,25 +1026,25 @@ public: mask = i->second; } - PCB_LAYER_ID layerId = ToLAYER_ID( (int) AsDouble() ); - - return mask.Contains( layerId ); + return mask.Contains( m_layer ); } + +protected: + PCB_LAYER_ID m_layer; }; -LIBEVAL::VALUE PCB_EXPR_VAR_REF::GetValue( LIBEVAL::CONTEXT* aCtx ) +LIBEVAL::VALUE* PCB_EXPR_VAR_REF::GetValue( LIBEVAL::CONTEXT* aCtx ) { + PCB_EXPR_CONTEXT* context = static_cast( aCtx ); + if( m_itemIndex == 2 ) - { - PCB_EXPR_CONTEXT* context = static_cast( aCtx ); - return PCB_LAYER_VALUE( context->GetLayer() ); - } + return new PCB_LAYER_VALUE( context->GetLayer() ); BOARD_ITEM* item = GetObject( aCtx ); if( !item ) - return LIBEVAL::VALUE(); + return new LIBEVAL::VALUE(); auto it = m_matchingTypes.find( TYPE_HASH( *item ) ); @@ -1053,12 +1054,12 @@ LIBEVAL::VALUE PCB_EXPR_VAR_REF::GetValue( LIBEVAL::CONTEXT* aCtx ) // simpler "A.Via_Type == 'buried'" is perfectly clear. Instead, return an undefined // value when the property doesn't appear on a particular object. - return LIBEVAL::VALUE(); + return new LIBEVAL::VALUE(); } else { if( m_type == LIBEVAL::VT_NUMERIC ) - return LIBEVAL::VALUE( (double) item->Get( it->second ) ); + return new LIBEVAL::VALUE( (double) item->Get( it->second ) ); else { wxString str; @@ -1066,7 +1067,7 @@ LIBEVAL::VALUE PCB_EXPR_VAR_REF::GetValue( LIBEVAL::CONTEXT* aCtx ) if( !m_isEnum ) { str = item->Get( it->second ); - return LIBEVAL::VALUE( str ); + return new LIBEVAL::VALUE( str ); } else { @@ -1074,45 +1075,50 @@ LIBEVAL::VALUE PCB_EXPR_VAR_REF::GetValue( LIBEVAL::CONTEXT* aCtx ) bool valid = any.GetAs( &str ); if( valid ) - return LIBEVAL::VALUE( str ); + { + if( it->second->Name() == wxT( "Layer" ) ) + return new PCB_LAYER_VALUE( context->GetBoard()->GetLayerID( str ) ); + else + return new LIBEVAL::VALUE( str ); + } } - return LIBEVAL::VALUE(); + return new LIBEVAL::VALUE(); } } } -LIBEVAL::VALUE PCB_EXPR_NETCLASS_REF::GetValue( LIBEVAL::CONTEXT* aCtx ) +LIBEVAL::VALUE* PCB_EXPR_NETCLASS_REF::GetValue( LIBEVAL::CONTEXT* aCtx ) { BOARD_CONNECTED_ITEM* item = dynamic_cast( GetObject( aCtx ) ); if( !item ) - return LIBEVAL::VALUE(); + return new LIBEVAL::VALUE(); - return LIBEVAL::VALUE( item->GetEffectiveNetClass()->GetName() ); + return new LIBEVAL::VALUE( item->GetEffectiveNetClass()->GetName() ); } -LIBEVAL::VALUE PCB_EXPR_NETNAME_REF::GetValue( LIBEVAL::CONTEXT* aCtx ) +LIBEVAL::VALUE* PCB_EXPR_NETNAME_REF::GetValue( LIBEVAL::CONTEXT* aCtx ) { BOARD_CONNECTED_ITEM* item = dynamic_cast( GetObject( aCtx ) ); if( !item ) - return LIBEVAL::VALUE(); + return new LIBEVAL::VALUE(); - return LIBEVAL::VALUE( item->GetNetname() ); + return new LIBEVAL::VALUE( item->GetNetname() ); } -LIBEVAL::VALUE PCB_EXPR_TYPE_REF::GetValue( LIBEVAL::CONTEXT* aCtx ) +LIBEVAL::VALUE* PCB_EXPR_TYPE_REF::GetValue( LIBEVAL::CONTEXT* aCtx ) { BOARD_ITEM* item = GetObject( aCtx ); if( !item ) - return LIBEVAL::VALUE(); + return new LIBEVAL::VALUE(); - return LIBEVAL::VALUE( ENUM_MAP::Instance().ToString( item->Type() ) ); + return new LIBEVAL::VALUE( ENUM_MAP::Instance().ToString( item->Type() ) ); } diff --git a/pcbnew/pcb_expr_evaluator.h b/pcbnew/pcb_expr_evaluator.h index a3eb1fb611..d9e110210e 100644 --- a/pcbnew/pcb_expr_evaluator.h +++ b/pcbnew/pcb_expr_evaluator.h @@ -103,7 +103,7 @@ public: m_matchingTypes[type_hash] = prop; } - virtual LIBEVAL::VALUE GetValue( LIBEVAL::CONTEXT* aCtx ) override; + LIBEVAL::VALUE* GetValue( LIBEVAL::CONTEXT* aCtx ) override; BOARD_ITEM* GetObject( const LIBEVAL::CONTEXT* aCtx ) const; @@ -126,7 +126,7 @@ public: //printf("*** CreateVarRef %p %d\n", this, aItemIndex ); } - LIBEVAL::VALUE GetValue( LIBEVAL::CONTEXT* aCtx ) override; + LIBEVAL::VALUE* GetValue( LIBEVAL::CONTEXT* aCtx ) override; }; @@ -141,7 +141,7 @@ public: //printf("*** CreateVarRef %p %d\n", this, aItemIndex ); } - LIBEVAL::VALUE GetValue( LIBEVAL::CONTEXT* aCtx ) override; + LIBEVAL::VALUE* GetValue( LIBEVAL::CONTEXT* aCtx ) override; }; @@ -155,7 +155,7 @@ public: //printf("*** CreateVarRef %p %d\n", this, aItemIndex ); } - LIBEVAL::VALUE GetValue( LIBEVAL::CONTEXT* aCtx ) override; + LIBEVAL::VALUE* GetValue( LIBEVAL::CONTEXT* aCtx ) override; };