Do not use generic expressions for statemap rules but masks and values

This commit is contained in:
Jan 2022-09-24 18:58:56 +02:00
parent 63f636d401
commit e009c2ee08
13 changed files with 173 additions and 167 deletions

View File

@ -22,7 +22,7 @@ separateAlphaBlendFunc
mtlBlendOp == Disable: // Unused
Disable, One, Zero;
mtlAlphaTest == Disable: // Used
mtlAlphaTest == Always: // Used
Add, Zero, One;
default:

View File

@ -23,6 +23,9 @@ namespace state_map
// Zero mask values must be last
assert(value.m_state_bits_mask != 0 || i == var.m_values.size() - 1);
// Must not have a value outside the var mask
assert((value.m_state_bits_mask & ~var.m_values_mask) == 0);
}
}
@ -68,9 +71,10 @@ StateMapLayoutVarValue::StateMapLayoutVarValue(std::string name, const size_t st
{
}
StateMapLayoutVar::StateMapLayoutVar(std::string name, const size_t stateBitsIndex, std::vector<StateMapLayoutVarValue> values)
StateMapLayoutVar::StateMapLayoutVar(std::string name, const size_t stateBitsIndex, const size_t valuesMask, std::vector<StateMapLayoutVarValue> values)
: m_name(std::move(name)),
m_state_bits_index(stateBitsIndex),
m_values_mask(valuesMask),
m_values(std::move(values))
{
}

View File

@ -36,10 +36,11 @@ namespace state_map
class StateMapLayoutVar
{
public:
StateMapLayoutVar(std::string name, size_t stateBitsIndex, std::vector<StateMapLayoutVarValue> values);
StateMapLayoutVar(std::string name, size_t stateBitsIndex, size_t valuesMask, std::vector<StateMapLayoutVarValue> values);
std::string m_name;
size_t m_state_bits_index;
size_t m_values_mask;
std::vector<StateMapLayoutVarValue> m_values;
};

View File

@ -651,7 +651,7 @@ namespace IW4
inline state_map::StateMapLayoutVars stateMapVarLayout({
{
"mtlAlphaTest", 0, {
"mtlAlphaTest", 0, GFXS0_ATEST_DISABLE | GFXS0_ATEST_MASK, {
{"Always", GFXS0_ATEST_DISABLE},
{"GE128", GFXS0_ATEST_GE_128},
{"GT0", GFXS0_ATEST_GT_0},
@ -659,7 +659,7 @@ namespace IW4
}
},
{
"mtlBlendOp", 0, {
"mtlBlendOp", 0, GFXS0_BLENDOP_RGB_MASK, {
{"Add", GFXS_BLENDOP_ADD << GFXS0_BLENDOP_RGB_SHIFT},
{"Subtract", GFXS_BLENDOP_SUBTRACT << GFXS0_BLENDOP_RGB_SHIFT},
{"RevSubtract", GFXS_BLENDOP_REVSUBTRACT << GFXS0_BLENDOP_RGB_SHIFT},
@ -669,7 +669,7 @@ namespace IW4
}
},
{
"mtlSrcBlend", 0, {
"mtlSrcBlend", 0, GFXS0_SRCBLEND_RGB_MASK, {
{"Zero", GFXS_BLEND_ZERO << GFXS0_SRCBLEND_RGB_SHIFT},
{"One", GFXS_BLEND_ONE << GFXS0_SRCBLEND_RGB_SHIFT},
{"SrcColor", GFXS_BLEND_SRCCOLOR << GFXS0_SRCBLEND_RGB_SHIFT},
@ -683,7 +683,7 @@ namespace IW4
}
},
{
"mtlDestBlend", 0, {
"mtlDestBlend", 0, GFXS0_DSTBLEND_RGB_MASK, {
{"Zero", GFXS_BLEND_ZERO << GFXS0_DSTBLEND_RGB_SHIFT},
{"One", GFXS_BLEND_ONE << GFXS0_DSTBLEND_RGB_SHIFT},
{"SrcColor", GFXS_BLEND_SRCCOLOR << GFXS0_DSTBLEND_RGB_SHIFT},
@ -697,7 +697,7 @@ namespace IW4
}
},
{
"mtlBlendOpAlpha", 0, {
"mtlBlendOpAlpha", 0, GFXS0_BLENDOP_ALPHA_MASK, {
{"Add", GFXS_BLENDOP_ADD << GFXS0_BLENDOP_ALPHA_SHIFT},
{"Subtract", GFXS_BLENDOP_SUBTRACT << GFXS0_BLENDOP_ALPHA_SHIFT},
{"RevSubtract", GFXS_BLENDOP_REVSUBTRACT << GFXS0_BLENDOP_ALPHA_SHIFT},
@ -707,7 +707,7 @@ namespace IW4
}
},
{
"mtlSrcBlendAlpha", 0, {
"mtlSrcBlendAlpha", 0, GFXS0_SRCBLEND_ALPHA_MASK, {
{"Zero", GFXS_BLEND_ZERO << GFXS0_SRCBLEND_ALPHA_SHIFT},
{"One", GFXS_BLEND_ONE << GFXS0_SRCBLEND_ALPHA_SHIFT},
{"SrcColor", GFXS_BLEND_SRCCOLOR << GFXS0_SRCBLEND_ALPHA_SHIFT},
@ -721,7 +721,7 @@ namespace IW4
}
},
{
"mtlDestBlendAlpha", 0, {
"mtlDestBlendAlpha", 0, GFXS0_DSTBLEND_ALPHA_MASK, {
{"Zero", GFXS_BLEND_ZERO << GFXS0_DSTBLEND_ALPHA_SHIFT},
{"One", GFXS_BLEND_ONE << GFXS0_DSTBLEND_ALPHA_SHIFT},
{"SrcColor", GFXS_BLEND_SRCCOLOR << GFXS0_DSTBLEND_ALPHA_SHIFT},
@ -735,38 +735,38 @@ namespace IW4
}
},
{
"mtlCullFace", 0, {
"mtlCullFace", 0, GFXS0_CULL_MASK, {
{"None", GFXS0_CULL_NONE},
{"Back", GFXS0_CULL_BACK},
{"Front", GFXS0_CULL_FRONT},
}
},
{
"mtlColorWriteRgb", 0, {
"mtlColorWriteRgb", 0, GFXS0_COLORWRITE_RGB, {
{"Enable", GFXS0_COLORWRITE_RGB},
{"Disable", 0},
}
},
{
"mtlColorWriteAlpha", 0, {
"mtlColorWriteAlpha", 0, GFXS0_COLORWRITE_ALPHA, {
{"Enable", GFXS0_COLORWRITE_ALPHA},
{"Disable", 0},
}
},
{
"mtlGammaWrite", 0, {
"mtlGammaWrite", 0, GFXS0_GAMMAWRITE, {
{"Enable", GFXS0_GAMMAWRITE},
{"Disable", 0},
}
},
{
"mtlWireframe", 0, {
"mtlWireframe", 0, GFXS0_POLYMODE_LINE, {
{"Enable", GFXS0_POLYMODE_LINE},
{"Disable", 0},
}
},
{
"mtlDepthTest", 1, {
"mtlDepthTest", 1, GFXS1_DEPTHTEST_DISABLE | GFXS1_DEPTHTEST_MASK, {
{"Disable", GFXS1_DEPTHTEST_DISABLE},
{"Less", GFXS1_DEPTHTEST_LESS},
{"LessEqual", GFXS1_DEPTHTEST_LESSEQUAL},
@ -775,13 +775,13 @@ namespace IW4
}
},
{
"mtlDepthWrite", 1, {
"mtlDepthWrite", 1, GFXS1_DEPTHWRITE, {
{"Enable", GFXS1_DEPTHWRITE},
{"Disable", 0},
}
},
{
"mtlPolygonOffset", 1, {
"mtlPolygonOffset", 1, GFXS1_POLYGON_OFFSET_MASK, {
{"1", GFXS1_POLYGON_OFFSET_1},
{"2", GFXS1_POLYGON_OFFSET_2},
{"shadowmap", GFXS1_POLYGON_OFFSET_SHADOWMAP},
@ -789,14 +789,14 @@ namespace IW4
}
},
{
"mtlStencil", 1, {
"mtlStencil", 1, GFXS1_STENCIL_FRONT_ENABLE | GFXS1_STENCIL_BACK_ENABLE, {
{"OneSided", GFXS1_STENCIL_FRONT_ENABLE},
{"TwoSided", GFXS1_STENCIL_FRONT_ENABLE | GFXS1_STENCIL_BACK_ENABLE},
{"Disable", 0},
}
},
{
"mtlStencilFuncFront", 1, {
"mtlStencilFuncFront", 1, GFXS1_STENCIL_FRONT_FUNC_MASK, {
{"Less", GFXS_STENCILFUNC_LESS << GFXS1_STENCIL_FRONT_FUNC_SHIFT},
{"Equal", GFXS_STENCILFUNC_EQUAL << GFXS1_STENCIL_FRONT_FUNC_SHIFT},
{"LessEqual", GFXS_STENCILFUNC_LESSEQUAL << GFXS1_STENCIL_FRONT_FUNC_SHIFT},
@ -808,7 +808,7 @@ namespace IW4
}
},
{
"mtlStencilOpFrontPass", 1, {
"mtlStencilOpFrontPass", 1, GFXS1_STENCIL_FRONT_PASS_MASK, {
{"Zero", GFXS_STENCILOP_ZERO << GFXS1_STENCIL_FRONT_PASS_SHIFT},
{"Replace", GFXS_STENCILOP_REPLACE << GFXS1_STENCIL_FRONT_PASS_SHIFT},
{"IncrSat", GFXS_STENCILOP_INCRSAT << GFXS1_STENCIL_FRONT_PASS_SHIFT},
@ -820,7 +820,7 @@ namespace IW4
}
},
{
"mtlStencilOpFrontFail", 1, {
"mtlStencilOpFrontFail", 1, GFXS1_STENCIL_FRONT_FAIL_MASK, {
{"Zero", GFXS_STENCILOP_ZERO << GFXS1_STENCIL_FRONT_FAIL_SHIFT},
{"Replace", GFXS_STENCILOP_REPLACE << GFXS1_STENCIL_FRONT_FAIL_SHIFT},
{"IncrSat", GFXS_STENCILOP_INCRSAT << GFXS1_STENCIL_FRONT_FAIL_SHIFT},
@ -832,7 +832,7 @@ namespace IW4
}
},
{
"mtlStencilOpFrontZFail", 1, {
"mtlStencilOpFrontZFail", 1, GFXS1_STENCIL_FRONT_ZFAIL_MASK, {
{"Zero", GFXS_STENCILOP_ZERO << GFXS1_STENCIL_FRONT_ZFAIL_SHIFT},
{"Replace", GFXS_STENCILOP_REPLACE << GFXS1_STENCIL_FRONT_ZFAIL_SHIFT},
{"IncrSat", GFXS_STENCILOP_INCRSAT << GFXS1_STENCIL_FRONT_ZFAIL_SHIFT},
@ -844,7 +844,7 @@ namespace IW4
}
},
{
"mtlStencilFuncBack", 1, {
"mtlStencilFuncBack", 1, GFXS1_STENCIL_BACK_FUNC_MASK, {
{"Less", GFXS_STENCILFUNC_LESS << GFXS1_STENCIL_BACK_FUNC_SHIFT},
{"Equal", GFXS_STENCILFUNC_EQUAL << GFXS1_STENCIL_BACK_FUNC_SHIFT},
{"LessEqual", GFXS_STENCILFUNC_LESSEQUAL << GFXS1_STENCIL_BACK_FUNC_SHIFT},
@ -856,7 +856,7 @@ namespace IW4
}
},
{
"mtlStencilOpBackPass", 1, {
"mtlStencilOpBackPass", 1, GFXS1_STENCIL_BACK_PASS_MASK, {
{"Zero", GFXS_STENCILOP_ZERO << GFXS1_STENCIL_BACK_PASS_SHIFT},
{"Replace", GFXS_STENCILOP_REPLACE << GFXS1_STENCIL_BACK_PASS_SHIFT},
{"IncrSat", GFXS_STENCILOP_INCRSAT << GFXS1_STENCIL_BACK_PASS_SHIFT},
@ -868,7 +868,7 @@ namespace IW4
}
},
{
"mtlStencilOpBackFail", 1, {
"mtlStencilOpBackFail", 1, GFXS1_STENCIL_BACK_FAIL_MASK, {
{"Zero", GFXS_STENCILOP_ZERO << GFXS1_STENCIL_BACK_FAIL_SHIFT},
{"Replace", GFXS_STENCILOP_REPLACE << GFXS1_STENCIL_BACK_FAIL_SHIFT},
{"IncrSat", GFXS_STENCILOP_INCRSAT << GFXS1_STENCIL_BACK_FAIL_SHIFT},
@ -880,7 +880,7 @@ namespace IW4
}
},
{
"mtlStencilOpBackZFail", 1, {
"mtlStencilOpBackZFail", 1, GFXS1_STENCIL_BACK_ZFAIL_MASK, {
{"Zero", GFXS_STENCILOP_ZERO << GFXS1_STENCIL_BACK_ZFAIL_SHIFT},
{"Replace", GFXS_STENCILOP_REPLACE << GFXS1_STENCIL_BACK_ZFAIL_SHIFT},
{"IncrSat", GFXS_STENCILOP_INCRSAT << GFXS1_STENCIL_BACK_ZFAIL_SHIFT},

View File

@ -1,50 +0,0 @@
#include "StateMapExpressionMatchers.h"
#include "Parsing/Simple/Expression/SimpleExpressionScopeValue.h"
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
using namespace state_map;
static constexpr int CAPTURE_VALUE = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION_EXT + 1;
StateMapExpressionMatchers::StateMapExpressionMatchers()
: StateMapExpressionMatchers(nullptr)
{
}
StateMapExpressionMatchers::StateMapExpressionMatchers(StateMapParserState* state)
: SimpleExpressionMatchers(false, false, false, false, true),
m_state(state)
{
}
std::unique_ptr<SimpleExpressionMatchers::matcher_t> StateMapExpressionMatchers::ParseOperandExtension(const supplier_t* labelSupplier) const
{
const SimpleMatcherFactory create(labelSupplier);
return create.Or({
create.Identifier().Capture(CAPTURE_VALUE),
create.Integer().Capture(CAPTURE_VALUE),
});
}
std::unique_ptr<ISimpleExpression> StateMapExpressionMatchers::ProcessOperandExtension(SequenceResult<SimpleParserValue>& result) const
{
assert(m_state);
const auto& valueToken = result.NextCapture(CAPTURE_VALUE);
auto value = valueToken.m_type == SimpleParserValueType::IDENTIFIER ? valueToken.IdentifierValue() : std::to_string(valueToken.IntegerValue());
if (value.rfind("mtl", 0) == 0)
{
if (m_state->m_valid_vars.find(value) == m_state->m_valid_vars.end())
throw ParsingException(valueToken.GetPos(), "Unknown variable");
return std::make_unique<SimpleExpressionScopeValue>(value);
}
if (m_state->m_valid_values.find(value) == m_state->m_valid_values.end())
throw ParsingException(valueToken.GetPos(), "Unknown value");
return std::make_unique<SimpleExpressionValue>(value);
}

View File

@ -1,23 +0,0 @@
#pragma once
#include <memory>
#include "Parsing/Simple/Expression/SimpleExpressionMatchers.h"
#include "StateMap/Parsing/StateMapParserState.h"
namespace state_map
{
class StateMapExpressionMatchers final : public SimpleExpressionMatchers
{
public:
StateMapExpressionMatchers();
explicit StateMapExpressionMatchers(StateMapParserState* state);
protected:
std::unique_ptr<matcher_t> ParseOperandExtension(const supplier_t* labelSupplier) const override;
std::unique_ptr<ISimpleExpression> ProcessOperandExtension(SequenceResult<SimpleParserValue>& result) const override;
private:
StateMapParserState* m_state;
};
}

View File

@ -1,6 +1,8 @@
#include "StateMapParser.h"
#include "Matcher/StateMapExpressionMatchers.h"
#include <array>
#include <sstream>
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
using namespace state_map;
@ -64,18 +66,45 @@ namespace state_map
class SequenceCondition final : public StateMapParser::sequence_t
{
static constexpr auto TAG_DEFAULT = 1;
static constexpr auto TAG_EXPRESSION = 2;
static constexpr auto TAG_CONDITION = 2;
static constexpr auto TAG_EQUALS_OPERATION = 3;
static constexpr auto CAPTURE_OPERATOR = 1;
static constexpr auto LABEL_CONDITION = 1;
static constexpr auto LABEL_EQUALS_OPERATION = 2;
static constexpr auto LABEL_CONDITION_OPERATOR = 3;
public:
SequenceCondition()
{
AddLabeledMatchers(StateMapExpressionMatchers().Expression(this), StateMapExpressionMatchers::LABEL_EXPRESSION);
const SimpleMatcherFactory create(this);
AddLabeledMatchers(create.Or({
create.Identifier(),
create.Integer()
}).Capture(CAPTURE_OPERATOR), LABEL_CONDITION_OPERATOR);
AddLabeledMatchers(create.And({
create.True().Tag(TAG_EQUALS_OPERATION),
create.Label(LABEL_CONDITION_OPERATOR),
create.MultiChar(StateMapParser::MULTI_TOKEN_EQUALS),
create.Label(LABEL_CONDITION_OPERATOR)
}), LABEL_EQUALS_OPERATION);
AddLabeledMatchers(create.And({
create.True().Tag(TAG_CONDITION),
create.Label(LABEL_EQUALS_OPERATION),
create.OptionalLoop(create.And({
create.MultiChar(StateMapParser::MULTI_TOKEN_AND),
create.Label(LABEL_EQUALS_OPERATION)
}))
}), LABEL_CONDITION);
AddMatchers({
create.Or({
create.Keyword("default").Tag(TAG_DEFAULT),
create.Label(StateMapExpressionMatchers::LABEL_EXPRESSION).Tag(TAG_EXPRESSION)
create.Label(LABEL_CONDITION)
}),
create.Char(':')
});
@ -94,11 +123,10 @@ namespace state_map
state->m_definition->m_state_map_entries[state->m_current_entry_index].m_rules.emplace_back(std::move(newRule));
}
if (result.PeekAndRemoveIfTag(TAG_EXPRESSION) == TAG_EXPRESSION)
if (result.PeekAndRemoveIfTag(TAG_CONDITION) == TAG_CONDITION)
{
auto expression = StateMapExpressionMatchers(state).ProcessExpression(result);
state->m_current_rule->m_conditions.emplace_back(std::move(expression));
auto condition = ProcessCondition(state, result);
state->m_current_rule->m_conditions.emplace_back(std::move(condition));
}
else
{
@ -108,6 +136,73 @@ namespace state_map
entry.m_default_index = entry.m_rules.size() - 1;
}
}
static StateMapCondition ProcessCondition(const StateMapParserState* state, SequenceResult<SimpleParserValue>& result)
{
StateMapCondition condition(state->m_layout.m_state_bits_count);
while (result.PeekAndRemoveIfTag(TAG_EQUALS_OPERATION) == TAG_EQUALS_OPERATION)
{
std::array<std::reference_wrapper<const SimpleParserValue>, 2> operatorToken
{
result.NextCapture(CAPTURE_OPERATOR),
result.NextCapture(CAPTURE_OPERATOR)
};
std::array<std::string, 2> operatorValue
{
ProcessOperator(operatorToken[0]),
ProcessOperator(operatorToken[1])
};
const auto variableIndex = IsVariable(operatorValue[1]) ? 1 : 0;
const auto valueIndex = variableIndex == 0 ? 1 : 0;
const auto& variable = GetVariable(state, operatorToken[variableIndex], operatorValue[variableIndex]);
const auto& value = GetValue(variable, operatorToken[valueIndex], operatorValue[valueIndex]);
condition.m_masks_per_index[variable.m_state_bits_index] |= variable.m_values_mask;
condition.m_values_per_index[variable.m_state_bits_index] |= value.m_state_bits_mask;
}
return condition;
}
static std::string ProcessOperator(const SimpleParserValue& token)
{
return token.m_type == SimpleParserValueType::IDENTIFIER ? token.IdentifierValue() : std::to_string(token.IntegerValue());
}
static bool IsVariable(const std::string& _operator)
{
return _operator.rfind("mtl", 0) == 0;
}
static const StateMapLayoutVar& GetVariable(const StateMapParserState* state, const SimpleParserValue& operatorToken, const std::string& operatorValue)
{
const auto& foundVariable = state->m_valid_vars.find(operatorValue);
if (foundVariable == state->m_valid_vars.end())
throw ParsingException(operatorToken.GetPos(), "Unknown variable");
return state->m_layout.m_var_layout.m_vars[foundVariable->second];
}
static const StateMapLayoutVarValue& GetValue(const StateMapLayoutVar& variable, const SimpleParserValue& operatorToken, const std::string& operatorValue)
{
const auto matchingValue = std::find_if(variable.m_values.begin(), variable.m_values.end(), [&operatorValue](const StateMapLayoutVarValue& value)
{
return value.m_name == operatorValue;
});
if (matchingValue == variable.m_values.end())
{
std::ostringstream ss;
ss << "Unknown value for variable \"" << variable.m_name << "\"";
throw ParsingException(operatorToken.GetPos(), ss.str());
}
return *matchingValue;
}
};
class SequenceValue final : public StateMapParser::sequence_t

View File

@ -11,6 +11,10 @@ namespace state_map
{
class StateMapParser final : public AbstractParser<SimpleParserValue, StateMapParserState>
{
public:
static constexpr auto MULTI_TOKEN_AND = 600;
static constexpr auto MULTI_TOKEN_EQUALS = 601;
protected:
const std::vector<sequence_t*>& GetTestsForState() override;

View File

@ -2,6 +2,12 @@
using namespace state_map;
StateMapCondition::StateMapCondition(const size_t entryCount)
: m_masks_per_index(entryCount),
m_values_per_index(entryCount)
{
}
StateMapRule::StateMapRule()
: m_value(0u),
m_passthrough(false)

View File

@ -4,14 +4,21 @@
#include <string>
#include <vector>
#include "Parsing/Simple/Expression/ISimpleExpression.h"
namespace state_map
{
class StateMapCondition
{
public:
std::vector<size_t> m_masks_per_index;
std::vector<size_t> m_values_per_index;
explicit StateMapCondition(size_t entryCount);
};
class StateMapRule
{
public:
std::vector<std::unique_ptr<ISimpleExpression>> m_conditions;
std::vector<StateMapCondition> m_conditions;
size_t m_value;
bool m_passthrough;

View File

@ -6,21 +6,6 @@
using namespace state_map;
void StateMapVars::AddValue(std::string key, std::string value)
{
m_vars.emplace(std::make_pair(std::move(key), std::move(value)));
}
SimpleExpressionValue StateMapVars::ValueByName(const std::string& name) const
{
const auto foundValue = m_vars.find(name);
if (foundValue != m_vars.end())
return SimpleExpressionValue(foundValue->second);
return SimpleExpressionValue(0);
}
StateMapHandler::StateMapHandler(const StateMapLayout& stateMapLayout, const StateMapDefinition& stateMap)
: m_state_map_layout(stateMapLayout),
m_state_map(stateMap)
@ -32,19 +17,17 @@ void StateMapHandler::ApplyStateMap(const uint32_t* baseStateBits, uint32_t* out
assert(baseStateBits != nullptr);
assert(outStateBits != nullptr);
const auto vars = BuildVars(baseStateBits);
for (auto i = 0u; i < m_state_map_layout.m_state_bits_count; i++)
outStateBits[i] = baseStateBits[i];
for (auto entryIndex = 0u; entryIndex < m_state_map.m_state_map_entries.size(); entryIndex++)
{
const auto& entry = m_state_map.m_state_map_entries[entryIndex];
const auto matchingRule = std::find_if(entry.m_rules.begin(), entry.m_rules.end(), [&vars](const std::unique_ptr<StateMapRule>& rule)
const auto matchingRule = std::find_if(entry.m_rules.begin(), entry.m_rules.end(), [&baseStateBits](const std::unique_ptr<StateMapRule>& rule)
{
const auto matchingCondition = std::find_if(rule->m_conditions.begin(), rule->m_conditions.end(), [&vars](std::unique_ptr<ISimpleExpression>& condition)
const auto matchingCondition = std::find_if(rule->m_conditions.begin(), rule->m_conditions.end(), [&baseStateBits](const StateMapCondition& condition)
{
return condition->EvaluateNonStatic(&vars).IsTruthy();
return ConditionIsTrue(condition, baseStateBits);
});
return matchingCondition != rule->m_conditions.end();
@ -57,27 +40,6 @@ void StateMapHandler::ApplyStateMap(const uint32_t* baseStateBits, uint32_t* out
}
}
StateMapVars StateMapHandler::BuildVars(const uint32_t* baseStateBits) const
{
StateMapVars result;
for (const auto& var : m_state_map_layout.m_var_layout.m_vars)
{
const auto baseStateBitField = baseStateBits[var.m_state_bits_index];
const auto matchingValue = std::find_if(var.m_values.begin(), var.m_values.end(), [&baseStateBitField](const StateMapLayoutVarValue& value)
{
return (baseStateBitField & value.m_state_bits_mask) == value.m_state_bits_mask;
});
if (matchingValue != var.m_values.end())
result.AddValue(var.m_name, matchingValue->m_name);
else
std::cerr << "Could not find base value for state map var \"" << var.m_name << "\"\n";
}
return result;
}
void StateMapHandler::ApplyRule(const StateMapLayoutEntry& entry, const StateMapRule& rule, uint32_t* outStateBits)
{
if (rule.m_passthrough)
@ -86,3 +48,15 @@ void StateMapHandler::ApplyRule(const StateMapLayoutEntry& entry, const StateMap
outStateBits[entry.m_state_bits_index] &= ~entry.m_state_bits_mask;
outStateBits[entry.m_state_bits_index] |= rule.m_value;
}
bool StateMapHandler::ConditionIsTrue(const StateMapCondition& condition, const uint32_t* stateBits)
{
const auto stateBitCount = std::min(condition.m_masks_per_index.size(), condition.m_values_per_index.size());
for (auto stateBitIndex = 0u; stateBitIndex < stateBitCount; stateBitIndex++)
{
if ((stateBits[stateBitIndex] & condition.m_masks_per_index[stateBitIndex]) != condition.m_values_per_index[stateBitIndex])
return false;
}
return true;
}

View File

@ -1,24 +1,12 @@
#pragma once
#include <cstdint>
#include <unordered_map>
#include "Utils/ClassUtils.h"
#include "StateMap/StateMapDefinition.h"
#include "StateMap/StateMapLayout.h"
namespace state_map
{
class StateMapVars final : public ISimpleExpressionScopeValues
{
public:
void AddValue(std::string key, std::string value);
_NODISCARD SimpleExpressionValue ValueByName(const std::string& name) const override;
private:
std::unordered_map<std::string, std::string> m_vars;
};
class StateMapHandler
{
public:
@ -27,8 +15,8 @@ namespace state_map
void ApplyStateMap(const uint32_t* baseStateBits, uint32_t* outStateBits) const;
private:
StateMapVars BuildVars(const uint32_t* baseStateBits) const;
static void ApplyRule(const StateMapLayoutEntry& entry, const StateMapRule& rule, uint32_t* outStateBits);
static bool ConditionIsTrue(const StateMapCondition& condition, const uint32_t* stateBits);
const StateMapLayout& m_state_map_layout;
const StateMapDefinition& m_state_map;

View File

@ -5,7 +5,6 @@
#include "Parsing/StateMapParser.h"
#include "Parsing/Impl/CommentRemovingStreamProxy.h"
#include "Parsing/Impl/ParserSingleInputStream.h"
#include "Parsing/Matcher/StateMapExpressionMatchers.h"
using namespace state_map;
@ -51,7 +50,8 @@ std::unique_ptr<StateMapDefinition> StateMapReader::ReadStateMapDefinition() con
lexerConfig.m_read_strings = false;
lexerConfig.m_read_integer_numbers = true;
lexerConfig.m_read_floating_point_numbers = false;
StateMapExpressionMatchers().ApplyTokensToLexerConfig(lexerConfig);
lexerConfig.m_multi_character_tokens.emplace_back(StateMapParser::MULTI_TOKEN_AND, "&&");
lexerConfig.m_multi_character_tokens.emplace_back(StateMapParser::MULTI_TOKEN_EQUALS, "==");
const auto lexer = std::make_unique<SimpleLexer>(m_comment_proxy.get(), std::move(lexerConfig));
const auto parser = std::make_unique<StateMapParser>(lexer.get(), m_state_map_name, m_state_map_layout);