diff --git a/pcbnew/pcb_expr_evaluator.cpp b/pcbnew/pcb_expr_evaluator.cpp index 7cdecd6241..5b9d24a7e4 100644 --- a/pcbnew/pcb_expr_evaluator.cpp +++ b/pcbnew/pcb_expr_evaluator.cpp @@ -1,14 +1,81 @@ #include #include "class_board.h" - #include "pcb_expr_evaluator.h" + +class PCB_EXPR_BUILTIN_FUNCTIONS +{ + public: + + using FPTR = LIBEVAL::UCODE::FUNC_PTR; + + PCB_EXPR_BUILTIN_FUNCTIONS(); + + 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; + + //printf("Cfc2\n"); + //it->second(nullptr, nullptr, nullptr); + + return it->second; + } + + private: + + std::map m_funcs; + + static void onLayer( LIBEVAL::UCODE* aUcode, LIBEVAL::UCODE::CONTEXT* aCtx, void *self ) + { + + //auto item = ucode->GetItem( self ); + auto arg = aCtx->Pop(); + printf("SP: %d\n", aCtx->SP() ); + + printf("OnLayer('%s') called!\n", arg->AsString().c_str() ); + + auto rv = aCtx->AllocValue(); + rv->Set( 1.0 ); + aCtx->Push( rv ); + } +}; + +PCB_EXPR_BUILTIN_FUNCTIONS::PCB_EXPR_BUILTIN_FUNCTIONS() +{ + m_funcs[ "onlayer" ] = onLayer; + //m_funcs[ "onlayer" ]( nullptr, nullptr, nullptr ); +} + +BOARD_ITEM* PCB_EXPR_VAR_REF::GetObject( LIBEVAL::UCODE* aUcode ) const +{ + auto ucode = static_cast( aUcode ); + auto item = ucode->GetItem( m_itemIndex ); + return item; +} + LIBEVAL::VALUE PCB_EXPR_VAR_REF::GetValue( LIBEVAL::UCODE* aUcode ) { - auto ucode = static_cast( aUcode ); - auto item = ucode->GetItem( m_itemIndex ); - + auto item = GetObject( aUcode ); auto it = m_matchingTypes.find( TYPE_HASH( *item ) ); if( it == m_matchingTypes.end() ) @@ -24,39 +91,71 @@ LIBEVAL::VALUE PCB_EXPR_VAR_REF::GetValue( LIBEVAL::UCODE* aUcode ) return LIBEVAL::VALUE( (double) item->Get( it->second ) ); else { - wxString str = item->Get( it->second ); - //printf("item %p GetStr '%s'\n", item, (const char*) str.c_str()); + wxString str; + if( !m_isEnum ) + { + //printf("item %p Get string '%s'\n", item, (const char*) it->second->Name().c_str() ); + str = item->Get( it->second ); + } else { + const auto& any = item->Get( it->second ); + any.GetAs( &str ); + //printf("item %p get enum: '%s'\n", item , (const char*) str.c_str() ); + } return LIBEVAL::VALUE( (const char*) str.c_str() ); } } } +LIBEVAL::UCODE::FUNC_PTR PCB_EXPR_UCODE::createFuncCall( LIBEVAL::COMPILER* aCompiler, const std::string& name ) +{ + auto registry = PCB_EXPR_BUILTIN_FUNCTIONS::Instance(); + + //printf("CreateFCall '%s' found %d\n", name.c_str(), registry.Get(name) != nullptr ? 1 : 0 ); + + auto f = registry.Get( name ); + //printf("Cfc3\n"); + //f(nullptr,nullptr,nullptr); + + return f; +} + LIBEVAL::VAR_REF* PCB_EXPR_UCODE::createVarRef( LIBEVAL::COMPILER *aCompiler, const std::string& var, const std::string& field ) { - PCB_EXPR_VAR_REF* rv; - PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); auto classes = propMgr.GetAllClasses(); auto vref = new PCB_EXPR_VAR_REF( var == "A" ? 0 : 1 ); + if( field.empty() ) // return reference to base object + return vref; + for( auto cls : classes ) { if( propMgr.IsOfType( cls.type, TYPE_HASH( BOARD_ITEM ) ) ) { PROPERTY_BASE* prop = propMgr.GetProperty( cls.type, field ); + if( prop ) { - //printf("Field '%s' class %s ptr %p\n", field.c_str(), (const char *) cls.name.c_str(), prop ); + //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 ); + vref->SetIsEnum ( true ); + } else { - printf( "Unknown property type\n" ); + (void) 0; // should we do anything here? + //printf("unmatched type for prop '%s'\n", field.c_str() ); + //wxString msg; + //msg.Printf("Unrecognized type for property '%s'", field.c_str() ); + //aCompiler->ReportError( (const char*) msg.c_str() ); } } } diff --git a/pcbnew/pcb_expr_evaluator.h b/pcbnew/pcb_expr_evaluator.h index 9521de893d..edf4e48ddf 100644 --- a/pcbnew/pcb_expr_evaluator.h +++ b/pcbnew/pcb_expr_evaluator.h @@ -19,6 +19,8 @@ public: virtual LIBEVAL::VAR_REF* createVarRef( LIBEVAL::COMPILER *aCompiler, const std::string& var, const std::string& field ) override; + virtual FUNC_PTR createFuncCall( LIBEVAL::COMPILER* aCompiler, const std::string& name ) override; + void SetItems( BOARD_ITEM* a, BOARD_ITEM* b = nullptr ) { m_items[0] = a; @@ -38,11 +40,16 @@ private: class PCB_EXPR_VAR_REF : public LIBEVAL::VAR_REF { public: - PCB_EXPR_VAR_REF( int aItemIndex ) : m_itemIndex( aItemIndex ) + PCB_EXPR_VAR_REF( int aItemIndex ) : + m_itemIndex( aItemIndex ), + m_isEnum( false ) { //printf("*** createVarRef %p %d\n", this, aItemIndex ); } + void SetIsEnum( bool s ) { m_isEnum = s; } + bool IsEnum() const { return m_isEnum; } + void SetType( LIBEVAL::VAR_TYPE_T type ) { m_type = type; @@ -60,10 +67,14 @@ public: virtual LIBEVAL::VALUE GetValue( LIBEVAL::UCODE* aUcode ) override; + + BOARD_ITEM* GetObject( LIBEVAL::UCODE* aUcode ) const; + private: std::unordered_map m_matchingTypes; int m_itemIndex; LIBEVAL::VAR_TYPE_T m_type; + bool m_isEnum; };