macroprocessor: introduce tuple type. #5

issue#70
Houtan Bastani 2018-08-07 09:54:23 +02:00
parent c342489397
commit 1285473aa1
3 changed files with 140 additions and 1 deletions

View File

@ -84,7 +84,7 @@ class MacroDriver;
%type <vector<string>> func_args
%type <MacroValuePtr> expr
%type <vector<MacroValuePtr>> comma_expr
%type <vector<MacroValuePtr>> comma_expr tuple_comma_expr
%%
%start statement_list_or_nothing;
@ -136,6 +136,8 @@ expr : INTEGER
{ $$ = make_shared<IntMV>($1); }
| STRING
{ $$ = make_shared<StringMV>(driver.replace_vars_in_str($1)); }
| LPAREN tuple_comma_expr RPAREN
{ $$ = make_shared<TupleMV>($2); }
| NAME
{
try
@ -213,6 +215,16 @@ comma_expr : %empty
{ $1.push_back($3); $$ = $1; }
;
tuple_comma_expr : %empty
{ $$ = vector<MacroValuePtr>{}; } // Empty array
| expr COMMA
{ $$ = vector<MacroValuePtr>{$1}; }
| expr COMMA expr
{ $$ = vector<MacroValuePtr>{$1, $3}; }
| tuple_comma_expr COMMA expr
{ $1.push_back($3); $$ = $1; }
;
%%
void

View File

@ -531,3 +531,110 @@ ArrayMV::range(const MacroValuePtr &mv1, const MacroValuePtr &mv2) noexcept(fals
result.push_back(make_shared<IntMV>(v1));
return make_shared<ArrayMV>(result);
}
TupleMV::TupleMV(vector<MacroValuePtr> values_arg) : values{move(values_arg)}
{
}
shared_ptr<IntMV>
TupleMV::is_equal(const MacroValuePtr &mv)
{
auto mv2 = dynamic_pointer_cast<TupleMV>(mv);
if (!mv2 || values.size() != mv2->values.size())
return make_shared<IntMV>(0);
auto it = values.cbegin();
auto it2 = mv2->values.cbegin();
while (it != values.cend())
{
if ((*it)->is_different(*it2)->value)
return make_shared<IntMV>(0);
++it;
++it2;
}
return make_shared<IntMV>(1);
}
MacroValuePtr
TupleMV::subscript(const MacroValuePtr &mv) noexcept(false)
{
vector<MacroValuePtr> result;
auto copy_element = [&](int i) {
if (i < 1 || i > static_cast<int>(values.size()))
throw OutOfBoundsError();
result.push_back(values[i - 1]);
};
auto mv2 = dynamic_pointer_cast<IntMV>(mv);
auto mv3 = dynamic_pointer_cast<TupleMV>(mv);
if (mv2)
copy_element(mv2->value);
else if (mv3)
for (auto &v : mv3->values)
{
auto v2 = dynamic_pointer_cast<IntMV>(v);
if (!v2)
throw TypeError("Expression inside [] must be an integer or an integer array");
copy_element(v2->value);
}
else
throw TypeError("Expression inside [] must be an integer or an integer array");
if (result.size() > 1 || result.size() == 0)
return make_shared<TupleMV>(result);
else
return result[0];
}
string
TupleMV::toString()
{
ostringstream ss;
bool print_comma = false;
ss << "(";
for (auto &v : values)
{
if (print_comma)
ss << ", ";
else
print_comma = true;
ss << v->toString();
}
ss << ")";
return ss.str();
}
shared_ptr<IntMV>
TupleMV::length() noexcept(false)
{
return make_shared<IntMV>(values.size());
}
string
TupleMV::print()
{
ostringstream ss;
ss << "(";
for (auto it = values.begin();
it != values.end(); it++)
{
if (it != values.begin())
ss << ", ";
ss << (*it)->print();
}
ss << ")";
return ss.str();
}
shared_ptr<IntMV>
TupleMV::in(const MacroValuePtr &mv) noexcept(false)
{
for (auto &v : values)
if (v->is_equal(mv)->value)
return make_shared<IntMV>(1);
return make_shared<IntMV>(0);
}

View File

@ -212,4 +212,24 @@ public:
static shared_ptr<ArrayMV> range(const MacroValuePtr &mv1, const MacroValuePtr &mv2) noexcept(false);
};
//! Represents a tuple value in macro language
class TupleMV : public MacroValue
{
public:
TupleMV(vector<MacroValuePtr> values_arg);
//! Underlying vector
const vector<MacroValuePtr> values;
shared_ptr<IntMV> is_equal(const MacroValuePtr &mv) override;
//! Subscripting operator
/*! Argument must be an ArrayMV<int>. Indexes begin at 1. Returns a StringMV. */
MacroValuePtr subscript(const MacroValuePtr &mv) noexcept(false) override;
//! Returns underlying string value
string toString() override;
string print() override;
shared_ptr<IntMV> length() noexcept(false) override;
shared_ptr<IntMV> in(const MacroValuePtr &mv) noexcept(false) override;
};
#endif