aboutsummaryrefslogtreecommitdiffstats
path: root/src/resp.hpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-12-25 08:35:43 +0000
committerDavid Robillard <d@drobilla.net>2012-12-25 08:35:43 +0000
commit77d27b3495bfa98c5e13707903e4f885e8521ab6 (patch)
treeb2cadb927fd0ab8732001fc77a580f1dffcd0744 /src/resp.hpp
parent12314c754187ae246bc38aceb827bf51d1669d73 (diff)
downloadresp-77d27b3495bfa98c5e13707903e4f885e8521ab6.tar.gz
resp-77d27b3495bfa98c5e13707903e4f885e8521ab6.tar.bz2
resp-77d27b3495bfa98c5e13707903e4f885e8521ab6.zip
Support multiple ellipses in macros.
Support lambda expressions with empty argument lists. git-svn-id: http://svn.drobilla.net/resp/trunk@445 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'src/resp.hpp')
-rw-r--r--src/resp.hpp56
1 files changed, 44 insertions, 12 deletions
diff --git a/src/resp.hpp b/src/resp.hpp
index 9e1e4f7..02d2746 100644
--- a/src/resp.hpp
+++ b/src/resp.hpp
@@ -83,15 +83,16 @@ struct Object;
/// Type tag for an AST node (must be even and > 1 since LSb is used as mark)
enum Tag {
- T_UNKNOWN = 2,
- T_BOOL = 4,
- T_FLOAT = 6,
- T_INT32 = 8,
- T_STRING = 10,
- T_SYMBOL = 12,
- T_LITSYM = 14,
- T_TUPLE = 16,
- T_TVAR = 18
+ T_UNKNOWN = 2,
+ T_BOOL = 4,
+ T_FLOAT = 6,
+ T_INT32 = 8,
+ T_STRING = 10,
+ T_SYMBOL = 12,
+ T_LITSYM = 14,
+ T_TUPLE = 16,
+ T_TVAR = 18,
+ T_ELLIPSIS = 20
};
/// Garbage collector
@@ -197,6 +198,15 @@ private:
ASymbol(const char* s, Cursor c) : AST(T_SYMBOL, c), _sym(s) {}
};
+/// Ellipsis, e.g. "..."
+struct AEllipsis : public AST {
+ AEllipsis(const AST* pred, Cursor c) : AST(T_ELLIPSIS, c), _pred(pred) {}
+ const AST* pred() const { return _pred; }
+private:
+ friend class PEnv;
+ const AST* _pred;
+};
+
/// Tuple (heterogeneous sequence of fixed length), e.g. "(a b c)"
struct ATuple : public AST {
explicit ATuple(Cursor c) : AST(T_TUPLE, c), _fst(0), _rst(0) {}
@@ -331,6 +341,16 @@ list_equals(const ATuple* lhs, const ATuple* rhs)
return true;
}
+inline void
+list_append(ATuple* head, const AST* child) {
+ for (ATuple* i = head; i; i = const_cast<ATuple*>(i->rst())) {
+ if (!i->rst()) {
+ i->last(new ATuple(child, NULL, child->loc));
+ return;
+ }
+ }
+}
+
struct AType {
static inline bool is_var(const AST* type) { return type->tag() == T_TVAR; }
static inline bool is_name(const AST* type) { return type->tag() == T_SYMBOL; }
@@ -427,6 +447,8 @@ AST::operator==(const AST& rhs) const
case T_SYMBOL:
case T_LITSYM:
return ((ASymbol*)this)->sym() == ((ASymbol*)&rhs)->sym(); // interned
+ case T_ELLIPSIS:
+ return *((AEllipsis*)this)->pred() == *((AEllipsis*)&rhs)->pred();
case T_UNKNOWN:
return this == &rhs;
}
@@ -542,7 +564,8 @@ struct Constraint : public pair<const AST*,const AST*> {
static inline bool
is_dots(const AST* exp) {
- return (exp->to_symbol() && exp->as_symbol()->str() == "...");
+ return (exp->tag() == T_ELLIPSIS ||
+ (exp->to_symbol() && exp->as_symbol()->str() == "..."));
}
/// Type substitution
@@ -562,14 +585,22 @@ struct Subst : public list<Constraint> {
return j;
return end();
}
+ const_iterator find_ellipsis(const AST* t) const {
+ for (const_iterator j = begin(); j != end(); ++j)
+ if (j->first->tag() == T_ELLIPSIS &&
+ *((AEllipsis*)j->first)->pred() == *t)
+ return j;
+ return end();
+ }
const AST* apply(const AST* in) const {
if (AType::is_expr(in)) {
if (in->as_tuple()->empty())
return in;
List out;
- for (auto i : *in->as_tuple()) {
+ const AST* prev = NULL;
+ for (const auto& i : *in->as_tuple()) {
if (is_dots(i)) {
- const_iterator o = find(i);
+ const_iterator o = find_ellipsis(prev);
if (o != end()) {
for (auto j : *o->second->as_tuple()) {
out.push_back(apply(j));
@@ -578,6 +609,7 @@ struct Subst : public list<Constraint> {
} else {
out.push_back(apply(i));
}
+ prev = i;
}
if (out.head)
out.head->loc = in->loc;