#include "externals.hh" #include "common.hh" #include "c-opcomp.hh" #include "c-ops.hh" #include #include #include /*============================================================================*/ namespace { void WriteSRDError( T_StringBuilder& sb , ebcl::T_SRDError const& error ) { sb << error.location( ) << " - " << error.error( ) << "\n"; } void DumpSRDErrors( T_String const& header , T_Array< ebcl::T_SRDError > const& errors ) { T_StringBuilder sb; sb << "=============================================================\n" << header << '\n' << "-------------------------------------------------------------\n"; for ( auto& error : errors ) { WriteSRDError( sb , error ); } sb << "=============================================================\n" << '\0'; printf( "%s" , sb.data( ) ); } } // namespace /*= T_ScriptManager ============================================================*/ T_ScriptManager::T_ScriptManager( ) noexcept : watcher_( Common::Watcher( ) , [this](){ loadScript( ); } ) , parser_( ) , compiler_( ) { Common::Project( ).addListener( this ); } T_ScriptManager::~T_ScriptManager( ) { Common::Project( ).removeListener( this ); } void T_ScriptManager::enable( ) noexcept { if ( !enabled_ ) { enabled_ = true; projectPathChanged( ); } } void T_ScriptManager::projectPathChanged( ) noexcept { path_ = Common::Project( ).pathOf( "demo.srd" ); if ( enabled_ ) { watcher_.clear( ); watcher_.watch( path_.toString( ) ); loadScript( ); } } /*----------------------------------------------------------------------------*/ void T_ScriptManager::loadScript( ) noexcept { output_.clear( ); errors_.clear( ); using namespace ebcl; T_File input( path_.toString( ) , E_FileMode::READ_ONLY ); try { input.open( ); } catch ( X_StreamError const& e ) { T_StringBuilder sb; sb << "could not open: " << e.what( ); if ( e.code( ) == ebcl::E_StreamError::SYSTEM_ERROR ) { sb << " (error code " << e.systemError( ) << ")"; } errors_.addNew( std::move( sb ) , T_SRDLocation{ path_.toString( ) , 1 , 1 } ); DumpSRDErrors( "Script not found" , errors_ ); return; } // Load SRD data T_SRDMemoryTarget srdOut; srdOut.clearComments( true ).clearFlushToken( true ); const auto fn{ path_.makeRelative( Common::Project( ).basePath( ) ) }; try { T_SRDTextReader srdReader{ srdOut }; T_FileInputStream fis{ input }; srdReader.read( fn.toString( ) , fis ); } catch ( X_StreamError const& e ) { T_StringBuilder sb; sb << "could not load: " << e.what( ); if ( e.code( ) == ebcl::E_StreamError::SYSTEM_ERROR ) { sb << " (error code " << e.systemError( ) << ")"; } errors_.addNew( std::move( sb ) , T_SRDLocation{ path_.toString( ) , 1 , 1 } ); DumpSRDErrors( "Script not loaded" , errors_ ); return; } catch ( X_SRDErrors const& e ) { T_StringBuilder sb; const auto nErrors( e.errors.size( ) ); errors_.ensureCapacity( nErrors ); for ( auto i = 0u ; i < nErrors ; i ++ ) { errors_.add( e.errors[ i ] ); } DumpSRDErrors( "Script not loaded" , errors_ ); return; } // Parse the fuck const bool parsed{ parser_.parse( path_ , srdOut.list( ) ) }; auto pOut{ parser_.result( ) }; const auto nf{ pOut->files.size( ) }; if ( nf ) { watcher_.clear( ); for ( auto i = 0u ; i < nf ; i ++ ) { watcher_.watch( pOut->files[ i ] ); } } if ( !parsed ) { errors_.addAll( parser_.errors( ) ); DumpSRDErrors( "Parse errors" , errors_ ); return; } output_ = compiler_.compile( *pOut ); // FIXME - errors from compiler printf( "Script loaded & compiled\n" ); }