Skip to content
Snippets Groups Projects
Commit 8366faeb authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Continue vector component affectation (still buggy)

parent 9b0c7f9d
No related branches found
No related tags found
1 merge request!37Feature/language
...@@ -54,7 +54,7 @@ struct AffOp<language::minuseq_op> ...@@ -54,7 +54,7 @@ struct AffOp<language::minuseq_op>
struct IAffectationExecutor struct IAffectationExecutor
{ {
virtual void affect(DataVariant&& rhs) = 0; virtual void affect(ExecutionPolicy& exec_policy, DataVariant&& rhs) = 0;
virtual ~IAffectationExecutor() = default; virtual ~IAffectationExecutor() = default;
}; };
...@@ -85,7 +85,7 @@ class AffectationExecutor final : public IAffectationExecutor ...@@ -85,7 +85,7 @@ class AffectationExecutor final : public IAffectationExecutor
} }
PUGS_INLINE void PUGS_INLINE void
affect(DataVariant&& rhs) affect(ExecutionPolicy&, DataVariant&& rhs)
{ {
if constexpr (_is_defined) { if constexpr (_is_defined) {
if constexpr (std::is_same_v<ValueT, std::string>) { if constexpr (std::is_same_v<ValueT, std::string>) {
...@@ -118,6 +118,84 @@ class AffectationExecutor final : public IAffectationExecutor ...@@ -118,6 +118,84 @@ class AffectationExecutor final : public IAffectationExecutor
} }
}; };
template <typename OperatorT, typename ArrayT, typename ValueT, typename DataT>
class ComponentAffectationExecutor final : public IAffectationExecutor
{
private:
ArrayT& m_lhs_array;
ASTNode& m_index_expression;
static inline const bool _is_defined{[] {
if constexpr (not std::is_same_v<typename ArrayT::data_type, ValueT>) {
return false;
} else if constexpr (std::is_same_v<std::decay_t<ValueT>, bool>) {
if constexpr (not std::is_same_v<OperatorT, language::eq_op>) {
return false;
}
}
return true;
}()};
public:
ComponentAffectationExecutor(ASTNode& node, ArrayT& lhs_array)
: m_lhs_array{lhs_array}, m_index_expression{*node.children[1]}
{
// LCOV_EXCL_START
if constexpr (not _is_defined) {
throw parse_error("unexpected error: invalid operands to affectation expression", std::vector{node.begin()});
}
// LCOV_EXCL_STOP
}
PUGS_INLINE void
affect(ExecutionPolicy& exec_policy, DataVariant&& rhs)
{
if constexpr (_is_defined) {
const int64_t index_value = [&](DataVariant&& value_variant) -> int64_t {
int64_t index_value = 0;
std::visit(
[&](auto&& value) {
using IndexValueT = std::decay_t<decltype(value)>;
if constexpr (std::is_integral_v<IndexValueT>) {
index_value = value;
} else {
throw parse_error("unexpected error: invalid index type", std::vector{m_index_expression.begin()});
}
},
value_variant);
return index_value;
}(m_index_expression.execute(exec_policy));
if constexpr (std::is_same_v<ValueT, std::string>) {
if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
if constexpr (std::is_same_v<std::string, DataT>) {
m_lhs_array[index_value] = std::get<DataT>(rhs);
} else {
m_lhs_array[index_value] = std::to_string(std::get<DataT>(rhs));
}
} else {
static_assert(std::is_same_v<OperatorT, language::pluseq_op>, "unexpected operator type");
if constexpr (std::is_same_v<std::string, DataT>) {
m_lhs_array[index_value] += std::get<std::string>(rhs);
} else {
m_lhs_array[index_value] += std::to_string(std::get<DataT>(rhs));
}
}
} else {
if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
if constexpr (std::is_same_v<ValueT, DataT>) {
m_lhs_array[index_value] = std::get<DataT>(rhs);
} else {
m_lhs_array[index_value] = static_cast<ValueT>(std::get<DataT>(rhs));
}
} else {
AffOp<OperatorT>().eval(m_lhs_array[index_value], std::get<DataT>(rhs));
}
}
}
}
};
template <typename OperatorT, typename ValueT, typename DataT> template <typename OperatorT, typename ValueT, typename DataT>
class AffectationProcessor final : public INodeProcessor class AffectationProcessor final : public INodeProcessor
{ {
...@@ -130,7 +208,7 @@ class AffectationProcessor final : public INodeProcessor ...@@ -130,7 +208,7 @@ class AffectationProcessor final : public INodeProcessor
DataVariant DataVariant
execute(ExecutionPolicy& exec_policy) execute(ExecutionPolicy& exec_policy)
{ {
m_affectation_executor->affect(m_node.children[1]->execute(exec_policy)); m_affectation_executor->affect(exec_policy, m_node.children[1]->execute(exec_policy));
return {}; return {};
} }
...@@ -149,6 +227,55 @@ class AffectationProcessor final : public INodeProcessor ...@@ -149,6 +227,55 @@ class AffectationProcessor final : public INodeProcessor
using AffectationExecutorT = AffectationExecutor<OperatorT, ValueT, DataT>; using AffectationExecutorT = AffectationExecutor<OperatorT, ValueT, DataT>;
m_affectation_executor = std::make_unique<AffectationExecutorT>(m_node, std::get<ValueT>(value)); m_affectation_executor = std::make_unique<AffectationExecutorT>(m_node, std::get<ValueT>(value));
} else if (node.children[0]->is_type<language::subscript_expression>()) {
auto& array_subscript_expression = *node.children[0];
auto& array_expression = *array_subscript_expression.children[0];
Assert(array_expression.is_type<language::name>());
const std::string& symbol = array_expression.string();
auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin());
Assert(found);
DataVariant& value = i_symbol->attributes().value();
if (array_expression.m_data_type != ASTNodeDataType::vector_t) {
throw parse_error("unexpected error: invalid lhs (expecting R^d)", std::vector{node.children[0]->begin()});
}
switch (array_expression.m_data_type.dimension()) {
case 1: {
using ArrayTypeT = TinyVector<1>;
if (not std::holds_alternative<ArrayTypeT>(value)) {
value = ArrayTypeT{};
}
using AffectationExecutorT = ComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>;
m_affectation_executor = std::make_unique<AffectationExecutorT>(m_node, std::get<ArrayTypeT>(value));
break;
}
case 2: {
using ArrayTypeT = TinyVector<2>;
if (not std::holds_alternative<ArrayTypeT>(value)) {
value = ArrayTypeT{};
}
using AffectationExecutorT = ComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>;
m_affectation_executor = std::make_unique<AffectationExecutorT>(m_node, std::get<ArrayTypeT>(value));
break;
}
case 3: {
using ArrayTypeT = TinyVector<3>;
if (not std::holds_alternative<ArrayTypeT>(value)) {
value = ArrayTypeT{};
}
using AffectationExecutorT = ComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>;
m_affectation_executor = std::make_unique<AffectationExecutorT>(m_node, std::get<ArrayTypeT>(value));
break;
}
default: {
throw parse_error("unexpected error: invalid vector dimension", std::vector{node.children[0]->begin()});
}
}
} else { } else {
throw parse_error("unexpected error: invalid lhs", std::vector{node.children[0]->begin()}); throw parse_error("unexpected error: invalid lhs", std::vector{node.children[0]->begin()});
} }
...@@ -264,7 +391,7 @@ class ListAffectationProcessor final : public INodeProcessor ...@@ -264,7 +391,7 @@ class ListAffectationProcessor final : public INodeProcessor
Assert(m_affectation_executor_list.size() == children_values.size()); Assert(m_affectation_executor_list.size() == children_values.size());
for (size_t i = 0; i < m_affectation_executor_list.size(); ++i) { for (size_t i = 0; i < m_affectation_executor_list.size(); ++i) {
m_affectation_executor_list[i]->affect(std::move(children_values[i])); m_affectation_executor_list[i]->affect(exec_policy, std::move(children_values[i]));
} }
return {}; return {};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment