Skip to content

Commit

Permalink
eoc/math: simplify eoc-math integration
Browse files Browse the repository at this point in the history
  • Loading branch information
andrei8l committed Nov 21, 2024
1 parent 3b873fc commit 5675653
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 201 deletions.
158 changes: 33 additions & 125 deletions src/condition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,16 @@ namespace
struct deferred_math {
JsonObject jo;
std::string str;
bool assignment;
math_type_t type;
std::shared_ptr<math_exp> exp;

deferred_math( JsonObject const &jo_, std::string_view str_, bool ass_ )
: jo( jo_ ), str( str_ ), assignment( ass_ ), exp( std::make_shared<math_exp>() ) {
deferred_math( JsonObject const &jo_, std::string_view str_, math_type_t type_ )
: jo( jo_ ), str( str_ ), type( type_ ), exp( std::make_shared<math_exp>() ) {

jo.allow_omitted_members();
}

void _validate_type() const;
};

struct condition_parser {
Expand Down Expand Up @@ -156,9 +158,10 @@ void clear_deferred_math()
get_deferred_math().swap( empty );
}

std::shared_ptr<math_exp> &defer_math( JsonObject const &jo, std::string_view str, bool ass )
std::shared_ptr<math_exp> &defer_math( JsonObject const &jo, std::string_view str,
math_type_t type )
{
get_deferred_math().emplace( jo, str, ass );
get_deferred_math().emplace( jo, str, type );
return get_deferred_math().back().exp;
}

Expand Down Expand Up @@ -197,7 +200,7 @@ dbl_or_var_part get_dbl_or_var_part( const JsonValue &jv, std::string_view membe
JsonObject jo = jv.get_object();
if( jo.has_array( "math" ) ) {
ret_val.math_val.emplace();
ret_val.math_val->from_json( jo, "math", eoc_math::type_t::ret );
ret_val.math_val->from_json( jo, "math", math_type_t::ret );
} else {
jo.allow_omitted_members();
ret_val.var_val = read_var_info( jo );
Expand Down Expand Up @@ -247,7 +250,7 @@ duration_or_var_part get_duration_or_var_part( const JsonValue &jv, const std::s
JsonObject jo = jv.get_object();
if( jo.has_array( "math" ) ) {
ret_val.math_val.emplace();
ret_val.math_val->from_json( jo, "math", eoc_math::type_t::ret );
ret_val.math_val->from_json( jo, "math", math_type_t::ret );
} else {
jo.allow_omitted_members();
ret_val.var_val = read_var_info( jo );
Expand Down Expand Up @@ -604,7 +607,8 @@ void finalize_conditions()
while( !dfr.empty() ) {
deferred_math &math = dfr.front();
try {
math.exp->parse( math.str, math.assignment, false );
math.exp->parse( math.str, false );
math._validate_type();
} catch( std::invalid_argument const &ex ) {
JsonObject jo{ std::move( math.jo ) };
clear_deferred_math();
Expand Down Expand Up @@ -1945,10 +1949,9 @@ conditional_t::func f_has_ammo()
conditional_t::func f_math( const JsonObject &jo, const std::string_view member )
{
eoc_math math;
math.from_json( jo, member, eoc_math::type_t::compare );
return [math = std::move( math )]( const_dialogue const & d ) {
dialogue loosey_goosey( d );
return math.act( loosey_goosey );
math.from_json( jo, member, math_type_t::compare );
return [math = std::move( math )]( const_dialogue const & d ) ->bool {
return math.act( d );
};
}

Expand Down Expand Up @@ -2474,131 +2477,36 @@ conditional_t::get_set_dbl( std::string_view checked_value, char scope )
throw std::invalid_argument( string_format( R"(Invalid aspect "%s" for val())", checked_value ) );
}

void eoc_math::_validate_type( JsonArray const &objects, type_t type_ ) const
void deferred_math::_validate_type() const
{
if( type_ != type_t::compare && action >= oper::equal ) {
objects.throw_error( "Comparison operators can only be used in conditional statements" );
} else if( type_ == type_t::compare && action < oper::equal ) {
if( action == oper::assign ) {
objects.throw_error(
R"(Assignment operator "=" can't be used in a conditional statement. Did you mean to use "=="? )" );
} else if( action != oper::ret ) {
objects.throw_error( "Only comparison operators can be used in conditional statements" );
}
} else if( type_ == type_t::ret && action > oper::ret ) {
objects.throw_error( "Only return expressions are allowed in this context" );
} else if( type_ != type_t::ret && action == oper::ret ) {
objects.throw_error( "Return expression in assignment context has no effect" );
math_type_t exp_type = exp->get_type();
if( exp_type == math_type_t::assign && type != math_type_t::assign ) {
jo.throw_error(
R"(Assignment operators can't be used in this context. Did you mean to use "=="? )" );
} else if( exp_type != math_type_t::assign && type == math_type_t::assign ) {
jo.throw_error(
R"(Eval statement in assignment context has no effect)" );
}
}

void eoc_math::from_json( const JsonObject &jo, std::string_view member, type_t type_ )
void eoc_math::from_json( const JsonObject &jo, std::string_view member, math_type_t type_ )
{
JsonArray const objects = jo.get_array( member );
if( objects.size() > 3 ) {
jo.throw_error( "Invalid number of args in " + jo.str() );
return;
}

std::string const oper = objects.size() >= 2 ? objects.get_string( 1 ) : std::string{};

if( objects.size() == 1 ) {
action = oper::ret;
} else if( objects.size() == 2 ) {
if( oper == "++" ) {
action = oper::increase;
} else if( oper == "--" ) {
action = oper::decrease;
} else {
jo.throw_error( "Invalid unary operator in " + jo.str() );
return;
}
} else if( objects.size() == 3 ) {
rhs = defer_math( jo, objects.get_string( 2 ), false );
if( oper == "=" ) {
action = oper::assign;
} else if( oper == "+=" ) {
action = oper::plus_assign;
} else if( oper == "-=" ) {
action = oper::minus_assign;
} else if( oper == "*=" ) {
action = oper::mult_assign;
} else if( oper == "/=" ) {
action = oper::div_assign;
} else if( oper == "%=" ) {
action = oper::mod_assign;
} else if( oper == "==" ) {
action = oper::equal;
} else if( oper == "!=" ) {
action = oper::not_equal;
} else if( oper == "<" ) {
action = oper::less;
} else if( oper == "<=" ) {
action = oper::equal_or_less;
} else if( oper == ">" ) {
action = oper::greater;
} else if( oper == ">=" ) {
action = oper::equal_or_greater;
} else {
jo.throw_error( "Invalid binary operator in " + jo.str() );
return;
}
}
_validate_type( objects, type_ );
bool const lhs_assign = action >= oper::assign && action <= oper::decrease;
lhs = defer_math( jo, objects.get_string( 0 ), lhs_assign );
if( action >= oper::plus_assign && action <= oper::decrease ) {
mhs = defer_math( jo, objects.get_string( 0 ), false );
std::string combined;
for( size_t i = 0; i < objects.size(); i++ ) {
combined.append( objects.get_string( i ) );
}
exp = defer_math( jo, combined, type_ );
}

double eoc_math::act( dialogue &d ) const
{
switch( action ) {
case oper::ret:
return lhs->eval( d );
case oper::assign:
lhs->assign( d, rhs->eval( d ) );
break;
case oper::plus_assign:
lhs->assign( d, mhs->eval( d ) + rhs->eval( d ) );
break;
case oper::minus_assign:
lhs->assign( d, mhs->eval( d ) - rhs->eval( d ) );
break;
case oper::mult_assign:
lhs->assign( d, mhs->eval( d ) * rhs->eval( d ) );
break;
case oper::div_assign:
lhs->assign( d, mhs->eval( d ) / rhs->eval( d ) );
break;
case oper::mod_assign:
lhs->assign( d, std::fmod( mhs->eval( d ), rhs->eval( d ) ) );
break;
case oper::increase:
lhs->assign( d, mhs->eval( d ) + 1 );
break;
case oper::decrease:
lhs->assign( d, mhs->eval( d ) - 1 );
break;
case oper::equal:
return static_cast<double>( float_equals( lhs->eval( d ), rhs->eval( d ) ) );
case oper::not_equal:
return static_cast<double>( !float_equals( lhs->eval( d ), rhs->eval( d ) ) );
case oper::less:
return lhs->eval( d ) < rhs->eval( d );
case oper::equal_or_less:
return lhs->eval( d ) <= rhs->eval( d );
case oper::greater:
return lhs->eval( d ) > rhs->eval( d );
case oper::equal_or_greater:
return lhs->eval( d ) >= rhs->eval( d );
case oper::invalid:
default:
debugmsg( "unknown eoc math operator %d %s", action, d.get_callstack() );
}
return exp->eval( d );
}

return 0;
double eoc_math::act( const_dialogue const &d ) const
{
return exp->eval( d );
}

static const
Expand Down
1 change: 0 additions & 1 deletion src/dialogue.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,6 @@ struct dialogue: public const_dialogue {
dialogue() = default;
~dialogue() = default;
dialogue( const dialogue &d );
explicit dialogue( const_dialogue const &d );
dialogue( dialogue && ) = default;
dialogue &operator=( const dialogue & );
dialogue &operator=( dialogue && ) = default;
Expand Down
6 changes: 2 additions & 4 deletions src/dialogue_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,7 @@ double dbl_or_var_part::evaluate( const_dialogue const &d ) const
return 0;
}
if( math_val ) {
dialogue loosey_goosey( d );
return math_val->act( loosey_goosey );
return math_val->act( d );
}
debugmsg( "No valid value for dbl_or_var_part. %s", d.get_callstack() );
return 0;
Expand Down Expand Up @@ -209,8 +208,7 @@ time_duration duration_or_var_part::evaluate( const_dialogue const &d ) const
return 0_seconds;
}
if( math_val ) {
dialogue loosey_goosey( d );
return time_duration::from_turns( math_val->act( loosey_goosey ) );
return time_duration::from_turns( math_val->act( d ) );
}
debugmsg( "No valid value for duration_or_var_part. %s", d.get_callstack() );
return 0_seconds;
Expand Down
39 changes: 5 additions & 34 deletions src/dialogue_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "calendar.h"
#include "debug.h"
#include "global_vars.h"
#include "math_parser_type.h"
#include "translation.h"

class JsonArray;
Expand Down Expand Up @@ -100,41 +101,11 @@ std::optional<std::string> maybe_read_var_value(
var_info process_variable( const std::string &type );

struct eoc_math {
enum class oper : int {
ret = 0,
assign,

// these need mhs
plus_assign,
minus_assign,
mult_assign,
div_assign,
mod_assign,
increase,
decrease,

equal,
not_equal,
less,
equal_or_less,
greater,
equal_or_greater,

invalid,
};
enum class type_t : int {
ret = 0,
compare,
assign,
};
std::shared_ptr<math_exp> lhs;
std::shared_ptr<math_exp> mhs;
std::shared_ptr<math_exp> rhs;
eoc_math::oper action = oper::invalid;

void from_json( const JsonObject &jo, std::string_view member, type_t type_ );
std::shared_ptr<math_exp> exp;

void from_json( const JsonObject &jo, std::string_view member, math_type_t type_ );
double act( dialogue &d ) const;
void _validate_type( JsonArray const &objects, type_t type_ ) const;
double act( const_dialogue const &d ) const;
};

struct dbl_or_var_part {
Expand Down
Loading

0 comments on commit 5675653

Please sign in to comment.