git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
C++: string optimizations
commit3711c76d296ee9f792e8ac7722d2ecf903baaacd authorAndy Arvanitis <andyarvanitis@gmail.com> dateSun 17 Jan 2016, 22:58 (11 years ago) parent53ecca2
3 files changed+152−96
pcc/include/purescript.cc+111−67 pcc/include/purescript.hh+34−29 src/Language/PureScript/Pretty/Cpp.hs+7
pcc/include/purescript.cc+111−67
@@ -19,18 +19,19 @@ namespace PureScript {
1919#define COPY_DATA(src) \
2020 type = src.type; \
2121 switch (type) { \
22− case Type::Integer: i = src.i; break; \
23− case Type::Double: d = src.d; break; \
24− case Type::Character: c = src.c; break; \
25− case Type::Boolean: b = src.b; break; \
26− case Type::String: new (&s) shared<string> (src.s); break; \
27− case Type::Map: new (&m) shared<map> (src.m); break; \
28− case Type::Vector: new (&v) shared<vector> (src.v); break; \
29− case Type::Function: f = src.f; break; \
30− case Type::Closure: new (&l) shared<closure> (src.l); break; \
31− case Type::EffFunction: new (&e) shared<eff_fn> (src.e); break; \
32− case Type::Thunk: t = src.t; break; \
33− case Type::Pointer: new (&p) shared<void> (src.p); break; \
22+ case Type::Integer: i = src.i; break; \
23+ case Type::Double: d = src.d; break; \
24+ case Type::Character: c = src.c; break; \
25+ case Type::Boolean: b = src.b; break; \
26+ case Type::StringLiteral: r = src.r; break; \
27+ case Type::String: new (&s) shared<std::string>(src.s); break; \
28+ case Type::Map: new (&m) shared<map>(src.m); break; \
29+ case Type::Vector: new (&v) shared<vector>(src.v); break; \
30+ case Type::Function: f = src.f; break; \
31+ case Type::Closure: new (&l) shared<closure>(src.l); break; \
32+ case Type::EffFunction: new (&e) shared<eff_fn>(src.e); break; \
33+ case Type::Thunk: t = src.t; break; \
34+ case Type::Pointer: new (&p) shared<void>(src.p); break; \
3435 \
3536 default: assert(false && "Unsupported type in copy"); \
3637 }
@@ -38,18 +39,19 @@ namespace PureScript {
3839#define MOVE_DATA(src) \
3940 type = src.type; \
4041 switch (type) { \
41− case Type::Integer: i = src.i; break; \
42− case Type::Double: d = src.d; break; \
43− case Type::Character: c = src.c; break; \
44− case Type::Boolean: b = src.b; break; \
45− case Type::String: new (&s) shared<string> (std::move(src.s)); break; \
46− case Type::Map: new (&m) shared<map> (std::move(src.m)); break; \
47− case Type::Vector: new (&v) shared<vector> (std::move(src.v)); break; \
48− case Type::Function: f = src.f; break; \
49− case Type::Closure: new (&l) shared<closure> (std::move(src.l)); break; \
50− case Type::EffFunction: new (&e) shared<eff_fn> (std::move(src.e)); break; \
51− case Type::Thunk: t = src.t; break; \
52− case Type::Pointer: new (&p) shared<void> (std::move(src.p)); break; \
42+ case Type::Integer: i = src.i; break; \
43+ case Type::Double: d = src.d; break; \
44+ case Type::Character: c = src.c; break; \
45+ case Type::Boolean: b = src.b; break; \
46+ case Type::StringLiteral: r = src.r; break; \
47+ case Type::String: new (&s) shared<std::string>(std::move(src.s)); break; \
48+ case Type::Map: new (&m) shared<map>(std::move(src.m)); break; \
49+ case Type::Vector: new (&v) shared<vector>(std::move(src.v)); break; \
50+ case Type::Function: f = src.f; break; \
51+ case Type::Closure: new (&l) shared<closure>(std::move(src.l)); break; \
52+ case Type::EffFunction: new (&e) shared<eff_fn>(std::move(src.e)); break; \
53+ case Type::Thunk: t = src.t; break; \
54+ case Type::Pointer: new (&p) shared<void>(std::move(src.p)); break; \
5355 \
5456 default: assert(false && "Unsupported type in move"); \
5557 }
@@ -81,18 +83,19 @@ auto any::operator=(any&& rhs) noexcept -> any& {
8183any::~any() {
8284 // std::cout << "destroy" << std::endl;
8385 switch (type) {
84− case Type::Integer: ; break;
85− case Type::Double: ; break;
86− case Type::Character: ; break;
87− case Type::Boolean: ; break;
88− case Type::String: s.~shared<string>(); break;
89− case Type::Map: m.~shared<map>(); break;
90− case Type::Vector: v.~shared<vector>(); break;
91− case Type::Function: ; break;
92− case Type::Closure: l.~shared<closure>(); break;
93− case Type::EffFunction: e.~shared<eff_fn>(); break;
94− case Type::Thunk: ; break;
95− case Type::Pointer: p.~shared<void>(); break;
86+ case Type::Integer: ; break;
87+ case Type::Double: ; break;
88+ case Type::Character: ; break;
89+ case Type::Boolean: ; break;
90+ case Type::StringLiteral: ; break;
91+ case Type::String: s.~shared<std::string>(); break;
92+ case Type::Map: m.~shared<map>(); break;
93+ case Type::Vector: v.~shared<vector>(); break;
94+ case Type::Function: ; break;
95+ case Type::Closure: l.~shared<closure>(); break;
96+ case Type::EffFunction: e.~shared<eff_fn>(); break;
97+ case Type::Thunk: ; break;
98+ case Type::Pointer: p.~shared<void>(); break;
9699
97100 default: assert(false && "Unsupported type in destructor");
98101 }
@@ -139,16 +142,15 @@ auto any::cast() const -> typename std::enable_if<std::is_same<T, bool>::value,
139142template auto any::cast<bool>() const -> bool;
140143
141144template <typename T>
142−auto any::cast() const -> typename std::enable_if<std::is_same<T, string>::value, const T&>::type {
143− RETURN_VALUE(Type::String, s, *)
144−}
145−template auto any::cast<string>() const -> const string&;
146−
147−template <typename T>
148−auto any::cast() const -> typename std::enable_if<std::is_same<T, const char*>::value, const T>::type {
149− RETURN_VALUE(Type::String, s->c_str(),)
145+auto any::cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type {
146+ const any& val = extractValue(*this);
147+ if (val.type == Type::StringLiteral) {
148+ return val.r;
149+ }
150+ assert(val.type == Type::String);
151+ return val.s->c_str();
150152}
151−template auto any::cast<const char*>() const -> const char* const;
153+template auto any::cast<string>() const -> string;
152154
153155template <typename T>
154156auto any::cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type {
@@ -219,8 +221,12 @@ any::operator bool() const {
219221 RETURN_VALUE(Type::Boolean, b,)
220222}
221223
222−any::operator const string&() const {
223− RETURN_VALUE(Type::String, s, *)
224+any::operator string() const {
225+ return cast<string>();
226+}
227+
228+any::operator std::string() const {
229+ return cast<string>();
224230}
225231
226232any::operator const map&() const {
@@ -275,25 +281,49 @@ auto operator op (ty lhs, const any& rhs) -> rty { \
275281 return lhs op rhs.cast<typename std::remove_const<std::remove_reference<ty>::type>::type>(); \
276282}
277283
284+#define DEFINE_CSTR_EQUALS_OPERATOR() \
285+ auto operator==(const any& lhs_, const char * rhs) -> bool { \
286+ const any& lhs = any::extractValue(lhs_); \
287+ assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
288+ if (lhs.type == any::Type::StringLiteral) { \
289+ return (lhs.r == rhs) || (strcmp(lhs.r, rhs) == 0); \
290+ } \
291+ return strcmp(lhs.s->c_str(), rhs) == 0; \
292+ } \
293+ auto operator==(const char * lhs, const any& rhs_) -> bool { \
294+ const any& rhs = any::extractValue(rhs_); \
295+ assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
296+ if (rhs.type == any::Type::StringLiteral) { \
297+ return (lhs == rhs.r) || (strcmp(lhs, rhs) == 0); \
298+ } \
299+ return strcmp(lhs, rhs.s->c_str()) == 0; \
300+ }
301+
278302#define DEFINE_CSTR_COMPARISON_OPERATOR(op) \
279303 auto operator op (const any& lhs, const char * rhs) -> bool { \
280− return lhs.cast<string>() op rhs; \
304+ return strcmp(lhs.cast<string>(), rhs) op 0; \
281305 } \
282306 auto operator op (const char * lhs, const any& rhs) -> bool { \
283− return lhs op rhs.cast<string>(); \
307+ return strcmp(lhs, rhs.cast<string>()) op 0; \
284308 }
285309
286310#define DEFINE_COMPARISON_OPERATOR(op) \
287311 auto operator op (const any& lhs_, const any& rhs_) -> bool { \
288312 const any& lhs = any::extractValue(lhs_); \
289313 const any& rhs = any::extractValue(rhs_); \
290− assert(lhs.type == rhs.type); \
291314 switch (lhs.type) { \
292− case any::Type::Integer: return lhs.i op rhs.i; \
293− case any::Type::Double: return lhs.d op rhs.d; \
294− case any::Type::Character: return lhs.c op rhs.c; \
295− case any::Type::Boolean: return lhs.b op rhs.b; \
296− case any::Type::String: return (*lhs.s) op (*rhs.s); \
315+ case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i op rhs.i; \
316+ case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d op rhs.d; \
317+ case any::Type::Character: assert(lhs.type == any::Type::Character); return lhs.c op rhs.c; \
318+ case any::Type::Boolean: assert(lhs.type == any::Type::Boolean); return lhs.b op rhs.b; \
319+ case any::Type::StringLiteral: \
320+ assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
321+ assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
322+ return strcmp(lhs.r, rhs.type == any::Type::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
323+ case any::Type::String: \
324+ assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String); \
325+ assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String); \
326+ return strcmp(lhs.s->c_str(), rhs.type == any::Type::StringLiteral ? rhs.r : rhs.s->c_str()) op 0; \
297327 case any::Type::Pointer: return lhs.p op rhs.p; \
298328 default: assert(false && "Unsupported type for operator " #op); \
299329 } \
@@ -303,8 +333,6 @@ auto operator op (ty lhs, const any& rhs) -> rty { \
303333 DEFINE_OPERATOR(op, double, bool) \
304334 DEFINE_OPERATOR(op, char, bool) \
305335 DEFINE_OPERATOR(op, bool, bool) \
306− DEFINE_OPERATOR(op, const string&, bool) \
307− DEFINE_CSTR_COMPARISON_OPERATOR(op)
308336
309337//-----------------------------------------------------------------------------
310338// Operator definitions
@@ -317,15 +345,28 @@ DEFINE_COMPARISON_OPERATOR(<=)
317345DEFINE_COMPARISON_OPERATOR(>)
318346DEFINE_COMPARISON_OPERATOR(>=)
319347
348+DEFINE_CSTR_EQUALS_OPERATOR()
349+DEFINE_CSTR_COMPARISON_OPERATOR(!=)
350+DEFINE_CSTR_COMPARISON_OPERATOR(<)
351+DEFINE_CSTR_COMPARISON_OPERATOR(<=)
352+DEFINE_CSTR_COMPARISON_OPERATOR(>)
353+DEFINE_CSTR_COMPARISON_OPERATOR(>=)
354+
320355auto operator+(const any& lhs_, const any& rhs_) -> any {
321356 const any& lhs = any::extractValue(lhs_);
322357 const any& rhs = any::extractValue(rhs_);
323− assert(lhs.type == rhs.type);
324358 switch (lhs.type) {
325− case any::Type::Integer: return lhs.i + rhs.i;
326− case any::Type::Double: return lhs.d + rhs.d;
327− case any::Type::Character: return any(char(lhs.c + rhs.c));
328− case any::Type::String: return (*lhs.s) + (*rhs.s);
359+ case any::Type::Integer: assert(lhs.type == any::Type::Integer); return lhs.i + rhs.i;
360+ case any::Type::Double: assert(lhs.type == any::Type::Double); return lhs.d + rhs.d;
361+ case any::Type::Character: assert(lhs.type == any::Type::Character); return any(char(lhs.c + rhs.c));
362+ case any::Type::StringLiteral:
363+ assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
364+ assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
365+ return rhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs.r : lhs.r + *rhs.s;
366+ case any::Type::String:
367+ assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
368+ assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
369+ return rhs.type == any::Type::StringLiteral ? *lhs.s + rhs.r : *lhs.s + *rhs.s;
329370 default: assert(false && "Unsupported type for '+' operator");
330371 }
331372 return nullptr;
@@ -334,14 +375,17 @@ auto operator+(const any& lhs_, const any& rhs_) -> any {
334375DEFINE_OPERATOR(+, long, long)
335376DEFINE_OPERATOR(+, double, double)
336377DEFINE_OPERATOR(+, char, char)
337−DEFINE_OPERATOR(+, const string&, string)
338378
339−auto operator+(const any& lhs, const char * rhs) -> string {
340− return lhs.cast<string>() + rhs;
379+auto operator+(const any& lhs_, const char * rhs) -> std::string {
380+ const any& lhs = any::extractValue(lhs_);
381+ assert(lhs.type == any::Type::StringLiteral || lhs.type == any::Type::String);
382+ return lhs.type == any::Type::StringLiteral ? std::string(lhs.r) + rhs : *lhs.s + rhs;
341383}
342384
343−auto operator+(const char * lhs, const any& rhs) -> string {
344− return lhs + rhs.cast<string>();
385+auto operator+(const char * lhs, const any& rhs_) -> std::string {
386+ const any& rhs = any::extractValue(rhs_);
387+ assert(rhs.type == any::Type::StringLiteral || rhs.type == any::Type::String);
388+ return rhs.type == any::Type::StringLiteral ? lhs + std::string(rhs.r) : lhs + *rhs.s;
345389}
346390
347391auto operator-(const any& lhs_, const any& rhs_) -> any {
pcc/include/purescript.hh+34−29
@@ -42,12 +42,12 @@
4242 DECLARE_OPERATOR(op, long, bool) \
4343 DECLARE_OPERATOR(op, double, bool) \
4444 DECLARE_OPERATOR(op, char, bool) \
45− DECLARE_OPERATOR(op, const string&, bool) \
4645 DECLARE_OPERATOR(op, const char *, bool)
4746
47+
4848namespace PureScript {
4949
50−using string = std::string;
50+using string = const char *;
5151using runtime_error = std::runtime_error;
5252using nullptr_t = std::nullptr_t;
5353
@@ -58,12 +58,13 @@ const bool undefined = false;
5858class any {
5959
6060 public:
61− enum class Type {
61+ enum class Type : int8_t {
6262 Unknown,
6363 Integer,
6464 Double,
6565 Character,
6666 Boolean,
67+ StringLiteral,
6768 String,
6869 Map,
6970 Vector,
@@ -80,12 +81,12 @@ class any {
8081 };
8182 static constexpr as_thunk unthunk = as_thunk{};
8283
83− using map = std::unordered_map<const map_key_t, const any, map_key_t::hasher, map_key_t::equal>;
84− using vector = std::vector<any>;
84+ using map = std::unordered_map<const map_key_t, const any, map_key_t::hasher, map_key_t::equal>;
85+ using vector = std::vector<any>;
8586 using fn = auto (*)(const any&) -> any;
8687 using closure = std::function<any(const any&)>;
87− using eff_fn = std::function<any()>;
88− using thunk = auto (*)(const as_thunk) -> const any&;
88+ using eff_fn = std::function<any()>;
89+ using thunk = auto (*)(const as_thunk) -> const any&;
8990
9091 template <typename T>
9192 using shared = std::shared_ptr<T>;
@@ -97,18 +98,19 @@ class any {
9798
9899 private:
99100 union {
100− mutable long i;
101− mutable double d;
102− mutable char c;
103− mutable bool b;
104− mutable shared<string> s;
105− mutable shared<map> m;
106− mutable shared<vector> v;
107− mutable fn f;
108− mutable shared<closure> l;
109− mutable shared<eff_fn> e;
110− mutable thunk t;
111− mutable shared<void> p;
101+ mutable long i;
102+ mutable double d;
103+ mutable char c;
104+ mutable bool b;
105+ mutable string r;
106+ mutable shared<std::string> s;
107+ mutable shared<map> m;
108+ mutable shared<vector> v;
109+ mutable fn f;
110+ mutable shared<closure> l;
111+ mutable shared<eff_fn> e;
112+ mutable thunk t;
113+ mutable shared<void> p;
112114 };
113115
114116 public:
@@ -122,9 +124,15 @@ class any {
122124 template <typename T, typename = typename std::enable_if<std::is_same<bool,T>::value>::type>
123125 any(const T val) : type(Type::Boolean), b(val) {}
124126
125− any(const string& val) : type(Type::String), s(make_shared<string>(val)) {}
126− any(string&& val) noexcept : type(Type::String), s(make_shared<string>(std::move(val))) {}
127− any(const char val[]) : type(Type::String), s(make_shared<string>(val)) {}
127+ template <size_t N>
128+ any(const char (&val)[N]) : type(Type::StringLiteral), r(val) {}
129+ any(char * val) : type(Type::String), s(make_shared<std::string>(val)) {}
130+
131+ any(const std::string& val) : type(Type::String), s(make_shared<std::string>(val)) {}
132+ any(std::string&& val) : type(Type::String), s(make_shared<std::string>(std::move(val))) {}
133+
134+ any(const shared<std::string>& val) : type(Type::String), s(val) {}
135+ any(shared<std::string>&& val) noexcept : type(Type::String), s(std::move(val)) {}
128136
129137 any(const map& val) : type(Type::Map), m(make_shared<map>(val)) {}
130138 any(map&& val) noexcept : type(Type::Map), m(make_shared<map>(std::move(val))) {}
@@ -182,10 +190,7 @@ class any {
182190 auto cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type;
183191
184192 template <typename T>
185− auto cast() const -> typename std::enable_if<std::is_same<T, string>::value, const T&>::type;
186−
187− template <typename T>
188− auto cast() const -> typename std::enable_if<std::is_same<T, const char*>::value, const T>::type;
193+ auto cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type;
189194
190195 template <typename T>
191196 auto cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type;
@@ -208,7 +213,8 @@ class any {
208213 operator double() const;
209214 operator bool() const;
210215
211− operator const string&() const;
216+ operator string() const;
217+ operator std::string() const;
212218 operator const map&() const;
213219 operator const vector&() const;
214220
@@ -232,8 +238,7 @@ class any {
232238 DECLARE_OPERATOR(+, long, long)
233239 DECLARE_OPERATOR(+, double, double)
234240 DECLARE_OPERATOR(+, char, char)
235− DECLARE_OPERATOR(+, const string&, string)
236− DECLARE_OPERATOR(+, const char *, string)
241+ DECLARE_OPERATOR(+, const char *, std::string)
237242
238243 friend auto operator-(const any&, const any&) -> any;
239244
src/Language/PureScript/Pretty/Cpp.hs+7
@@ -214,6 +214,13 @@ literals = mkPattern' match
214214 , return $ if null cpps then "" else "\n"
215215 , prettyStatements cpps
216216 ]
217+ match (CppReturn value@(CppStringLiteral _)) = fmap concat $ sequence
218+ [ return "return "
219+ , return . runType $ CppAny []
220+ , return "("
221+ , prettyPrintCpp' value
222+ , return ")"
223+ ]
217224 match (CppReturn value) = fmap concat $ sequence
218225 [ return "return "
219226 , prettyPrintCpp' value