diff --git a/opparser.cc b/opparser.cc index 78f962e..dc2a247 100644 --- a/opparser.cc +++ b/opparser.cc @@ -685,67 +685,69 @@ bool T_ParserImpl_::checkIdentifierExpressions( ) noexcept 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; + 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( ) ); + } else if ( callInfo[ cfi ] & E_InstrRestriction::INIT ) { + errors.addNew( "input used in initialisation" , + e.location( ) ); } - - // 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; - } ); + } + + 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( ); }