}
}
+template<typename T>
+std::ostream &Emit(std::ostream &o, const CopyableIndirection<Expr<T>> &expr) {
+ return expr->Dump(o);
+}
+template<typename T>
+std::ostream &Emit(std::ostream &, const ArrayConstructorValues<T> &);
+
+template<typename ITEM, typename INT>
+std::ostream &Emit(std::ostream &o, const ImpliedDo<ITEM, INT> &implDo) {
+ o << '(';
+ Emit(o, *implDo.values);
+ o << ',' << INT::Dump() << "::";
+ o << implDo.controlVariableName.ToString();
+ o << '=';
+ implDo.lower->Dump(o) << ',';
+ implDo.upper->Dump(o) << ',';
+ implDo.stride->Dump(o) << ')';
+ return o;
+}
+
+template<typename T>
+std::ostream &Emit(std::ostream &o, const ArrayConstructorValues<T> &values) {
+ const char *sep{""};
+ for (const auto &value : values.values) {
+ o << sep;
+ std::visit([&](const auto &x) { Emit(o, x); }, value.u);
+ sep = ",";
+ }
+ return o;
+}
+
+template<typename T>
+std::ostream &ArrayConstructor<T>::Dump(std::ostream &o) const {
+ o << '[' << Result::Dump() << "::";
+ Emit(o, *this);
+ return o << ']';
+}
+
template<typename RESULT>
std::ostream &ExpressionBase<RESULT>::Dump(std::ostream &o) const {
std::visit(common::visitors{[&](const BOZLiteralConstant &x) {
LogicalOperator logicalOperator;
};
+// Array constructors
+
+template<typename RESULT> struct ArrayConstructorValues;
+
+template<typename ITEM, typename OPERAND> struct ImpliedDo {
+ using Item = ITEM;
+ using Result = typename Item::Result;
+ using Operand = OPERAND;
+ static_assert(Operand::category == TypeCategory::Integer);
+ parser::CharBlock controlVariableName;
+ CopyableIndirection<Expr<Operand>> lower, upper, stride;
+ CopyableIndirection<Item> values;
+};
+
+template<typename RESULT> struct ArrayConstructorValue {
+ using Result = RESULT;
+ EVALUATE_UNION_CLASS_BOILERPLATE(ArrayConstructorValue)
+ template<typename INT>
+ using ImpliedDo = ImpliedDo<ArrayConstructorValues<Result>, INT>;
+ common::CombineVariants<std::variant<CopyableIndirection<Expr<Result>>>,
+ common::MapTemplate<ImpliedDo, IntegerTypes>>
+ u;
+};
+
+template<typename RESULT> struct ArrayConstructorValues {
+ using Result = RESULT;
+ CLASS_BOILERPLATE(ArrayConstructorValues)
+ template<typename A> void Push(A &&x) { values.emplace_back(std::move(x)); }
+ std::vector<ArrayConstructorValue<Result>> values;
+};
+
+template<typename RESULT>
+struct ArrayConstructor : public ArrayConstructorValues<RESULT> {
+ using Result = RESULT;
+ using ArrayConstructorValues<Result>::ArrayConstructorValues;
+ static constexpr int Rank() { return 1; }
+ std::ostream &Dump(std::ostream &) const;
+};
+
// Per-category expression representations
template<int KIND>
using Operations = std::variant<Parentheses<Result>, Negate<Result>,
Add<Result>, Subtract<Result>, Multiply<Result>, Divide<Result>,
Power<Result>, Extremum<Result>>;
- using Others =
- std::variant<Constant<Result>, Designator<Result>, FunctionRef<Result>>;
+ using Others = std::variant<Constant<Result>, ArrayConstructor<Result>,
+ Designator<Result>, FunctionRef<Result>>;
public:
common::CombineVariants<Operations, Conversions, Others> u;
public:
using Result = SomeDerived;
EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
+ // TODO: array constructor, structure constructor
std::variant<Designator<Result>, FunctionRef<Result>> u;
};
return category == that.category && kind == that.kind &&
derived == that.derived;
}
- std::string Dump() const {
- return EnumToString(category) + '(' + std::to_string(kind) + ')';
- }
-
+ std::string Dump() const;
DynamicType ResultTypeForMultiply(const DynamicType &) const;
TypeCategory category;
int kind{0};
const semantics::DerivedTypeSpec *derived{nullptr};
+ // TODO pmk: descriptor for character length
+ // TODO pmk: derived type kind parameters and descriptor for lengths
};
std::optional<DynamicType> GetSymbolType(const semantics::Symbol &);