diff options
Diffstat (limited to 'src/resp.hpp')
-rw-r--r-- | src/resp.hpp | 56 |
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; |