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

Terminate R^d vectors declarations and affectation

One can now write
``
R^3 u = (1, 2, 3);
R^3 v = u;

R^3 w = 0; // One cannot give another scalar value: just the constant value 0
           // that is `R^3 w = 1-1;` is an error!

w += u;    // w and u belong to the same space R^d (with d=3 here)

v *= 2.5-1;// the right hand side is a scalar expression that can be naturally
           // cast to an R

v -= u;
``
These constructions are allowed for small vectors: valid types are `R^1`, `R^2`
and `R^3`.

Remark: tuples are only allowed in initialization:
``
R^2 v = (0,1); // ok

R^2 w ;
w = (2,3);     // ok

w += (1,4);    // forbidden
``
parent ac9400d4
No related branches found
No related tags found
1 merge request!37Feature/language
......@@ -44,21 +44,91 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode
using OperatorT = std::decay_t<decltype(operator_v)>;
using ValueT = std::decay_t<decltype(value)>;
if constexpr (std::is_same_v<OperatorT, language::eq_op> or std::is_same_v<OperatorT, language::pluseq_op>) {
if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
switch (data_type) {
case ASTNodeDataType::vector_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, ValueT>>(n);
break;
}
case ASTNodeDataType::list_t: {
n.m_node_processor = std::make_unique<AffectationFromListProcessor<OperatorT, ValueT>>(n);
break;
}
case ASTNodeDataType::bool_t: {
if constexpr (std::is_same_v<ValueT, TinyVector<1>>) {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, bool>>(n);
break;
}
}
case ASTNodeDataType::unsigned_int_t: {
if constexpr (std::is_same_v<ValueT, TinyVector<1>>) {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, uint64_t>>(n);
break;
}
}
case ASTNodeDataType::int_t: {
if constexpr (std::is_same_v<ValueT, TinyVector<1>>) {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, int64_t>>(n);
break;
} else {
if (n.children[1]->is_type<language::integer>()) {
if (std::stoi(n.children[1]->string()) == 0) {
n.m_node_processor = std::make_unique<AffectationFromZeroProcessor<ValueT>>(n);
break;
}
}
}
throw parse_error("invalid operand value", std::vector{n.children[1]->begin()});
}
case ASTNodeDataType::double_t: {
if constexpr (std::is_same_v<ValueT, TinyVector<1>>) {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, double>>(n);
break;
}
}
// LCOV_EXCL_START
default: {
throw parse_error("unexpected error: undefined operand type for vector affectation",
std::vector{n.children[1]->begin()});
throw parse_error("invalid operand type", std::vector{n.children[1]->begin()});
}
// LCOV_EXCL_STOP
}
} else if constexpr (std::is_same_v<OperatorT, language::pluseq_op> or
std::is_same_v<OperatorT, language::minuseq_op>) {
switch (data_type) {
case ASTNodeDataType::vector_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, ValueT>>(n);
break;
}
// LCOV_EXCL_START
default: {
throw parse_error("invalid operand type", std::vector{n.children[1]->begin()});
}
// LCOV_EXCL_STOP
}
} else if constexpr (std::is_same_v<OperatorT, language::multiplyeq_op>) {
switch (data_type) {
case ASTNodeDataType::bool_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, bool>>(n);
break;
}
case ASTNodeDataType::unsigned_int_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, uint64_t>>(n);
break;
}
case ASTNodeDataType::int_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, int64_t>>(n);
break;
}
case ASTNodeDataType::double_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, double>>(n);
break;
}
default: {
throw parse_error("invalid operand", std::vector{n.children[1]->begin()});
}
}
} else {
throw parse_error("unexpected error: undefined operator type", std::vector{n.children[0]->begin()});
throw parse_error("invalid operator type", std::vector{n.begin()});
}
};
......@@ -120,9 +190,25 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode
break;
}
case ASTNodeDataType::vector_t: {
switch (value_type.dimension()) {
case 1: {
set_affectation_processor_for_vector_data(TinyVector<1>{}, data_type);
break;
}
case 2: {
set_affectation_processor_for_vector_data(TinyVector<2>{}, data_type);
break;
}
case 3: {
set_affectation_processor_for_vector_data(TinyVector<3>{}, data_type);
break;
}
default: {
throw parse_error("unexpected error: unexpected vector dimension", std::vector{n.begin()});
}
}
break;
}
case ASTNodeDataType::string_t: {
set_affectation_processor_for_string_data(data_type);
break;
......@@ -144,16 +230,16 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode
for (const auto& child : data_node.children) {
ASTNodeNaturalConversionChecker{n, child->m_data_type, ASTNodeDataType::double_t};
}
break;
}
case ASTNodeDataType::vector_t: {
if (data_node.children.size() != n.m_data_type.dimension()) {
if (data_node.m_data_type.dimension() != n.m_data_type.dimension()) {
throw parse_error("incompatible dimensions in affectation", std::vector{n.begin()});
}
break;
}
default: {
throw parse_error("invalid operand for affectation", std::vector{n.children[1]->begin()});
}
}
} else {
......
......@@ -21,7 +21,7 @@ dataTypeName(const ASTNodeDataType& data_type)
name = "R";
break;
case ASTNodeDataType::vector_t:
name = "vector";
name = "vector[" + std::to_string(data_type.dimension()) + "]";
break;
case ASTNodeDataType::string_t:
name = "string";
......
......@@ -146,6 +146,77 @@ class AffectationProcessor final : public INodeProcessor
}
};
template <typename OperatorT, typename ValueT>
class AffectationFromListProcessor final : public INodeProcessor
{
private:
ASTNode& m_node;
DataVariant* m_lhs;
public:
DataVariant
execute(ExecutionPolicy& exec_policy)
{
AggregateDataVariant children_values = std::get<AggregateDataVariant>(m_node.children[1]->execute(exec_policy));
static_assert(std::is_same_v<OperatorT, language::eq_op>, "forbidden affection operator for list to vectors");
ValueT v;
for (size_t i = 0; i < v.dimension(); ++i) {
std::visit(
[&](auto&& child_value) {
using T = std::decay_t<decltype(child_value)>;
if constexpr (std::is_same_v<T, bool> or std::is_same_v<T, uint64_t> or std::is_same_v<T, int64_t> or
std::is_same_v<T, double>) {
v[i] = child_value;
} else {
throw parse_error("unexpected error: unexpected right hand side type in affectation", m_node.begin());
}
},
children_values[i]);
}
*m_lhs = v;
return {};
}
AffectationFromListProcessor(ASTNode& node) : m_node{node}
{
const std::string& symbol = m_node.children[0]->string();
auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin());
Assert(found);
m_lhs = &i_symbol->attributes().value();
}
};
template <typename ValueT>
class AffectationFromZeroProcessor final : public INodeProcessor
{
private:
ASTNode& m_node;
DataVariant* m_lhs;
public:
DataVariant
execute(ExecutionPolicy&)
{
*m_lhs = ValueT{zero};
return {};
}
AffectationFromZeroProcessor(ASTNode& node) : m_node{node}
{
const std::string& symbol = m_node.children[0]->string();
auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin());
Assert(found);
m_lhs = &i_symbol->attributes().value();
}
};
template <typename OperatorT>
class ListAffectationProcessor final : public INodeProcessor
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment