1#include "Expressions.h"
5#include "Foundation/HashFunctions.h"
6#include "Foundation/StringViewFormat.h"
8#include "Foundation/Logging/Logger.h"
17Cogs::Core::ExpressionContext::ExpressionContext()
23void Cogs::Core::ExpressionContext::reserve()
25 values.reserve(kMaxVariables);
26 variables.reserve(kMaxVariables);
29void Cogs::Core::ExpressionContext::inherit(ExpressionContext * other)
31 assert(parent ==
nullptr);
34 assert(scope.parent ==
nullptr);
35 scope.parent = &other->scope;
37 scope.variables = variables.data();
38 scope.var_count =
static_cast<int>(variables.size());
41float Cogs::Core::ExpressionContext::eval(std::string_view expression,
float defaultValue)
43 return static_cast<float>(eval(expression,
static_cast<double>(defaultValue)));
46double Cogs::Core::ExpressionContext::eval(std::string_view expression,
double defaultValue)
48 double result = defaultValue;
50 auto expr = compile(expression,
"");
52 if (expr && expr->expression) {
53 result =
static_cast<float>(te_eval(expr->expression));
61int Cogs::Core::ExpressionContext::eval(std::string_view expression,
int defaultValue)
63 return static_cast<int>(eval(expression,
static_cast<double>(defaultValue)));
66Cogs::Core::Expression * Cogs::Core::ExpressionContext::compile(std::string_view expression, std::string_view variable)
69 ExpressionVariable* resultVariable =
nullptr;
71 if (variable.size()) {
72 for (
auto & v : values) {
73 if (variable == v.name) {
78 auto fIt = expressions.find(code);
80 if (fIt != expressions.end()) {
85 auto expr = te_compile(expression.data(), expression.size(), &scope, &error);
88 LOG_ERROR(logger,
"Could not compile expression '%.*s' <error> '%.*s'.",
89 StringViewFormat(expression.substr(0, error)),
90 StringViewFormat(expression.substr(error)));
94 expressions[code] = Expression{ std::string(expression), resultVariable, expr, code };
96 return &expressions[code];
99void Cogs::Core::ExpressionContext::free(Expression * )
107 for (
auto & v : values) {
108 if (name == v.name) {
114 values.emplace_back();
115 variables.emplace_back();
117 auto & v = values.back();
119 v.name = std::string(name);
122 auto & var = variables.back();
124 var.address = &values.back().value;
125 var.name = v.name.c_str();
127 scope.variables = variables.data();
128 scope.var_count =
static_cast<int>(variables.size());
133double Cogs::Core::ExpressionContext::update(
const Expression * expression,
double defaultValue)
135 if (!expression || !expression->expression)
return defaultValue;
137 auto result = te_eval(expression->expression);
139 if (expression->resultVariable) {
140 expression->resultVariable->value = result;
146float Cogs::Core::ExpressionContext::update(
const Expression * expression,
float defaultValue)
148 return static_cast<float>(update(expression,
static_cast<double>(defaultValue)));
151int Cogs::Core::ExpressionContext::update(
const Expression * expression,
int defaultValue)
153 return static_cast<int>(update(expression,
static_cast<double>(defaultValue)));
156size_t Cogs::Core::ExpressionContext::update(
const Expression * expression,
size_t defaultValue)
158 double value = update(expression,
static_cast<double>(defaultValue));
160 if (glm::fract(value) > std::numeric_limits<double>::epsilon()) {
161 LOG_TRACE(logger,
"Truncating evaluated expression %f", value);
164 return static_cast<size_t>(value);
167void Cogs::Core::ExpressionContext::link(ExpressionContext * source, std::string_view sourceName, std::string_view destName)
170 while (source !=
nullptr) {
171 int numSourceVars = source->scope.var_count;
172 for (
int i = 0; i < numSourceVars; ++i) {
173 if (sourceName == source->variables[i].name) {
174 auto& sourceVariable = source->variables[i];
176 values.emplace_back();
177 variables.emplace_back();
179 auto& v = values.back();
181 v.name = std::string(destName);
182 v.value = source->values[i].value;
184 auto& var = variables.back();
186 var.address = &values.back().value;
187 var.name = v.name.c_str();
188 var.link = &sourceVariable;
190 scope.variables = variables.data();
191 scope.var_count =
static_cast<int>(variables.size());
196 source = source->parent;
199 LOG_WARNING(logger,
"Could not link variable.");
202void Cogs::Core::ExpressionContext::clear()
204 for (
auto & e : expressions) {
205 te_free(e.second.expression);
210 scope.parent =
nullptr;
211 scope.variables =
nullptr;
215std::span<const Cogs::Core::ExpressionVariable> Cogs::Core::ExpressionContext::getValues()
const
217 return std::span(values.data(), values.data() + values.size());
220std::span<Cogs::Core::ExpressionVariable> Cogs::Core::ExpressionContext::getValues()
222 return std::span(values.data(), values.data() + values.size());
225void Cogs::Core::readSize_t(ExpressionValue<size_t> & value, ExpressionContext * ev,
const std::string & prefix,
const ParsedValue & parsedValue)
227 if (parsedValue.type == ParsedDataType::Int) {
228 value = parsedValue.intValue;
229 }
else if (parsedValue.type == ParsedDataType::Float) {
230 value =
static_cast<size_t>(parsedValue.floatValue);
232 value = { ev, prefix +
"." + parsedValue.key, parsedValue.value };
Log implementation class.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
constexpr size_t hash() noexcept
Simple getter function that returns the initial value for fnv1a hashing.
Defines a single named expression variable.
Defines a string expression, to be parsed and evaluated by an expression context.