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_InstrListNode& parent ,
|
||||
T_SRDToken const& idToken ) noexcept
|
||||
: A_InstructionNode( OP_PIPELINE , parent ) ,
|
||||
: A_InstructionNode( OP_PIPELINE , parent , E_InstrRestriction::FRAME ) ,
|
||||
id_( idToken.stringValue( ) ) ,
|
||||
idLocation_( idToken.location( ) )
|
||||
{ }
|
||||
|
||||
T_PipelineInstrNode::T_PipelineInstrNode(
|
||||
T_InstrListNode& parent ) noexcept
|
||||
: A_InstructionNode( OP_PIPELINE , parent ) ,
|
||||
: A_InstructionNode( OP_PIPELINE , parent , E_InstrRestriction::FRAME ) ,
|
||||
id_( "*invalid*" ) ,
|
||||
idLocation_{ }
|
||||
{ }
|
||||
|
@ -160,7 +160,7 @@ T_Optional< T_SRDLocation > T_PipelineInstrNode::addProgram(
|
|||
T_ProfileInstrNode::T_ProfileInstrNode(
|
||||
T_InstrListNode& parent ,
|
||||
T_String const& text ) noexcept
|
||||
: A_InstructionNode( OP_PROFILE , parent ) ,
|
||||
: A_InstructionNode( OP_PROFILE , parent , E_InstrRestriction::INIT ) ,
|
||||
text_( text ) ,
|
||||
instructions_( *this )
|
||||
{ }
|
||||
|
@ -172,7 +172,7 @@ T_ProgramInstrNode::T_ProgramInstrNode(
|
|||
T_InstrListNode& parent ,
|
||||
T_SRDToken const& idToken ,
|
||||
T_SRDToken const& pathToken ) noexcept
|
||||
: A_InstructionNode( OP_PROGRAM , parent ) ,
|
||||
: A_InstructionNode( OP_PROGRAM , parent , E_InstrRestriction::FRAME ) ,
|
||||
id_( idToken.stringValue( ) ) ,
|
||||
idLocation_( idToken.location( ) ) ,
|
||||
path_( pathToken.stringValue( ) ) ,
|
||||
|
@ -197,7 +197,7 @@ T_TextureInstrNode::T_TextureInstrNode(
|
|||
T_InstrListNode& parent ,
|
||||
T_SRDToken const& idToken ,
|
||||
const E_TexType type ) noexcept
|
||||
: A_InstructionNode( OP_PROGRAM , parent ) ,
|
||||
: A_InstructionNode( OP_PROGRAM , parent , E_InstrRestriction::FRAME ) ,
|
||||
id_( idToken.stringValue( ) ) ,
|
||||
idLocation_( idToken.location( ) ) ,
|
||||
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
|
||||
class A_InstructionNode : public A_Node
|
||||
{
|
||||
private:
|
||||
const T_InstrRestriction restriction_;
|
||||
|
||||
protected:
|
||||
A_InstructionNode( E_Type type ,
|
||||
A_Node& parent ) noexcept
|
||||
: A_Node( type , &parent )
|
||||
{}
|
||||
A_InstructionNode( const E_Type type ,
|
||||
A_Node& 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
|
||||
class T_InstrListNode : public A_Node
|
||||
{
|
||||
|
@ -341,14 +363,14 @@ class T_InputInstrNode : public A_InstructionNode
|
|||
public:
|
||||
T_InputInstrNode( T_InstrListNode& parent ,
|
||||
T_SRDToken const& tName ) noexcept
|
||||
: A_InstructionNode( OP_INPUT , parent ) ,
|
||||
: A_InstructionNode( OP_INPUT , parent , E_InstrRestriction::FRAME ) ,
|
||||
name_( tName.stringValue( ) ) , nameLocation_( tName.location( ) )
|
||||
{}
|
||||
|
||||
T_InputInstrNode( T_InstrListNode& parent ,
|
||||
T_SRDToken const& tName ,
|
||||
T_SRDToken const& tDefault ) noexcept
|
||||
: A_InstructionNode( OP_INPUT , parent ) ,
|
||||
: A_InstructionNode( OP_INPUT , parent , E_InstrRestriction::FRAME ) ,
|
||||
name_( tName.stringValue( ) ) , nameLocation_( tName.location( ) ) ,
|
||||
defValue_( tDefault.floatValue( ) ) , dvLocation_( tDefault.location( ) )
|
||||
{}
|
||||
|
|
|
@ -239,30 +239,54 @@ bool checkCalls( T_RootNode& root )
|
|||
}
|
||||
return {};
|
||||
} );
|
||||
enum class E_CallInfo_ {
|
||||
INIT_CHECKED , FRAME_CHECKED ,
|
||||
INIT_CALLED , FRAME_CALLED
|
||||
};
|
||||
using T_CallInfo_ = T_Flags< E_CallInfo_ , uint8_t >;
|
||||
T_CallInfo_ callInfo[ calls.size( ) ];
|
||||
T_InstrRestriction callInfo[ calls.size( ) ];
|
||||
|
||||
callGraphVisitor.visit( root.functionIndex( "*init*" ) ,
|
||||
[&]( uint32_t id , const bool exit ) -> bool {
|
||||
if ( exit || callInfo[ id ] & E_CallInfo_::INIT_CALLED ) {
|
||||
if ( exit || callInfo[ id ] & E_InstrRestriction::INIT ) {
|
||||
return false;
|
||||
}
|
||||
callInfo[ id ] |= E_CallInfo_::INIT_CALLED;
|
||||
callInfo[ id ] |= E_InstrRestriction::INIT;
|
||||
return true;
|
||||
} );
|
||||
callGraphVisitor.visit( root.functionIndex( "*frame*" ) ,
|
||||
[&]( uint32_t id , const bool exit ) -> bool {
|
||||
if ( exit || callInfo[ id ] & E_CallInfo_::FRAME_CALLED ) {
|
||||
if ( exit || callInfo[ id ] & E_InstrRestriction::FRAME ) {
|
||||
return false;
|
||||
}
|
||||
callInfo[ id ] |= E_CallInfo_::FRAME_CALLED;
|
||||
callInfo[ id ] |= E_InstrRestriction::FRAME;
|
||||
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;
|
||||
for ( auto callerId = 0u ; callerId < calls.size( ) ; callerId ++ ) {
|
||||
const auto nCallees( calls.sizeOf( callerId ) );
|
||||
|
|
Loading…
Reference in a new issue