@@ -653,6 +653,28 @@ namespace FlatModelica
653653 std::vector<Expression> _elements;
654654 };
655655
656+ class Range : public ExpressionBase
657+ {
658+ public:
659+ Range (Expression start, Expression step, Expression stop)
660+ : _start(std::move(start)), _step(std::move(step)), _stop(std::move(stop)) {}
661+
662+ Range (const QJsonObject &value);
663+
664+ std::unique_ptr<ExpressionBase> clone () const override { return std::make_unique<Range>(*this ); }
665+ Expression eval (const Expression::VariableEvaluator &var_eval) const override ;
666+
667+ bool isLiteral () const override ;
668+
669+ void print (std::ostream &os) const override ;
670+ QJsonValue serialize () const override ;
671+
672+ private:
673+ Expression _start;
674+ Expression _step;
675+ Expression _stop;
676+ };
677+
656678 class Call : public ExpressionBase
657679 {
658680 public:
@@ -682,6 +704,46 @@ namespace FlatModelica
682704 bool _is_record;
683705 };
684706
707+ class Iterator
708+ {
709+ public:
710+ Iterator (std::string name, Expression range)
711+ : _name(std::move(name)), _range(std::move(range)) {}
712+
713+ Iterator (const QJsonValue &value);
714+
715+ const std::string& name () const { return _name; }
716+ const Expression& range () const { return _range; }
717+
718+ QJsonValue serialize () const ;
719+
720+ private:
721+ std::string _name;
722+ Expression _range;
723+ };
724+
725+ class IteratorCall : public ExpressionBase
726+ {
727+ public:
728+ IteratorCall (std::string name, Expression exp, std::vector<Iterator> iterators)
729+ : _name(std::move(name)), _exp(std::move(exp)), _iterators(std::move(iterators)) {}
730+
731+ IteratorCall (const QJsonObject &value);
732+
733+ std::unique_ptr<ExpressionBase> clone () const override { return std::make_unique<IteratorCall>(*this ); }
734+ Expression eval (const Expression::VariableEvaluator &var_eval) const override ;
735+
736+ bool isLiteral () const override { return false ; }
737+
738+ void print (std::ostream &os) const override ;
739+ QJsonValue serialize () const override ;
740+
741+ private:
742+ std::string _name;
743+ Expression _exp;
744+ std::vector<Iterator> _iterators;
745+ };
746+
685747 class Binary : public ExpressionBase
686748 {
687749 public:
@@ -1157,22 +1219,17 @@ namespace FlatModelica
11571219 if (kind.isString ()) {
11581220 switch (djb2_qHash (kind.toString ().data ())) {
11591221 case djb2_hash (" enum" ): return std::make_unique<Enum>(value);
1160- // case djb2_hash("clock"): return std::make_unique<Clock >(value);
1222+ case djb2_hash (" clock" ): return std::make_unique<Cref >(value);
11611223 case djb2_hash (" cref" ): return std::make_unique<Cref>(value);
1162- // case djb2_hash("typename"): return std::make_unique<Typename >(value);
1163- // case djb2_hash("range"): return std::make_unique<Range>(value);
1224+ case djb2_hash (" typename" ): return std::make_unique<Cref >(value);
1225+ case djb2_hash (" range" ): return std::make_unique<Range>(value);
11641226 // case djb2_hash("tuple"): return std::make_unique<Tuple>(value);
11651227 case djb2_hash (" record" ): return std::make_unique<Call>(value, true );
11661228 case djb2_hash (" call" ): return std::make_unique<Call>(value, false );
1167- // case djb2_hash("array_constructor"): return std::make_unique<ArrayConstructor>(value);
1168- // case djb2_hash("reduction"): return std::make_unique<Reduction>(value);
1169- // case djb2_hash("size"): return std::make_unique<Size>(value);
1229+ case djb2_hash (" iterator_call" ): return std::make_unique<IteratorCall>(value);
11701230 case djb2_hash (" binary_op" ): return std::make_unique<Binary>(value);
11711231 case djb2_hash (" unary_op" ): return std::make_unique<Unary>(value);
11721232 case djb2_hash (" if" ): return std::make_unique<IfExp>(value);
1173- // case djb2_hash("cast"): return std::make_unique<Cast>(value);
1174- // case djb2_hash("box"): return std::make_unique<Box>(value);
1175- // case djb2_hash("unbox"): return std::make_unique<Unbox>(value);
11761233 // case djb2_hash("sub"): return std::make_unique<Subscripted>(value);
11771234 // case djb2_hash("tuple_element"): return std::make_unique<TupleElement>(value);
11781235 // case djb2_hash("record_element"): return std::make_unique<RecordElement>(value);
@@ -1466,6 +1523,69 @@ namespace FlatModelica
14661523 return Expression (std::move (elems));
14671524 }
14681525
1526+ Range::Range (const QJsonObject &value)
1527+ {
1528+ auto start = value.find (" start" );
1529+
1530+ if (start == value.end ()) {
1531+ throw json_error (" Expression: missing range start in " , value);
1532+ }
1533+
1534+ _start.deserialize (*start);
1535+
1536+ auto stop = value.find (" stop" );
1537+
1538+ if (stop == value.end ()) {
1539+ throw json_error (" Expression: missing range stop in " , value);
1540+ }
1541+
1542+ _stop.deserialize (*stop);
1543+
1544+ auto step = value.find (" step" );
1545+
1546+ if (step != value.end ()) {
1547+ _step.deserialize (*step);
1548+ }
1549+ }
1550+
1551+ Expression Range::eval (const Expression::VariableEvaluator &var_eval) const
1552+ {
1553+ auto start = _start.evaluate (var_eval);
1554+ auto stop = _stop.evaluate (var_eval);
1555+ auto step = _step.isNull () ? Expression () : _step.evaluate (var_eval);
1556+ return Expression (std::make_unique<Range>(std::move (start), std::move (step), std::move (stop)));
1557+ }
1558+
1559+ bool Range::isLiteral () const
1560+ {
1561+ return _start.isLiteral () && _step.isLiteral () && _stop.isLiteral ();
1562+ }
1563+
1564+ void Range::print (std::ostream &os) const
1565+ {
1566+ os << _start << ' :' ;
1567+
1568+ if (!_step.isNull ()) {
1569+ os << _step << ' :' ;
1570+ }
1571+
1572+ os << _stop;
1573+ }
1574+
1575+ QJsonValue Range::serialize () const
1576+ {
1577+ QJsonObject obj;
1578+ obj.insert (" $kind" , " range" );
1579+ obj.insert (" start" , _start.serialize ());
1580+
1581+ if (!_step.isNull ()) {
1582+ obj.insert (" step" , _step.serialize ());
1583+ }
1584+
1585+ obj.insert (" stop" , _stop.serialize ());
1586+ return obj;
1587+ }
1588+
14691589 Call::Call (const QJsonObject &value, bool isRecord)
14701590 : _is_record(isRecord)
14711591 {
@@ -1615,6 +1735,107 @@ namespace FlatModelica
16151735 return Expression (std::make_unique<Call>(name, std::move (args)));
16161736 }
16171737
1738+ Iterator::Iterator (const QJsonValue &value)
1739+ {
1740+ if (!value.isObject ()) {
1741+ throw json_error (" Expression: invalid iterator expression: " , value);
1742+ }
1743+
1744+ auto obj = value.toObject ();
1745+ auto name = obj[" name" ];
1746+
1747+ if (!name.isString ()) {
1748+ throw json_error (" Expression: invalid iterator name: " , name);
1749+ }
1750+
1751+ _name = name.toString ().toStdString ();
1752+
1753+ auto range = obj.find (" range" );
1754+
1755+ if (range == obj.end ()) {
1756+ throw json_error (" Expression: missing iterator range in " , value);
1757+ }
1758+
1759+ _range.deserialize (*range);
1760+ }
1761+
1762+ QJsonValue Iterator::serialize () const
1763+ {
1764+ QJsonObject obj;
1765+ obj.insert (" name" , _name.c_str ());
1766+ obj.insert (" range" , _range.serialize ());
1767+ return obj;
1768+ }
1769+
1770+ std::ostream& operator << (std::ostream &os, const Iterator &i)
1771+ {
1772+ os << i.name () << " in " << i.range ();
1773+ return os;
1774+ }
1775+
1776+ IteratorCall::IteratorCall (const QJsonObject &value)
1777+ {
1778+ auto name = value[" name" ];
1779+
1780+ if (!name.isString ()) {
1781+ throw json_error (" Expression: invalid JSON iterator call name: " , name);
1782+ }
1783+
1784+ _name = name.toString ().toStdString ();
1785+ _exp.deserialize (value[" exp" ]);
1786+
1787+ auto iters = value[" iterators" ];
1788+
1789+ if (!iters.isArray ()) {
1790+ throw json_error (" Expression: invalid JSON iterator call iterators: " , iters);
1791+ }
1792+
1793+ for (const auto &i: iters.toArray ()) {
1794+ _iterators.emplace_back (i);
1795+ }
1796+ }
1797+
1798+ Expression IteratorCall::eval (const Expression::VariableEvaluator &var_eval) const
1799+ {
1800+ return Expression (std::make_unique<IteratorCall>(*this ));
1801+ }
1802+
1803+ void IteratorCall::print (std::ostream &os) const
1804+ {
1805+ bool is_array = _name == " $array" ;
1806+
1807+ if (is_array) {
1808+ os << ' {' ;
1809+ } else {
1810+ os << _name << ' (' ;
1811+ }
1812+
1813+ os << _exp << " for " ;
1814+
1815+ for (auto it = _iterators.begin (); it != _iterators.end (); ++it) {
1816+ if (it != _iterators.begin ()) os << " , " ;
1817+ os << *it;
1818+ }
1819+
1820+ os << (is_array ? ' }' : ' )' );
1821+ }
1822+
1823+ QJsonValue IteratorCall::serialize () const
1824+ {
1825+ QJsonObject obj;
1826+ obj.insert (" $kind" , " iterator_call" );
1827+ obj.insert (" name" , _name.c_str ());
1828+ obj.insert (" exp" , _exp.serialize ());
1829+
1830+ QJsonArray iters;
1831+ for (auto &i: _iterators) {
1832+ iters.push_back (i.serialize ());
1833+ }
1834+ obj.insert (" iterators" , std::move (iters));
1835+
1836+ return obj;
1837+ }
1838+
16181839 Binary::Binary (const QJsonObject &value)
16191840 {
16201841 _e1.deserialize (value[" lhs" ]);
0 commit comments