Parser - Type checking for inputs and global identifiers
This commit is contained in:
parent
36a3e5e26f
commit
949e4099ec
1 changed files with 81 additions and 4 deletions
85
opparser.cc
85
opparser.cc
|
@ -149,8 +149,10 @@ struct T_ParserImpl_
|
||||||
|
|
||||||
T_OwnPtr< T_ParserOutput >& output;
|
T_OwnPtr< T_ParserOutput >& output;
|
||||||
T_Array< T_SRDError >& errors;
|
T_Array< T_SRDError >& errors;
|
||||||
T_Visitor< A_Node > visitor{ opast::ASTVisitorBrowser };
|
|
||||||
T_MultiArray< uint32_t > calls;
|
T_MultiArray< uint32_t > calls;
|
||||||
|
T_Array< T_InstrRestriction > callInfo;
|
||||||
|
|
||||||
|
T_Visitor< A_Node > visitor{ opast::ASTVisitorBrowser };
|
||||||
T_Visitor< uint32_t , uint32_t > callGraphVisitor{
|
T_Visitor< uint32_t , uint32_t > callGraphVisitor{
|
||||||
[this]( uint32_t v , uint32_t child ) -> T_Optional< uint32_t > {
|
[this]( uint32_t v , uint32_t child ) -> T_Optional< uint32_t > {
|
||||||
const uint32_t nc( calls.sizeOf( v ) );
|
const uint32_t nc( calls.sizeOf( v ) );
|
||||||
|
@ -172,6 +174,7 @@ struct T_ParserImpl_
|
||||||
bool checkInstructionRestrictions( ) noexcept;
|
bool checkInstructionRestrictions( ) noexcept;
|
||||||
bool collectGlobalTypes( ) noexcept;
|
bool collectGlobalTypes( ) noexcept;
|
||||||
bool checkLocalVariables( ) noexcept;
|
bool checkLocalVariables( ) noexcept;
|
||||||
|
bool checkIdentifierExpressions( ) noexcept;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -284,7 +287,8 @@ void T_ParserImpl_::main(
|
||||||
&& checkCalls( )
|
&& checkCalls( )
|
||||||
&& checkInstructionRestrictions( )
|
&& checkInstructionRestrictions( )
|
||||||
&& collectGlobalTypes( )
|
&& collectGlobalTypes( )
|
||||||
&& checkLocalVariables( );
|
&& checkLocalVariables( )
|
||||||
|
&& checkIdentifierExpressions( );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
@ -350,7 +354,9 @@ bool T_ParserImpl_::checkCalls( ) noexcept
|
||||||
|
|
||||||
bool T_ParserImpl_::checkInstructionRestrictions( ) noexcept
|
bool T_ParserImpl_::checkInstructionRestrictions( ) noexcept
|
||||||
{
|
{
|
||||||
T_InstrRestriction callInfo[ calls.size( ) ];
|
callInfo.clear( );
|
||||||
|
callInfo.resize( calls.size( ) );
|
||||||
|
|
||||||
callGraphVisitor.visit( output->root.functionIndex( "*init*" ) ,
|
callGraphVisitor.visit( output->root.functionIndex( "*init*" ) ,
|
||||||
[&]( uint32_t id , const bool exit ) -> bool {
|
[&]( uint32_t id , const bool exit ) -> bool {
|
||||||
if ( exit || callInfo[ id ] & E_InstrRestriction::INIT ) {
|
if ( exit || callInfo[ id ] & E_InstrRestriction::INIT ) {
|
||||||
|
@ -463,9 +469,9 @@ bool T_ParserImpl_::collectGlobalTypes( ) noexcept
|
||||||
bool T_ParserImpl_::checkLocalVariables( ) noexcept
|
bool T_ParserImpl_::checkLocalVariables( ) noexcept
|
||||||
{
|
{
|
||||||
uint32_t cfi;
|
uint32_t cfi;
|
||||||
|
T_StringBuilder esb;
|
||||||
for ( cfi = 0 ; cfi < output->root.nFunctions( ) ; cfi ++ ) {
|
for ( cfi = 0 ; cfi < output->root.nFunctions( ) ; cfi ++ ) {
|
||||||
auto& function( output->root.function( cfi ) );
|
auto& function( output->root.function( cfi ) );
|
||||||
T_StringBuilder esb;
|
|
||||||
visitor.visit( function ,
|
visitor.visit( function ,
|
||||||
[&]( A_Node& n , const bool exit ) -> bool {
|
[&]( A_Node& n , const bool exit ) -> bool {
|
||||||
if ( exit || n.type( ) != A_Node::OP_LOCALS ) {
|
if ( exit || n.type( ) != A_Node::OP_LOCALS ) {
|
||||||
|
@ -493,6 +499,77 @@ bool T_ParserImpl_::checkLocalVariables( ) noexcept
|
||||||
return errors.empty( );
|
return errors.empty( );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool T_ParserImpl_::checkIdentifierExpressions( ) noexcept
|
||||||
|
{
|
||||||
|
uint32_t cfi;
|
||||||
|
T_StringBuilder esb;
|
||||||
|
for ( cfi = 0 ; cfi < output->root.nFunctions( ) ; cfi ++ ) {
|
||||||
|
auto& function( output->root.function( cfi ) );
|
||||||
|
visitor.visit( function ,
|
||||||
|
[&]( A_Node& n , const bool exit ) -> bool {
|
||||||
|
if ( exit ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check get-input expressions
|
||||||
|
if ( n.type( ) == A_Node::EXPR_INPUT ) {
|
||||||
|
auto& e( dynamic_cast< T_InputExprNode& >( n ) );
|
||||||
|
auto const* const t( output->types.get( e.id( ) ) );
|
||||||
|
if ( !t ) {
|
||||||
|
errors.addNew( "no such input" , e.idLocation( ) );
|
||||||
|
} else if ( *t != E_DataType::INPUT ) {
|
||||||
|
esb << "'" << e.id( ) << "' used as input but declared as a "
|
||||||
|
<< *t;
|
||||||
|
errors.addNew( std::move( esb ) , e.idLocation( ) );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( n.type( ) != A_Node::EXPR_ID ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check use of identifiers in expressions
|
||||||
|
auto& e( dynamic_cast< T_IdentifierExprNode& >( n ) );
|
||||||
|
auto const* const gType{ output->types.get( e.id( ) ) };
|
||||||
|
if ( gType ) {
|
||||||
|
// FIXME handle aliases
|
||||||
|
|
||||||
|
// Variables are fine
|
||||||
|
if ( *gType == E_DataType::VARIABLE ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check builtins
|
||||||
|
if ( *gType == E_DataType::BUILTIN ) {
|
||||||
|
if ( ( callInfo[ cfi ] & E_InstrRestriction::INIT )
|
||||||
|
&& e.id( ) == "time" ) {
|
||||||
|
errors.addNew( "'time' built-in used in initialisation" ,
|
||||||
|
e.location( ) );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We'll allow other types to be used in an expression
|
||||||
|
// in the context of the call instruction.
|
||||||
|
if ( e.parent( ).type( ) == A_Node::OP_CALL ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
esb << "'" << e.id( ) << "' used as a variable but declared as a "
|
||||||
|
<< *gType;
|
||||||
|
errors.addNew( std::move( esb ) , e.location( ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME check locals
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
return errors.empty( );
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
bool T_ParserImpl_::parseTopLevel(
|
bool T_ParserImpl_::parseTopLevel(
|
||||||
|
|
Loading…
Reference in a new issue