Parser - prototype - restrictions on instruction use
This commit is contained in:
parent
c093ba2213
commit
397f1c5c75
3 changed files with 67 additions and 21 deletions
10
opast.cc
10
opast.cc
|
@ -129,14 +129,14 @@ T_Optional< T_SRDLocation > T_FuncNode::addArgument(
|
||||||
T_PipelineInstrNode::T_PipelineInstrNode(
|
T_PipelineInstrNode::T_PipelineInstrNode(
|
||||||
T_InstrListNode& parent ,
|
T_InstrListNode& parent ,
|
||||||
T_SRDToken const& idToken ) noexcept
|
T_SRDToken const& idToken ) noexcept
|
||||||
: A_InstructionNode( OP_PIPELINE , parent ) ,
|
: A_InstructionNode( OP_PIPELINE , parent , E_InstrRestriction::FRAME ) ,
|
||||||
id_( idToken.stringValue( ) ) ,
|
id_( idToken.stringValue( ) ) ,
|
||||||
idLocation_( idToken.location( ) )
|
idLocation_( idToken.location( ) )
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
T_PipelineInstrNode::T_PipelineInstrNode(
|
T_PipelineInstrNode::T_PipelineInstrNode(
|
||||||
T_InstrListNode& parent ) noexcept
|
T_InstrListNode& parent ) noexcept
|
||||||
: A_InstructionNode( OP_PIPELINE , parent ) ,
|
: A_InstructionNode( OP_PIPELINE , parent , E_InstrRestriction::FRAME ) ,
|
||||||
id_( "*invalid*" ) ,
|
id_( "*invalid*" ) ,
|
||||||
idLocation_{ }
|
idLocation_{ }
|
||||||
{ }
|
{ }
|
||||||
|
@ -160,7 +160,7 @@ T_Optional< T_SRDLocation > T_PipelineInstrNode::addProgram(
|
||||||
T_ProfileInstrNode::T_ProfileInstrNode(
|
T_ProfileInstrNode::T_ProfileInstrNode(
|
||||||
T_InstrListNode& parent ,
|
T_InstrListNode& parent ,
|
||||||
T_String const& text ) noexcept
|
T_String const& text ) noexcept
|
||||||
: A_InstructionNode( OP_PROFILE , parent ) ,
|
: A_InstructionNode( OP_PROFILE , parent , E_InstrRestriction::INIT ) ,
|
||||||
text_( text ) ,
|
text_( text ) ,
|
||||||
instructions_( *this )
|
instructions_( *this )
|
||||||
{ }
|
{ }
|
||||||
|
@ -172,7 +172,7 @@ T_ProgramInstrNode::T_ProgramInstrNode(
|
||||||
T_InstrListNode& parent ,
|
T_InstrListNode& parent ,
|
||||||
T_SRDToken const& idToken ,
|
T_SRDToken const& idToken ,
|
||||||
T_SRDToken const& pathToken ) noexcept
|
T_SRDToken const& pathToken ) noexcept
|
||||||
: A_InstructionNode( OP_PROGRAM , parent ) ,
|
: A_InstructionNode( OP_PROGRAM , parent , E_InstrRestriction::FRAME ) ,
|
||||||
id_( idToken.stringValue( ) ) ,
|
id_( idToken.stringValue( ) ) ,
|
||||||
idLocation_( idToken.location( ) ) ,
|
idLocation_( idToken.location( ) ) ,
|
||||||
path_( pathToken.stringValue( ) ) ,
|
path_( pathToken.stringValue( ) ) ,
|
||||||
|
@ -197,7 +197,7 @@ T_TextureInstrNode::T_TextureInstrNode(
|
||||||
T_InstrListNode& parent ,
|
T_InstrListNode& parent ,
|
||||||
T_SRDToken const& idToken ,
|
T_SRDToken const& idToken ,
|
||||||
const E_TexType type ) noexcept
|
const E_TexType type ) noexcept
|
||||||
: A_InstructionNode( OP_PROGRAM , parent ) ,
|
: A_InstructionNode( OP_PROGRAM , parent , E_InstrRestriction::FRAME ) ,
|
||||||
id_( idToken.stringValue( ) ) ,
|
id_( idToken.stringValue( ) ) ,
|
||||||
idLocation_( idToken.location( ) ) ,
|
idLocation_( idToken.location( ) ) ,
|
||||||
type_( type )
|
type_( type )
|
||||||
|
|
34
opast.hh
34
opast.hh
|
@ -76,16 +76,38 @@ class A_Node
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// Some instructions are restricted to either the initialisation code or the
|
||||||
|
// frame code.
|
||||||
|
enum class E_InstrRestriction
|
||||||
|
{
|
||||||
|
INIT , FRAME
|
||||||
|
};
|
||||||
|
using T_InstrRestriction = T_Flags< E_InstrRestriction >;
|
||||||
|
|
||||||
// Base class for instruction nodes
|
// Base class for instruction nodes
|
||||||
class A_InstructionNode : public A_Node
|
class A_InstructionNode : public A_Node
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
const T_InstrRestriction restriction_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
A_InstructionNode( E_Type type ,
|
A_InstructionNode( const E_Type type ,
|
||||||
A_Node& parent ) noexcept
|
A_Node& parent ,
|
||||||
: A_Node( type , &parent )
|
T_InstrRestriction restriction = {} ) noexcept
|
||||||
{}
|
: A_Node( type , &parent ) ,
|
||||||
|
restriction_( restriction )
|
||||||
|
{
|
||||||
|
assert( !restriction_.isSet({
|
||||||
|
E_InstrRestriction::INIT ,
|
||||||
|
E_InstrRestriction::FRAME }) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
T_InstrRestriction restriction( ) const noexcept
|
||||||
|
{ return restriction_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Nodes that store lists of instructions
|
// Nodes that store lists of instructions
|
||||||
class T_InstrListNode : public A_Node
|
class T_InstrListNode : public A_Node
|
||||||
{
|
{
|
||||||
|
@ -341,14 +363,14 @@ class T_InputInstrNode : public A_InstructionNode
|
||||||
public:
|
public:
|
||||||
T_InputInstrNode( T_InstrListNode& parent ,
|
T_InputInstrNode( T_InstrListNode& parent ,
|
||||||
T_SRDToken const& tName ) noexcept
|
T_SRDToken const& tName ) noexcept
|
||||||
: A_InstructionNode( OP_INPUT , parent ) ,
|
: A_InstructionNode( OP_INPUT , parent , E_InstrRestriction::FRAME ) ,
|
||||||
name_( tName.stringValue( ) ) , nameLocation_( tName.location( ) )
|
name_( tName.stringValue( ) ) , nameLocation_( tName.location( ) )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
T_InputInstrNode( T_InstrListNode& parent ,
|
T_InputInstrNode( T_InstrListNode& parent ,
|
||||||
T_SRDToken const& tName ,
|
T_SRDToken const& tName ,
|
||||||
T_SRDToken const& tDefault ) noexcept
|
T_SRDToken const& tDefault ) noexcept
|
||||||
: A_InstructionNode( OP_INPUT , parent ) ,
|
: A_InstructionNode( OP_INPUT , parent , E_InstrRestriction::FRAME ) ,
|
||||||
name_( tName.stringValue( ) ) , nameLocation_( tName.location( ) ) ,
|
name_( tName.stringValue( ) ) , nameLocation_( tName.location( ) ) ,
|
||||||
defValue_( tDefault.floatValue( ) ) , dvLocation_( tDefault.location( ) )
|
defValue_( tDefault.floatValue( ) ) , dvLocation_( tDefault.location( ) )
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -239,30 +239,54 @@ bool checkCalls( T_RootNode& root )
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
} );
|
} );
|
||||||
enum class E_CallInfo_ {
|
T_InstrRestriction callInfo[ calls.size( ) ];
|
||||||
INIT_CHECKED , FRAME_CHECKED ,
|
|
||||||
INIT_CALLED , FRAME_CALLED
|
|
||||||
};
|
|
||||||
using T_CallInfo_ = T_Flags< E_CallInfo_ , uint8_t >;
|
|
||||||
T_CallInfo_ callInfo[ calls.size( ) ];
|
|
||||||
|
|
||||||
callGraphVisitor.visit( root.functionIndex( "*init*" ) ,
|
callGraphVisitor.visit( root.functionIndex( "*init*" ) ,
|
||||||
[&]( uint32_t id , const bool exit ) -> bool {
|
[&]( uint32_t id , const bool exit ) -> bool {
|
||||||
if ( exit || callInfo[ id ] & E_CallInfo_::INIT_CALLED ) {
|
if ( exit || callInfo[ id ] & E_InstrRestriction::INIT ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
callInfo[ id ] |= E_CallInfo_::INIT_CALLED;
|
callInfo[ id ] |= E_InstrRestriction::INIT;
|
||||||
return true;
|
return true;
|
||||||
} );
|
} );
|
||||||
callGraphVisitor.visit( root.functionIndex( "*frame*" ) ,
|
callGraphVisitor.visit( root.functionIndex( "*frame*" ) ,
|
||||||
[&]( uint32_t id , const bool exit ) -> bool {
|
[&]( uint32_t id , const bool exit ) -> bool {
|
||||||
if ( exit || callInfo[ id ] & E_CallInfo_::FRAME_CALLED ) {
|
if ( exit || callInfo[ id ] & E_InstrRestriction::FRAME ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
callInfo[ id ] |= E_CallInfo_::FRAME_CALLED;
|
callInfo[ id ] |= E_InstrRestriction::FRAME;
|
||||||
return true;
|
return true;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
for ( auto i = 0u ; i < root.nFunctions( ) ; i ++ ) {
|
||||||
|
visitor.visit( root.function( i ) ,
|
||||||
|
[&]( A_Node& node , bool exit ) {
|
||||||
|
if ( exit ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const* instr( dynamic_cast< A_InstructionNode const* >( &node ) );
|
||||||
|
if ( instr && ( instr->restriction( ) & callInfo[ i ] ) ) {
|
||||||
|
T_StringBuilder sb;
|
||||||
|
sb << "instruction not allowed in "
|
||||||
|
<< ( ( instr->restriction( ) & E_InstrRestriction::INIT )
|
||||||
|
? "initialisation" : "frame function" );
|
||||||
|
errors.addNew( std::move( sb ) , instr->location( ) );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !errors.empty( ) ) {
|
||||||
|
T_StringBuilder sb;
|
||||||
|
for ( auto const& err : errors ) {
|
||||||
|
WriteSRDError( sb , err );
|
||||||
|
}
|
||||||
|
sb << "Parser failed\n" << '\0';
|
||||||
|
fprintf( stderr , "%s" , sb.data( ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
T_StringBuilder sb;
|
T_StringBuilder sb;
|
||||||
for ( auto callerId = 0u ; callerId < calls.size( ) ; callerId ++ ) {
|
for ( auto callerId = 0u ; callerId < calls.size( ) ; callerId ++ ) {
|
||||||
const auto nCallees( calls.sizeOf( callerId ) );
|
const auto nCallees( calls.sizeOf( callerId ) );
|
||||||
|
|
Loading…
Reference in a new issue