Scripting - Includes work!

This commit is contained in:
Emmanuel BENOîT 2017-12-28 10:27:23 +01:00
parent 68f6c49066
commit 542e791199
10 changed files with 164 additions and 56 deletions

2
3rdparty/ebcl vendored

@ -1 +1 @@
Subproject commit 5497856be2761a6f4f1848636304cff134668766
Subproject commit 7b97993448d086a92d9875db2c2815afa249ba65

View file

@ -1,4 +1,6 @@
#include "externals.hh"
#include "common.hh"
#include "c-project.hh"
#include "c-buildcfg.hh"
#include <ebcl/Files.hh>
@ -159,11 +161,12 @@ T_SRDParserConfig BCLInitDefinitions_( ) noexcept
struct T_BCLImpl_
{
const T_String fileName{ T_String::Pooled( "build.srd" ) };
T_SRDParserConfig pConfig;
T_BCLImpl_( ) noexcept;
T_BuildConfigurations load( T_String const& path );
T_BuildConfigurations load( );
};
/*----------------------------------------------------------------------------*/
@ -172,16 +175,16 @@ T_BCLImpl_::T_BCLImpl_( ) noexcept
: pConfig{ BCLInitDefinitions_( ) }
{ }
T_BuildConfigurations T_BCLImpl_::load(
T_String const& path )
T_BuildConfigurations T_BCLImpl_::load( )
{
// TODO: keep errors so we get warnings/notes too
T_SRDParser parser{ pConfig };
T_SRDTextReader srdReader{ parser };
T_File input{ path , E_FileMode::READ_ONLY };
T_File input{ Common::Project( ).pathOf( fileName ) ,
E_FileMode::READ_ONLY };
T_FileInputStream fis{ input };
srdReader.read( path , fis );
srdReader.read( fileName , fis );
return std::move( *parser.getData< T_SharedPtr< T_BuildConfigurations > >( ) );
}
@ -195,8 +198,7 @@ T_BuildConfigurationLoader::T_BuildConfigurationLoader( ) noexcept
{ }
T_BuildConfigurations T_BuildConfigurationLoader::load(
T_String const& path )
T_BuildConfigurations T_BuildConfigurationLoader::load( )
{
return p< T_BCLImpl_ >( ).load( path );
return p< T_BCLImpl_ >( ).load( );
}

View file

@ -50,7 +50,7 @@ struct T_BuildConfigurationLoader : public ebcl::A_PrivateImplementation
// Load build configurations from the specified path; may throw
// X_StreamError or X_SRDErrors
T_BuildConfigurations load( T_String const& path );
T_BuildConfigurations load( );
};
/*----------------------------------------------------------------------------*/

View file

