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());
41double Cogs::Core::ExpressionContext::eval(std::string_view expression,
double defaultValue)
43 double result = defaultValue;
45 auto expr = compile(expression,
"");
47 if (expr && expr->expression) {
48 result = te_eval(expr->expression);
56Cogs::Core::Expression * Cogs::Core::ExpressionContext::compile(std::string_view expression, std::string_view variable)
59 ExpressionVariable* resultVariable =
nullptr;
61 if (variable.size()) {
62 for (
auto & v : values) {
63 if (variable == v.name) {
68 auto fIt = expressions.find(code);
70 if (fIt != expressions.end()) {
75 auto expr = te_compile(expression.data(), expression.size(), &scope, &error);
78 LOG_ERROR(logger,
"Could not compile expression '%.*s' <error> '%.*s'.",
79 StringViewFormat(expression.substr(0, error)),
80 StringViewFormat(expression.substr(error)));
84 expressions[code] = Expression{ std::string(expression), resultVariable, expr, code };
86 return &expressions[code];
89void Cogs::Core::ExpressionContext::free(Expression * )
97 for (
auto & v : values) {
104 values.emplace_back();
105 variables.emplace_back();
107 auto & v = values.back();
109 v.name = std::string(name);
112 auto & var = variables.back();
114 var.address = &values.back().value;
115 var.name = v.name.c_str();
117 scope.variables = variables.data();
118 scope.var_count =
static_cast<int>(variables.size());
123double Cogs::Core::ExpressionContext::update(
const Expression * expression,
double defaultValue)
125 if (!expression || !expression->expression)
return defaultValue;
127 auto result = te_eval(expression->expression);
129 if (expression->resultVariable) {
130 expression->resultVariable->value = result;
136float Cogs::Core::ExpressionContext::update(
const Expression * expression,
float defaultValue)
138 return static_cast<float>(update(expression,
static_cast<double>(defaultValue)));
141int Cogs::Core::ExpressionContext::update(
const Expression * expression,
int defaultValue)
143 return static_cast<int>(update(expression,
static_cast<double>(defaultValue)));
146size_t Cogs::Core::ExpressionContext::update(
const Expression * expression,
size_t defaultValue)
148 double value = update(expression,
static_cast<double>(defaultValue));
150 if (glm::fract(value) > std::numeric_limits<double>::epsilon()) {
151 LOG_TRACE(logger,
"Truncating evaluated expression %f", value);
154 return static_cast<size_t>(value);
157void Cogs::Core::ExpressionContext::link(ExpressionContext * source, std::string_view sourceName, std::string_view destName)
160 while (source !=
nullptr) {
161 int numSourceVars = source->scope.var_count;
162 for (
int i = 0; i < numSourceVars; ++i) {
163 if (sourceName == source->variables[i].name) {
164 auto& sourceVariable = source->variables[i];
166 values.emplace_back();
167 variables.emplace_back();
169 auto& v = values.back();
171 v.name = std::string(destName);
172 v.value = source->values[i].value;
174 auto& var = variables.back();
178 var.address = &source->values[i].value;
179 var.name = v.name.c_str();
180 var.link = &sourceVariable;
182 scope.variables = variables.data();
183 scope.var_count =
static_cast<int>(variables.size());
188 source = source->parent;
191 LOG_WARNING(logger,
"Could not link variable. \"%s\" to \"%s\".", sourceName.data(), destName.data());
194void Cogs::Core::ExpressionContext::clear()
196 for (
auto & e : expressions) {
197 te_free(e.second.expression);
202 scope.parent =
nullptr;
203 scope.variables =
nullptr;
207std::span<const Cogs::Core::ExpressionVariable> Cogs::Core::ExpressionContext::getValues()
const
209 return std::span(values.data(), values.data() + values.size());
212std::span<Cogs::Core::ExpressionVariable> Cogs::Core::ExpressionContext::getValues()
214 return std::span(values.data(), values.data() + values.size());
217void Cogs::Core::readSize_t(ExpressionValue<size_t> & value, ExpressionContext * ev,
const std::string & prefix,
const ParsedValue & parsedValue)
219 if (parsedValue.type == ParsedDataType::Int) {
220 value = parsedValue.intValue;
221 }
else if (parsedValue.type == ParsedDataType::Float) {
222 value =
static_cast<size_t>(parsedValue.floatValue);
224 value = ExpressionValue<size_t>(ev, prefix +
"." + parsedValue.key, parsedValue.value, 0);
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.