mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
* all except pol * pol and includes under defines * something weird has happened * remove own folder from include searchpath * fixed remaining, adapted include style for external headers * missing include
174 lines
5.2 KiB
C++
174 lines
5.2 KiB
C++
#include "bscript/compiler/analyzer/ShortCircuitWarning.h"
|
|
|
|
#include "bscript/compiler/Report.h"
|
|
#include "bscript/compiler/ast/BinaryOperator.h"
|
|
#include "bscript/compiler/ast/BinaryOperatorShortCircuit.h"
|
|
#include "bscript/compiler/ast/ElementAssignment.h"
|
|
#include "bscript/compiler/ast/Function.h"
|
|
#include "bscript/compiler/ast/FunctionCall.h"
|
|
#include "bscript/compiler/ast/MemberAssignment.h"
|
|
#include "bscript/compiler/ast/MemberAssignmentByOperator.h"
|
|
#include "bscript/compiler/ast/MethodCall.h"
|
|
#include "bscript/compiler/ast/ModuleFunctionDeclaration.h"
|
|
#include "bscript/compiler/ast/Program.h"
|
|
#include "bscript/compiler/ast/TopLevelStatements.h"
|
|
#include "bscript/compiler/ast/UnaryOperator.h"
|
|
#include "bscript/compiler/ast/UserFunction.h"
|
|
#include "bscript/compiler/ast/VariableAssignmentStatement.h"
|
|
#include "bscript/compiler/model/CompilerWorkspace.h"
|
|
#include "bscript/compiler/model/FunctionLink.h"
|
|
#include "bscript/compilercfg.h"
|
|
#include "bscript/tokens.h"
|
|
#include "clib/strutil.h"
|
|
|
|
namespace Pol::Bscript::Compiler
|
|
{
|
|
ShortCircuitWarning::ShortCircuitWarning( Report& report ) : visitor( report ) {}
|
|
|
|
void ShortCircuitWarning::warn( CompilerWorkspace& workspace )
|
|
{
|
|
if ( !compilercfg.ShortCircuitEvaluation || !compilercfg.ShortCircuitEvaluationWarning )
|
|
return;
|
|
workspace.top_level_statements->accept( *this );
|
|
if ( auto& program = workspace.program )
|
|
{
|
|
program->accept( *this );
|
|
}
|
|
for ( auto& user_function : workspace.user_functions )
|
|
{
|
|
user_function->accept( *this );
|
|
}
|
|
}
|
|
|
|
void ShortCircuitWarning::visit_binary_operator_short_circuit( BinaryOperatorShortCircuit& op )
|
|
{
|
|
// check only right side, left is only needed if more compile
|
|
// optimizations are done
|
|
// left still could be a ShortCircuit so visit it with this instance
|
|
op.lhs().accept( *this );
|
|
op.rhs().accept( visitor );
|
|
}
|
|
|
|
///////
|
|
|
|
ShortCircuitReporter::ShortCircuitReporter( Report& report ) : report( report ) {}
|
|
|
|
void ShortCircuitReporter::trigger( Node& op )
|
|
{
|
|
report.warning( op.source_location,
|
|
"Short circuit change: \"{}\" will potentially not been executed.\n{}",
|
|
op.describe(), op.source_location.getSourceLine() );
|
|
}
|
|
|
|
void ShortCircuitReporter::visit_binary_operator( BinaryOperator& op )
|
|
{
|
|
switch ( op.token_id )
|
|
{
|
|
case TOK_ASSIGN:
|
|
case INS_ASSIGN_CONSUME:
|
|
case TOK_PLUSEQUAL:
|
|
case TOK_MINUSEQUAL:
|
|
case TOK_TIMESEQUAL:
|
|
case TOK_DIVIDEEQUAL:
|
|
case TOK_MODULUSEQUAL:
|
|
case TOK_ADDMEMBER:
|
|
case TOK_DELMEMBER:
|
|
trigger( op );
|
|
return;
|
|
|
|
default:
|
|
visit_children( op );
|
|
return;
|
|
}
|
|
}
|
|
|
|
void ShortCircuitReporter::visit_element_assignment( ElementAssignment& op )
|
|
{
|
|
trigger( op );
|
|
}
|
|
|
|
void ShortCircuitReporter::visit_function_call( FunctionCall& op )
|
|
{
|
|
// Whitelist of module functions without sideeffects
|
|
// not all, just some I found
|
|
static std::map<std::string, std::vector<std::string>> modulefuncs = {
|
|
{ "attributes", { "getattribute" } },
|
|
{ "basicio", {} },
|
|
{ "basic",
|
|
{ "casc", "cascz", "cdbl", "cint", "cstr", "find", "hex", "len", "lower", "upper", "sizeof",
|
|
"typeof", "typeofint" } },
|
|
{ "cfgfile", { "getconfigint", "getconfigreal", "getconfigstring" } },
|
|
{ "math", { "abs" } },
|
|
{ "npc", { "self" } },
|
|
{ "os", { "getpid", "getprocess" } },
|
|
{ "util", {} },
|
|
{ "uo",
|
|
{ "accessible", "checklineofsight", "checklosat", "coordinatedistance", "distance",
|
|
"distanceeuclidean", "enumerateitemsincontainer", "getamount", "getequipmentbylayer",
|
|
"getglobalproperty", "getobjproperty", "getobjpropertynames", "getobjtypebyname",
|
|
"listequippeditems", "listhostiles", "listmobilesatlocation", "listmobilesnearlocation",
|
|
"readgameclock", "systemfindobjectbyserial" } },
|
|
|
|
};
|
|
if ( auto mf = op.function_link->module_function_declaration() )
|
|
{
|
|
bool ignore = false;
|
|
if ( auto mod = modulefuncs.find( Clib::strlowerASCII( mf->scope ) ); mod != modulefuncs.end() )
|
|
{
|
|
if ( mod->second.empty() )
|
|
ignore = true;
|
|
else if ( std::find( mod->second.begin(), mod->second.end(),
|
|
Clib::strlowerASCII( mf->name ) ) != mod->second.end() )
|
|
ignore = true;
|
|
}
|
|
if ( ignore )
|
|
{
|
|
visit_children( op );
|
|
return;
|
|
}
|
|
}
|
|
trigger( op );
|
|
}
|
|
|
|
void ShortCircuitReporter::visit_member_assignment( MemberAssignment& op )
|
|
{
|
|
trigger( op );
|
|
}
|
|
|
|
void ShortCircuitReporter::visit_member_assignment_by_operator( MemberAssignmentByOperator& op )
|
|
{
|
|
// todo what
|
|
trigger( op );
|
|
}
|
|
|
|
void ShortCircuitReporter::visit_variable_assignment_statement( VariableAssignmentStatement& op )
|
|
{
|
|
// todo what
|
|
trigger( op );
|
|
}
|
|
|
|
void ShortCircuitReporter::visit_method_call( MethodCall& op )
|
|
{
|
|
trigger( op );
|
|
}
|
|
|
|
void ShortCircuitReporter::visit_unary_operator( UnaryOperator& op )
|
|
{
|
|
switch ( op.token_id )
|
|
{
|
|
case TOK_UNPLUSPLUS:
|
|
case TOK_UNMINUSMINUS:
|
|
case TOK_UNPLUSPLUS_POST:
|
|
case TOK_UNMINUSMINUS_POST:
|
|
case INS_SET_MEMBER_ID_UNPLUSPLUS:
|
|
case INS_SET_MEMBER_ID_UNMINUSMINUS:
|
|
case INS_SET_MEMBER_ID_UNPLUSPLUS_POST:
|
|
case INS_SET_MEMBER_ID_UNMINUSMINUS_POST:
|
|
trigger( op );
|
|
return;
|
|
default:
|
|
visit_children( op );
|
|
return;
|
|
}
|
|
}
|
|
} // namespace Pol::Bscript::Compiler
|