Skip to content
Permalink
Browse files

ExpressionParser: Move FunctionExpression type definitions into anoth…

…er file.
  • Loading branch information...
jordan-woyak committed Jan 26, 2019
1 parent d4f9b8c commit fd07ae8cec5c77ac60788350610739e6ac094547
@@ -45,6 +45,8 @@ add_library(inputcommon
ControlReference/ControlReference.h
ControlReference/ExpressionParser.cpp
ControlReference/ExpressionParser.h
ControlReference/FunctionExpression.cpp
ControlReference/FunctionExpression.h
)

target_link_libraries(inputcommon PUBLIC
@@ -2,29 +2,24 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include <algorithm>
#include <cassert>
#include <chrono>
#include <cmath>
#include <iostream>
#include <locale>
#include <map>
#include <memory>
#include <regex>
#include <string>
#include <utility>
#include <vector>

#include "Common/MathUtil.h"
#include "Common/StringUtil.h"

#include "InputCommon/ControlReference/ExpressionParser.h"
#include "InputCommon/ControlReference/FunctionExpression.h"

namespace ciface::ExpressionParser
{
using namespace ciface::Core;

constexpr int LOOP_MAX_REPS = 10000;
constexpr ControlState CONDITION_THRESHOLD = 0.5;

enum TokenType
{
TOK_DISCARD,
@@ -420,253 +415,6 @@ class BinaryExpression : public Expression
}
};

class FunctionExpression : public Expression
{
public:
int CountNumControls() const override
{
int result = 0;

for (auto& arg : m_args)
result += arg->CountNumControls();

return result;
}

void UpdateReferences(ControlEnvironment& env) override
{
for (auto& arg : m_args)
arg->UpdateReferences(env);
}

operator std::string() const override
{
std::string result = '!' + GetFuncName();

for (auto& arg : m_args)
result += ' ' + static_cast<std::string>(*arg);

return result;
}

bool SetArguments(std::vector<std::unique_ptr<Expression>>&& args)
{
m_args = std::move(args);

return ValidateArguments(m_args);
}

protected:
virtual std::string GetFuncName() const = 0;
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) = 0;

Expression& GetArg(u32 number) { return *m_args[number]; }
const Expression& GetArg(u32 number) const { return *m_args[number]; }

private:
std::vector<std::unique_ptr<Expression>> m_args;
};

// TODO: Return an oscillating value to make it apparent something was spelled wrong?
class UnknownFunctionExpression : public FunctionExpression
{
private:
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{
return false;
}
ControlState GetValue() const override { return 0.0; }
void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "unknown"; }
};

class ToggleExpression : public FunctionExpression
{
private:
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{
return 1 == args.size();
}

ControlState GetValue() const override
{
const ControlState inner_value = GetArg(0).GetValue();

if (inner_value < CONDITION_THRESHOLD)
{
m_released = true;
}
else if (m_released && inner_value > CONDITION_THRESHOLD)
{
m_released = false;
m_state ^= true;
}

return m_state;
}

void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "toggle"; }

mutable bool m_released{};
mutable bool m_state{};
};

class NotExpression : public FunctionExpression
{
private:
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{
return 1 == args.size();
}

ControlState GetValue() const override { return 1.0 - GetArg(0).GetValue(); }
void SetValue(ControlState value) override { GetArg(0).SetValue(1.0 - value); }
std::string GetFuncName() const override { return ""; }
};

class SinExpression : public FunctionExpression
{
private:
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{
return 1 == args.size();
}

ControlState GetValue() const override { return std::sin(GetArg(0).GetValue()); }
void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "sin"; }
};

class TimerExpression : public FunctionExpression
{
private:
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{
return 1 == args.size();
}

ControlState GetValue() const override
{
const auto now = Clock::now();
const auto elapsed = now - m_start_time;

using FSec = std::chrono::duration<ControlState>;

const ControlState val = GetArg(0).GetValue();

ControlState progress = std::chrono::duration_cast<FSec>(elapsed).count() / val;

if (std::isinf(progress))
{
// User configured a 0.0 length timer. Reset the timer and return 0.0.
progress = 0.0;
m_start_time = now;
}
else if (progress >= 1.0)
{
const ControlState reset_count = std::floor(progress);

m_start_time += std::chrono::duration_cast<Clock::duration>(FSec(val * reset_count));
progress -= reset_count;
}

return progress;
}
void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "timer"; }

private:
using Clock = std::chrono::steady_clock;
mutable Clock::time_point m_start_time = Clock::now();
};

class IfExpression : public FunctionExpression
{
private:
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{
return 3 == args.size();
}

ControlState GetValue() const override
{
return (GetArg(0).GetValue() > CONDITION_THRESHOLD) ? GetArg(1).GetValue() :
GetArg(2).GetValue();
}

void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "if"; }
};

class UnaryMinusExpression : public FunctionExpression
{
private:
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{
return 1 == args.size();
}

ControlState GetValue() const override
{
// Subtraction for clarity:
return 0.0 - GetArg(0).GetValue();
}

void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "minus"; }
};

class WhileExpression : public FunctionExpression
{
virtual bool ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
{
return 2 == args.size();
}

ControlState GetValue() const override
{
// Returns 1.0 on successful loop, 0.0 on reps exceeded. Sensible?

for (int i = 0; i != LOOP_MAX_REPS; ++i)
{
// Check condition of 1st argument:
const ControlState val = GetArg(0).GetValue();
if (val < CONDITION_THRESHOLD)
return 1.0;

// Evaluate 2nd argument:
GetArg(1).GetValue();
}

// Exceeded max reps:
return 0.0;
}

void SetValue(ControlState value) override {}
std::string GetFuncName() const override { return "while"; }
};

std::unique_ptr<FunctionExpression> MakeFunctionExpression(std::string name)
{
if (name.empty())
return std::make_unique<NotExpression>();
else if ("if" == name)
return std::make_unique<IfExpression>();
else if ("sin" == name)
return std::make_unique<SinExpression>();
else if ("timer" == name)
return std::make_unique<TimerExpression>();
else if ("toggle" == name)
return std::make_unique<ToggleExpression>();
else if ("while" == name)
return std::make_unique<WhileExpression>();
else if ("minus" == name)
return std::make_unique<UnaryMinusExpression>();
else
return std::make_unique<UnknownFunctionExpression>();
}

class LiteralExpression : public Expression
{
public:
@@ -7,7 +7,7 @@
#include <map>
#include <memory>
#include <string>
#include <utility>

#include "InputCommon/ControllerInterface/Device.h"

namespace ciface::ExpressionParser

0 comments on commit fd07ae8

Please sign in to comment.
You can’t perform that action at this time.