lib/parser/source.cc
)
add_executable(f18 ${SOURCES})
-add_executable(type-test type.cc idioms.cc attr.cc)
+add_executable(type-test type.cc attr.cc lib/parser/idioms.cc)
if (allowed.find(attr) == allowed.end()) {
std::stringstream temp;
temp << attr;
- die("invalid attribute '%s' for class %s", temp.str().c_str(),
+ parser::die("invalid attribute '%s' for class %s", temp.str().c_str(),
className.c_str());
}
}
#ifndef FORTRAN_ATTR_H_
#define FORTRAN_ATTR_H_
-#include "idioms.h"
+#include "lib/parser/idioms.h"
#include <iostream>
#include <set>
#include <string>
} // namespace Fortran
// For switch statements without default: labels.
-#define CRASH_NO_CASE die("no case at " __FILE__ "(%d)", __LINE__)
+#define CRASH_NO_CASE \
+ Fortran::parser::die("no case at " __FILE__ "(%d)", __LINE__)
// For cheap assertions that should be applied in production.
#define CHECK(x) \
- ((x) || (die("CHECK(" #x ") failed at " __FILE__ "(%d)", __LINE__), false))
+ ((x) || \
+ (Fortran::parser::die( \
+ "CHECK(" #x ") failed at " __FILE__ "(%d)", __LINE__), \
+ false))
// To make error messages more informative, wrap some type information
// around a false compile-time value, e.g.
Name name = def.name();
validNames.insert(name);
if (!def.defaultValue() && values.find(name) == values.end()) {
- die("no value or default value for %s parameter '%s'", kindOrLen.c_str(),
+ parser::die("no value or default value for %s parameter '%s'", kindOrLen.c_str(),
name.c_str());
}
}
for (auto pair : values) {
Name name = pair.first;
if (validNames.find(name) == validNames.end()) {
- die("invalid %s parameter '%s'", kindOrLen.c_str(), name.c_str());
+ parser::die("invalid %s parameter '%s'", kindOrLen.c_str(), name.c_str());
}
}
}
-const IntConst IntConst::ZERO = IntConst{0};
-const IntConst IntConst::ONE = IntConst{1};
-
-const IntExpr *IntConst::clone() const {
- if (*this == ZERO) {
- return &ZERO;
- } else if (*this == ONE) {
- return &ONE;
- } else {
- return new IntConst{*this};
- }
-}
+std::unordered_map<int, IntConst> IntConst::cache;
std::ostream &operator<<(std::ostream &o, const KindParamValue &x) {
return o << x.value_;
}
+const IntConst &IntConst::make(int value) {
+ auto it = cache.find(value);
+ if (it == cache.end()) {
+ it = cache.insert({value, IntConst{value}}).first;
+ }
+ return it->second;
+}
+
const LenParamValue LenParamValue::ASSUMED =
LenParamValue(LenParamValue::Assumed);
const LenParamValue LenParamValue::DEFERRED =
std::cout << r2 << "\n";
CharacterTypeSpec c1{LenParamValue::DEFERRED, 1};
std::cout << c1 << "\n";
- CharacterTypeSpec c2{IntConst{10}};
+ CharacterTypeSpec c2{IntConst::make(10)};
std::cout << c2 << "\n";
IntegerTypeSpec i1 = IntegerTypeSpec::make();
}
void testShapeSpec() {
- IntConst ten{10};
+ const IntConst &ten{IntConst::make(10)};
const ShapeSpec s1{ShapeSpec::makeExplicit(ten)};
std::cout << "explicit-shape-spec: " << s1 << "\n";
- ShapeSpec s2{ShapeSpec::makeExplicit(IntConst{2}, IntConst{8})};
+ ShapeSpec s2{ShapeSpec::makeExplicit(IntConst::make(2), IntConst::make(8))};
std::cout << "explicit-shape-spec: " << s2 << "\n";
ShapeSpec s3{ShapeSpec::makeAssumed()};
std::cout << "assumed-shape-spec: " << s3 << "\n";
- ShapeSpec s4{ShapeSpec::makeAssumed(IntConst{2})};
+ ShapeSpec s4{ShapeSpec::makeAssumed(IntConst::make(2))};
std::cout << "assumed-shape-spec: " << s4 << "\n";
ShapeSpec s5{ShapeSpec::makeDeferred()};
std::cout << "deferred-shape-spec: " << s5 << "\n";
- ShapeSpec s6{ShapeSpec::makeImplied(IntConst{2})};
+ ShapeSpec s6{ShapeSpec::makeImplied(IntConst::make(2))};
std::cout << "implied-shape-spec: " << s6 << "\n";
ShapeSpec s7{ShapeSpec::makeAssumedRank()};
#define FORTRAN_TYPE_H_
#include "attr.h"
-#include "idioms.h"
+#include "lib/parser/idioms.h"
#include <algorithm>
#include <list>
#include <map>
#include <ostream>
#include <sstream>
#include <string>
+#include <unordered_map>
#include <vector>
/*
// TODO
class IntConst : public IntExpr {
public:
- static const IntConst ZERO;
- static const IntConst ONE;
- IntConst(int value) : value_{value} {}
- virtual const IntExpr *clone() const;
+ static const IntConst &make(int value);
+ virtual const IntExpr *clone() const { return &make(value_); }
bool operator==(const IntConst &x) const { return value_ == x.value_; }
bool operator!=(const IntConst &x) const { return !operator==(x); }
bool operator<(const IntConst &x) const { return value_ < x.value_; }
virtual std::ostream &output(std::ostream &o) const {
return o << this->value_;
}
-
private:
+ static std::unordered_map<int, IntConst> cache;
+ IntConst(int value) : value_{value} {}
const int value_;
};
// The value of a kind type parameter
class KindParamValue {
public:
- KindParamValue(int value) : value_{value} {}
+ KindParamValue(int value) : value_{IntConst::make(value)} {}
bool operator==(const KindParamValue &x) const { return value_ == x.value_; }
bool operator!=(const KindParamValue &x) const { return !operator==(x); }
bool operator<(const KindParamValue &x) const { return value_ < x.value_; }
private:
- const IntConst value_;
+ const IntConst &value_;
friend std::ostream &operator<<(std::ostream &, const KindParamValue &);
};
// Instantiation of a DerivedTypeDef with kind and len parameter values
class DerivedTypeSpec : public TypeSpec {
public:
- DerivedTypeSpec(DerivedTypeDef def, KindParamValues kindParamValues{},
- LenParamValues lenParamValues{});
+ DerivedTypeSpec(DerivedTypeDef def, KindParamValues kindParamValues = {},
+ LenParamValues lenParamValues = {});
private:
const DerivedTypeDef def_;
private:
enum Category { Explicit, Deferred, Assumed };
- Bound(Category category) : category_{category}, expr_{&IntConst::ZERO} {}
+ Bound(Category category) : category_{category}, expr_{&IntConst::make(0)} {}
const Category category_;
const IntExpr *const expr_;
friend std::ostream &operator<<(std::ostream &, const Bound &);
}
// 1:ub
static const ShapeSpec makeExplicit(const Bound &ub) {
- return makeExplicit(IntConst::ONE, ub);
+ return makeExplicit(IntConst::make(1), ub);
}
// 1: or lb:
- static ShapeSpec makeAssumed(const Bound &lb = IntConst::ONE) {
+ static ShapeSpec makeAssumed(const Bound &lb = IntConst::make(1)) {
return ShapeSpec(lb, Bound::DEFERRED);
}
// :