@ -6,7 +6,9 @@
#include "c-syncoverrides.hh"
#include <ebcl/Algorithms.hh>
#include <ebcl/Files.hh>
#include <ebcl/SRDParser.hh>
#include <ebcl/SRDText.hh>
using namespace ebcl;
using namespace opast;
@ -172,8 +174,9 @@ struct T_ParserImpl_
T_SRDParserConfig ovParserConfig;
T_SRDParser ovParser;
T_String curFile;
T_AutoArray< T_String , 32 > inclStack;
T_FSPath curFile;
T_FSPath baseDir;
T_AutoArray< T_FSPath , 32 > inclStack;
T_Visitor< A_Node > visitor{ opast::ASTVisitorBrowser };
T_Visitor< uint32_t , uint32_t > callGraphVisitor{
@ -192,7 +195,8 @@ struct T_ParserImpl_
// ---------------------------------------------------------------------
void main( T_SRDList const& list ) noexcept;
void main( T_FSPath const& file ,
T_SRDList const& list ) noexcept;
// ---------------------------------------------------------------------
@ -221,7 +225,8 @@ struct T_ParserImpl_
// ---------------------------------------------------------------------
bool parseTopLevel( T_SRDList const& list ) noexcept;
void parseTLList( T_SRDList const& funcList ) noexcept;
void parseTLList( T_SRDList const& list ) noexcept;
void parseTLListItem( T_SRDList const& funcList ) noexcept;
void handleInclude( T_SRDToken const& tFileName ) noexcept;
@ -331,8 +336,12 @@ inline T_ParserImpl_::T_ParserImpl_(
{ }
void T_ParserImpl_::main(
T_FSPath const& file ,
T_SRDList const& input ) noexcept
{
assert( file.isAbsolute( ) );
curFile = file.canonical( );
baseDir = file.parent( );
parseTopLevel( input )
&& checkRequiredBlocks( input )
&& checkCalls( )
@ -948,18 +957,24 @@ bool T_ParserImpl_::parseTopLevel(
T_SRDList const& input ) noexcept
{
M_LOGSTR_( "... Generating tree" , 2 );
for ( auto const& t : input ) {
if ( t.type( ) == E_SRDTokenType::LIST && t.list( ).size( ) > 0 ) {
parseTLList( t.list( ) );
} else {
errors.addNew( "top-level list expected" , t.location( ) );
}
}
parseTLList( input );
return errors.empty( );
}
void T_ParserImpl_::parseTLList(
T_SRDList const& input ) noexcept
{
for ( auto const& t : input ) {
if ( t.type( ) == E_SRDTokenType::LIST && t.list( ).size( ) > 0 ) {
parseTLListItem( t.list( ) );
} else {
errors.addNew( "top-level list expected" , t.location( ) );
}
}
}
void T_ParserImpl_::parseTLListItem(
T_SRDList const& input ) noexcept
{
assert( input.size( ) != 0 );
auto const& ft{ input[ 0 ] };
@ -970,7 +985,6 @@ void T_ParserImpl_::parseTLList(
auto const& fw{ ft.stringValue( ) };
if ( fw == "include" ) {
// TODO
if ( input.size( ) == 1 ) {
errors.addNew( "file name expected" ,
ft.location( ) );
@ -999,14 +1013,78 @@ void T_ParserImpl_::handleInclude(
return;
}
if ( !curFile ) {
curFile = tFileName.location( ).source( );
// Resolve included file path
T_FSPath inclPath{ tFileName.stringValue( ) };
if ( !inclPath.isValid( ) ) {
errors.addNew( "invalid file name" ,
tFileName.location( ) );
return;
}
if ( !inclPath.isAbsolute( ) ) {
inclPath = curFile.parent( ) + inclPath;
}
inclPath = inclPath.canonical( );
if ( !inclPath.isUnder( baseDir ) ) {
errors.addNew( "file is not in the project's directory" ,
tFileName.location( ) );
return;
}
// TODO: resolve included file path
// TODO: check for recursive includes
// TODO: load file
// TODO: parse it
// Check for recursive includes
if ( inclStack.contains( inclPath ) ) {
errors.addNew( "recursive file inclusion" ,
tFileName.location( ) );
return;
}
// Load file
const auto relPath{ inclPath.makeRelative( baseDir ) };
T_SRDMemoryTarget srdOut;
{
T_File input{ inclPath , E_FileMode::READ_ONLY };
try {
input.open( );
} catch ( X_StreamError const& e ) {
T_StringBuilder sb;
sb << "could not open '" << relPath << "': " << e.what( );
if ( e.code( ) == E_StreamError::SYSTEM_ERROR ) {
sb << " (error code " << e.systemError( ) << ")";
}
errors.addNew( std::move( sb ) , tFileName.location( ) );
return;
}
srdOut.clearComments( true ).clearFlushToken( true );
try {
T_SRDTextReader srdReader{ srdOut };
T_FileInputStream fis{ input };
srdReader.read( relPath.toString( ) , fis );
} catch ( X_StreamError const& e ) {
T_StringBuilder sb;
sb << "could not read '" << relPath << "': " << e.what( );
if ( e.code( ) == E_StreamError::SYSTEM_ERROR ) {
sb << " (error code " << e.systemError( ) << ")";
}
errors.addNew( std::move( sb ) , tFileName.location( ) );
return;
} catch ( X_SRDErrors const& e ) {
const auto ne{ e.errors.size( ) };
for ( auto i = 0u ; i < ne ; i ++ ) {
errors.add( e.errors[ i ] );
}
return;
}
}
// Parse included file
inclStack.add( curFile );
curFile = inclPath;
parseTLList( srdOut.list( ) );
curFile = inclStack.last( );
inclStack.removeLast( );
}
/*----------------------------------------------------------------------------*/
@ -2224,6 +2302,6 @@ bool T_OpsParser::parse(
{
errors_.clear( );
output_ = NewOwned< T_OpsParserOutput >( );
p< T_ParserImpl_ >( ).main( input );
p< T_ParserImpl_ >( ).main( filePath , input );
return errors_.empty( );
}

View file

@ -24,21 +24,27 @@ struct CommonData_
{}
};
uint32_t Initialised_{ 0 };
std::aligned_storage_t< sizeof( CommonData_ ) , alignof( CommonData_ ) > Instance_;
} // namespace <anon>
/*----------------------------------------------------------------------------*/
void Common::Init(
Common::Common(
T_FSPath const& path ) noexcept
{
new ((char*)&Instance_) CommonData_( path );
if ( !Initialised_ ++ ) {
new ((char*)&Instance_) CommonData_( path );
}
}
void Common::Shutdown( ) noexcept
Common::~Common( ) noexcept
{
((CommonData_*)(char*)&Instance_)->~CommonData_( );
assert( Initialised_ );
if ( !-- Initialised_ ) {
((CommonData_*)(char*)&Instance_)->~CommonData_( );
}
}
/*----------------------------------------------------------------------------*/

View file

@ -13,8 +13,8 @@ class T_UndoManager;
struct Common
{
static void Init( T_FSPath const& path = {} ) noexcept;
static void Shutdown( ) noexcept;
explicit Common( T_FSPath const& path = {} ) noexcept;
~Common( ) noexcept;
static T_Project& Project( ) noexcept;
static T_FilesWatcher& Watcher( ) noexcept;

View file

@ -1,5 +1,6 @@
#include "externals.hh"
#include "common.hh"
#include "c-opast.hh"
#include "c-ops.hh"
#include "c-opcomp.hh"
@ -34,7 +35,13 @@ void PrintStreamError(
T_FSPath const& name ,
X_StreamError const& error ) noexcept
{
const T_FSPath rp{ name.makeRelative( Filesystem::Cwd( ) ) };
const T_FSPath rp{ ([&]() {
if ( error.path( ) ) {
return *( error.path( ) );
}
return name;
}()).makeRelative( Filesystem::Cwd( ) ) };
T_StringBuilder sb;
sb << prefix << " '" << rp << "': " << error.what( );
if ( error.code( ) == E_StreamError::SYSTEM_ERROR ) {
@ -138,6 +145,8 @@ int main( int argc , char** argv )
}
}
// Initialise common layer
const T_FSPath srcPath{ ([&](){
const T_FSPath raw{ oSrcPath };
if ( !raw.isAbsolute( ) ) {
@ -149,6 +158,7 @@ int main( int argc , char** argv )
fprintf( stderr , "Invalid source path\n" );
return EXIT_FAILURE;
}
Common common{ srcPath };
// Logger setup
const uint32_t logLevel{ oLogLevel ? *oLogLevel : 0 };
@ -163,11 +173,11 @@ int main( int argc , char** argv )
// Build configurations
M_LOGSTR( "Loading build configurations" , 1 );
const auto bcfgFile{ FilePath( srcPath , "build.srd" ) };
const T_BuildConfiguration cfg{ [&]() {
try {
T_BuildConfigurationLoader bcfgLoader;
T_BuildConfigurations cfs{ bcfgLoader.load( bcfgFile.toString( ) ) };
T_BuildConfigurations cfs{
T_BuildConfigurationLoader{ }.load( )
};
if ( oBuildCfg && !cfs.contains( oBuildCfg ) ) {
fprintf( stderr , "===== BUILD CONFIGURATIONS\n" );
fprintf( stderr , "Build configuration not found\n" );
@ -183,7 +193,9 @@ int main( int argc , char** argv )
} catch ( X_StreamError const& e ) {
fprintf( stderr , "===== BUILD CONFIGURATIONS\n" );
PrintStreamError( "Could not open" , bcfgFile , e );
PrintStreamError( "Could not open" ,
Common::Project( ).pathOf( "build.srd" ) ,
e );
exit( EXIT_FAILURE );
} catch ( X_SRDErrors const& e ) {
@ -210,24 +222,25 @@ int main( int argc , char** argv )
// Open and load script
M_LOGSTR( "Loading script" , 1 );
const auto inputName{ FilePath( srcPath , "demo.srd" ) };
char const* const scriptName{ "demo.srd" };
const auto scriptPath{ Common::Project( ).pathOf( scriptName ) };
T_SRDMemoryTarget srdOut;
{
T_File input( inputName.toString( ) , E_FileMode::READ_ONLY );
T_File input( scriptPath , E_FileMode::READ_ONLY );
try {
input.open( );
} catch ( X_StreamError const& e ) {
PrintStreamError( "Could not open" , inputName , e );
PrintStreamError( "Could not open" , scriptPath , e );
return 1;
}
srdOut.clearComments( true ).clearFlushToken( true );
try {
T_SRDTextReader srdReader{ srdOut };
T_FileInputStream fis{ input };
srdReader.read( inputName.toString( ) , fis );
srdReader.read( scriptName , fis );
} catch ( X_StreamError const& e ) {
fprintf( stderr , "===== SCRIPT\n" );
PrintStreamError( "Could not open" , inputName , e );
PrintStreamError( "Could not open" , scriptPath , e );
exit( EXIT_FAILURE );
} catch ( X_SRDErrors const& e ) {
WriteSRDErrors( "SCRIPT" , e.errors );
@ -239,7 +252,7 @@ int main( int argc , char** argv )
M_LOGSTR( "Parsing script" , 1 );
T_OpsParser parser;
parser.setLogger( logger );
if ( !parser.parse( inputName , srdOut.list( ) ) ) {
if ( !parser.parse( scriptPath , srdOut.list( ) ) ) {
WriteSRDErrors( "SCRIPT" , parser.errors( ) );
exit( EXIT_FAILURE );
}

View file

@ -33,6 +33,7 @@ struct T_Main
uint32_t stopResize = 0;
ImVec2 prevSize;
UI ui;
T_Optional< T_Demo > demo;
T_Optional< T_SyncView > sequencer;
@ -46,8 +47,8 @@ struct T_Main
/*----------------------------------------------------------------------------*/
T_Main::T_Main( T_FSPath const& path )
: ui{ path }
{
UI::Init( path );
prevSize = ImVec2( -1 , -1 );
}
@ -103,7 +104,6 @@ void T_Main::mainLoop( )
T_Main::~T_Main( )
{
demo.clear( );
UI::Shutdown( );
}
/*----------------------------------------------------------------------------*/

21
ui.cc
View file

@ -23,6 +23,7 @@ const char CopyShader_[] = {
struct UIData_
{
Common common;
T_UIApp window;
T_Profiler profiler;
T_TextureManager textures;
@ -35,24 +36,32 @@ struct UIData_
};
T_OutputDebugger odbg;
T_UISync sync;
UIData_( T_FSPath const& path ) noexcept
: common{ path }
{}
};
uint32_t Initialised_{ 0 };
std::aligned_storage_t< sizeof( UIData_ ) , alignof( UIData_ ) > Instance_;
} // namespace <anon>
/*----------------------------------------------------------------------------*/
void UI::Init( T_FSPath const& path ) noexcept
UI::UI( T_FSPath const& path ) noexcept
{
Common::Init( path );
new ((char*)&Instance_) UIData_( );
if ( !Initialised_ ++ ) {
new ((char*)&Instance_) UIData_( path );
}
}
void UI::Shutdown( ) noexcept
UI::~UI( ) noexcept
{
((UIData_*)(char*)&Instance_)->~UIData_( );
Common::Shutdown( );
assert( Initialised_ );
if ( !-- Initialised_ ) {
((UIData_*)(char*)&Instance_)->~UIData_( );
}
}
/*----------------------------------------------------------------------------*/

4
ui.hh
View file

@ -15,8 +15,8 @@ struct T_UISync;
struct UI
{
public:
static void Init( T_FSPath const& path = {} ) noexcept;
static void Shutdown( ) noexcept;
explicit UI( T_FSPath const& path = {} ) noexcept;
~UI( ) noexcept;
static T_UIApp& Main( ) noexcept;
static T_Profiler& Profiler( ) noexcept;