summaryrefslogtreecommitdiffstats
path: root/src/libixion/formula_value_stack.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libixion/formula_value_stack.hpp')
-rw-r--r--src/libixion/formula_value_stack.hpp153
1 files changed, 153 insertions, 0 deletions
diff --git a/src/libixion/formula_value_stack.hpp b/src/libixion/formula_value_stack.hpp
new file mode 100644
index 0000000..91c8fb0
--- /dev/null
+++ b/src/libixion/formula_value_stack.hpp
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_IXION_FORMULA_VALUE_STACK_HPP
+#define INCLUDED_IXION_FORMULA_VALUE_STACK_HPP
+
+#include <ixion/address.hpp>
+#include <ixion/global.hpp>
+#include <ixion/matrix.hpp>
+#include <ixion/model_context.hpp>
+
+#include "impl_types.hpp"
+
+#include <deque>
+#include <variant>
+#include <ostream>
+#include <optional>
+
+namespace ixion {
+
+/**
+ * Type of stack value which can be used as intermediate value during
+ * formula interpretation.
+ */
+enum class stack_value_t
+{
+ boolean,
+ error,
+ value,
+ string,
+ single_ref,
+ range_ref,
+ matrix,
+};
+
+std::ostream& operator<<(std::ostream& os, stack_value_t sv);
+
+/**
+ * Individual stack value storage.
+ */
+class stack_value
+{
+ using stored_value_type = std::variant<bool, double, abs_address_t, abs_range_t, formula_error_t, matrix, std::string>;
+
+ stack_value_t m_type;
+ stored_value_type m_value;
+
+public:
+ stack_value() = delete;
+ stack_value(const stack_value&) = delete;
+ stack_value& operator= (const stack_value&) = delete;
+
+ explicit stack_value(bool b);
+ explicit stack_value(double val);
+ explicit stack_value(std::string str);
+ explicit stack_value(const abs_address_t& val);
+ explicit stack_value(const abs_range_t& val);
+ explicit stack_value(formula_error_t err);
+ explicit stack_value(matrix mtx);
+ stack_value(stack_value&& other);
+ ~stack_value();
+
+ stack_value& operator= (stack_value&& other);
+
+ stack_value_t get_type() const;
+ bool get_boolean() const;
+ double get_value() const;
+ const std::string& get_string() const;
+ const abs_address_t& get_address() const;
+ const abs_range_t& get_range() const;
+ formula_error_t get_error() const;
+
+ const matrix& get_matrix() const;
+
+ /**
+ * Move the matrix value out from storage. The internal matrix content
+ * will be empty after this call.
+ */
+ matrix pop_matrix();
+};
+
+/**
+ * FILO stack of values; last pushed value gets popped first.
+ */
+class formula_value_stack
+{
+ typedef std::deque<stack_value> store_type;
+ store_type m_stack;
+ const model_context& m_context;
+
+public:
+ formula_value_stack() = delete;
+ formula_value_stack(const formula_value_stack&) = delete;
+ formula_value_stack& operator= (const formula_value_stack&) = delete;
+
+ explicit formula_value_stack(const model_context& cxt);
+
+ typedef store_type::value_type value_type;
+ typedef store_type::iterator iterator;
+ typedef store_type::const_iterator const_iterator;
+ iterator begin();
+ iterator end();
+ const_iterator begin() const;
+ const_iterator end() const;
+ value_type release(iterator pos);
+ value_type release_back();
+ bool empty() const;
+ size_t size() const;
+ void clear();
+ void swap(formula_value_stack& other);
+
+ stack_value& back();
+ const stack_value& back() const;
+ const stack_value& operator[](size_t pos) const;
+
+ double get_value(size_t pos) const;
+
+ void push_back(value_type&& val);
+ void push_boolean(bool b);
+ void push_value(double val);
+ void push_string(std::string str);
+ void push_single_ref(const abs_address_t& val);
+ void push_range_ref(const abs_range_t& val);
+ void push_matrix(matrix mtx);
+ void push_error(formula_error_t err);
+
+ bool pop_boolean();
+ double pop_value();
+ std::string pop_string();
+ matrix pop_matrix();
+ std::optional<matrix> maybe_pop_matrix();
+ abs_address_t pop_single_ref();
+ abs_range_t pop_range_ref();
+ matrix pop_range_value();
+ formula_error_t pop_error();
+
+ resolved_stack_value pop_matrix_or_numeric();
+ resolved_stack_value pop_matrix_or_string();
+
+ void pop_back();
+
+ stack_value_t get_type() const;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */