From ad056bdf71c8bf780e22f983c83fac0e3a2f41f3 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 3 Dec 2010 03:08:08 +0000 Subject: Remove use of RTTI for AST. git-svn-id: http://svn.drobilla.net/resp/resp@290 ad02d1e2-f140-0410-9f75-f8b11f17cedd --- src/c.cpp | 24 ++++++------ src/compile.cpp | 57 ++++++++++++++--------------- src/constrain.cpp | 46 ++++++++++++----------- src/cps.cpp | 6 +-- src/gc.cpp | 7 ++-- src/lift.cpp | 42 +++++++++++---------- src/llvm.cpp | 53 +++++++++++++-------------- src/parse.cpp | 28 +++++++------- src/pprint.cpp | 60 ++++++++++++++---------------- src/repl.cpp | 6 +-- src/resp.cpp | 10 ++--- src/resp.hpp | 107 ++++++++++++++++++++++++++++++++++++++---------------- src/unify.cpp | 24 ++++++------ 13 files changed, 254 insertions(+), 216 deletions(-) diff --git a/src/c.cpp b/src/c.cpp index 7df33b0..6493ff3 100644 --- a/src/c.cpp +++ b/src/c.cpp @@ -55,14 +55,14 @@ llType(const AType* t) throw Error(t->loc, string("Unknown primitive type `") + t->str() + "'"); } else if (t->kind == AType::EXPR && t->head()->str() == "Fn") { AType::const_iterator i = t->begin(); - const ATuple* protT = (*++i)->to(); - const AType* retT = (*i)->as(); + const ATuple* protT = (*++i)->to_tuple(); + const AType* retT = (*i)->as_type(); if (!llType(retT)) return NULL; Type* ret = new Type(*llType(retT) + " (*)("); FOREACHP(ATuple::const_iterator, i, protT) { - const AType* at = (*i)->to(); + const AType* at = (*i)->to_type(); const Type* lt = llType(at); if (!lt) return NULL; @@ -74,7 +74,7 @@ llType(const AType* t) } else if (t->kind == AType::EXPR && t->head()->str() == "Tup") { Type* ret = new Type("struct { void* me; "); for (AType::const_iterator i = t->iter_at(1); i != t->end(); ++i) { - const Type* lt = llType((*i)->to()); + const Type* lt = llType((*i)->to_type()); if (!lt) return NULL; ret->append("; "); @@ -103,12 +103,12 @@ struct CEngine : public Engine { CFunc startFunction(CEnv& cenv, const std::string& name, const ATuple* args, const AType* type) { - const AType* argsT = type->prot()->as(); - const AType* retT = type->list_ref(2)->as(); + const AType* argsT = type->prot()->as_type(); + const AType* retT = type->list_ref(2)->as_type(); vector cprot; FOREACHP(ATuple::const_iterator, i, argsT) { - const AType* at = (*i)->as(); + const AType* at = (*i)->as_type(); THROW_IF(!llType(at), Cursor(), string("non-concrete parameter :: ") + at->str()) cprot.push_back(llType(at)); @@ -126,7 +126,7 @@ struct CEngine : public Engine { for (; ai != argsT->end(); ++ai, ++ni) { if (ai != argsT->begin()) f->text += ", "; - f->text += *llType((*ai)->as()) + " " + (*ni)->as()->cppstr; + f->text += *llType((*ai)->as_type()) + " " + (*ni)->as_symbol()->cppstr; } f->text += ")\n{\n"; @@ -215,17 +215,17 @@ CEngine::pushFunctionArgs(CEnv& cenv, const ATuple* fn, const AType* type, CFunc { cenv.push(); - const AType* argsT = type->prot()->as(); + const AType* argsT = type->prot()->as_type(); // Bind argument values in CEnv vector args; ATuple::const_iterator p = fn->prot()->begin(); ATuple::const_iterator pT = argsT->begin(); for (; p != fn->prot()->end(); ++p, ++pT) { - const AType* t = (*pT)->as(); + const AType* t = (*pT)->as_type(); const Type* lt = llType(t); THROW_IF(!lt, fn->loc, "untyped parameter\n"); - cenv.def((*p)->as(), *p, t, new string((*p)->str())); + cenv.def((*p)->as_symbol(), *p, t, new string((*p)->str())); } } @@ -275,7 +275,7 @@ CEngine::compilePrimitive(CEnv& cenv, const ATuple* prim) Value* a = llVal(resp_compile(cenv, *i++)); Value* b = llVal(resp_compile(cenv, *i++)); - const string n = prim->head()->to()->str(); + const string n = prim->head()->to_symbol()->str(); string op = n; // Convert operator to C operator if they don't match diff --git a/src/compile.cpp b/src/compile.cpp index ebd6083..142fa0a 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -69,7 +69,7 @@ compile_fn(CEnv& cenv, const ATuple* fn) throw() static CVal compile_type(CEnv& cenv, const AType* type) throw() { - const ASymbol* sym = type->head()->as(); + const ASymbol* sym = type->head()->as_symbol(); CVal* existing = cenv.vals.ref(sym); if (existing) { return *existing; @@ -99,7 +99,7 @@ compile_call(CEnv& cenv, const ATuple* call) throw() static CVal compile_def(CEnv& cenv, const ATuple* def) throw() { - const ASymbol* const sym = def->list_ref(1)->as(); + const ASymbol* const sym = def->list_ref(1)->as_symbol(); const AST* const body = def->list_ref(2); cenv.def(sym, body, cenv.type(body), NULL); // define stub first for recursion CVal val = resp_compile(cenv, body); @@ -115,7 +115,7 @@ compile_def(CEnv& cenv, const ATuple* def) throw() static CVal compile_cons(CEnv& cenv, const ATuple* cons) throw() { - AType* type = new AType(const_cast(cons->head()->as()), NULL, Cursor()); + AType* type = new AType(const_cast(cons->head()->as_symbol()), NULL, Cursor()); TList tlist(type); vector fields; for (ATuple::const_iterator i = cons->iter_at(1); i != cons->end(); ++i) { @@ -128,9 +128,10 @@ compile_cons(CEnv& cenv, const ATuple* cons) throw() static CVal compile_dot(CEnv& cenv, const ATuple* dot) throw() { - ATuple::const_iterator i = dot->begin(); - const AST* tup = *++i; - const ALiteral* index = (*++i)->as*>(); + ATuple::const_iterator i = dot->begin(); + const AST* tup = *++i; + const ALiteral* index = (ALiteral*)(*++i); + assert(index->tag() == T_INT32); CVal tupVal = resp_compile(cenv, tup); return cenv.engine()->compileDot(cenv, tupVal, index->val); } @@ -138,33 +139,28 @@ compile_dot(CEnv& cenv, const ATuple* dot) throw() CVal resp_compile(CEnv& cenv, const AST* ast) throw() { - if (ast->to*>() - || ast->to*>() - || ast->to*>()) + switch (ast->tag()) { + case T_UNKNOWN: + return NULL; + case T_TYPE: + return compile_type(cenv, ast->as_type()); + case T_BOOL: + case T_FLOAT: + case T_INT32: return cenv.engine()->compileLiteral(cenv, ast); - - const AString* str = ast->to(); - if (str) - return cenv.engine()->compileString(cenv, str->cppstr.c_str()); - - const ALexeme* lexeme = ast->to(); - if (lexeme) - return cenv.engine()->compileString(cenv, lexeme->cppstr.c_str()); - - const ASymbol* sym = ast->to(); - if (sym) - return compile_symbol(cenv, sym); - - const AType* type = ast->to(); - if (type) - return compile_type(cenv, type); - - const ATuple* const call = ast->to(); - if (call) { - const ASymbol* const sym = call->head()->to(); + case T_LEXEME: + return cenv.engine()->compileString(cenv, ((ALexeme*)ast)->cppstr.c_str()); + case T_STRING: + return cenv.engine()->compileString(cenv, ((AString*)ast)->cppstr.c_str()); + case T_SYMBOL: + return compile_symbol(cenv, ast->as_symbol()); + case T_TUPLE: + { + const ATuple* const call = ast->as_tuple(); + const ASymbol* const sym = call->head()->to_symbol(); const std::string form = sym ? sym->cppstr : ""; if (is_primitive(cenv.penv, call)) - return cenv.engine()->compilePrimitive(cenv, ast->as()); + return cenv.engine()->compilePrimitive(cenv, ast->as_tuple()); else if (form == "fn") return compile_fn(cenv, call); else if (form == "def") @@ -184,6 +180,7 @@ resp_compile(CEnv& cenv, const AST* ast) throw() else return compile_call(cenv, call); } + } cenv.err << "Attempt to compile unknown type: " << ast << endl; assert(false); diff --git a/src/constrain.cpp b/src/constrain.cpp index fd4e9f4..410df87 100644 --- a/src/constrain.cpp +++ b/src/constrain.cpp @@ -41,7 +41,7 @@ constrain_fn(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) // Add parameters to environment frame TList protT; for (ATuple::const_iterator i = prot->begin(); i != prot->end(); ++i) { - const ASymbol* sym = (*i)->to(); + const ASymbol* sym = (*i)->to_symbol(); THROW_IF(!sym, (*i)->loc, "parameter name is not a symbol"); THROW_IF(defs.count(sym) != 0, sym->loc, (format("duplicate parameter `%1%'") % sym->str()).str()); @@ -58,9 +58,9 @@ constrain_fn(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) // Add internal definitions to environment frame for (++i; i != call->end(); ++i) { const AST* exp = *i; - const ATuple* call = exp->to(); + const ATuple* call = exp->to_tuple(); if (call && is_form(call, "def")) { - const ASymbol* sym = call->list_ref(1)->as(); + const ASymbol* sym = call->list_ref(1)->as_symbol(); THROW_IF(defs.count(sym) != 0, call->loc, (format("`%1%' defined twice") % sym->str()).str()); defs.insert(sym); @@ -89,7 +89,7 @@ static void constrain_def(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) { THROW_IF(call->list_len() != 3, call->loc, "`def' requires exactly 2 arguments"); - const ASymbol* const sym = call->list_ref(1)->as(); + const ASymbol* const sym = call->list_ref(1)->as_symbol(); THROW_IF(!sym, call->loc, "`def' has no symbol") const AST* const body = call->list_ref(2); @@ -105,19 +105,19 @@ constrain_def_type(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) { THROW_IF(call->list_len() < 3, call->loc, "`def-type' requires at least 2 arguments"); ATuple::const_iterator i = call->iter_at(1); - const ATuple* prot = (*i)->to(); + const ATuple* prot = (*i)->to_tuple(); THROW_IF(!prot, (*i)->loc, "first argument of `def-type' is not a tuple"); - const ASymbol* sym = (*prot->begin())->as(); + const ASymbol* sym = (*prot->begin())->as_symbol(); THROW_IF(!sym, (*prot->begin())->loc, "type name is not a symbol"); THROW_IF(tenv.ref(sym), call->loc, "type redefinition"); TList type(new AType(tenv.U, NULL, call->loc)); for (ATuple::const_iterator i = call->iter_at(2); i != call->end(); ++i) { - const ATuple* exp = (*i)->as(); - const ASymbol* tag = (*exp->begin())->as(); + const ATuple* exp = (*i)->as_tuple(); + const ASymbol* tag = (*exp->begin())->as_symbol(); TList consT; consT.push_back(new AType(const_cast(sym), AType::NAME)); for (ATuple::const_iterator i = exp->begin(); i != exp->end(); ++i) { - const ASymbol* sym = (*i)->to(); + const ASymbol* sym = (*i)->to_symbol(); THROW_IF(!sym, (*i)->loc, "type expression element is not a symbol"); consT.push_back(new AType(const_cast(sym), AType::NAME)); } @@ -138,15 +138,15 @@ constrain_match(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) resp_constrain(tenv, c, matchee); for (ATuple::const_iterator i = call->iter_at(2); i != call->end();) { const AST* exp = *i++; - const ATuple* pattern = exp->to(); + const ATuple* pattern = exp->to_tuple(); THROW_IF(!pattern, exp->loc, "pattern expression expected"); - const ASymbol* name = (*pattern->begin())->to(); + const ASymbol* name = (*pattern->begin())->to_symbol(); THROW_IF(!name, (*pattern->begin())->loc, "pattern does not start with a symbol"); const AType* consT = *tenv.ref(name); if (!matcheeT) { - const AType* headT = consT->head()->as(); + const AType* headT = consT->head()->as_type(); matcheeT = tup(call->loc, const_cast(headT), 0); } @@ -184,7 +184,7 @@ constrain_if(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) static void constrain_cons(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) { - const ASymbol* sym = (*call->begin())->as(); + const ASymbol* sym = (*call->begin())->as_symbol(); const AType* type = NULL; for (ATuple::const_iterator i = call->iter_at(1); i != call->end(); ++i) @@ -201,7 +201,7 @@ constrain_cons(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) THROW_IF(!consTRef, call->loc, (format("call to undefined constructor `%1%'") % sym->cppstr).str()); const AType* consT = *consTRef; - type = tup(call->loc, const_cast(consT->head()->as()), 0); + type = tup(call->loc, const_cast(consT->head()->as_type()), 0); } c.constrain(tenv, call, type); } @@ -210,10 +210,12 @@ static void constrain_dot(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) { THROW_IF(call->list_len() != 3, call->loc, "`.' requires exactly 2 arguments"); - ATuple::const_iterator i = call->begin(); - const AST* obj = *++i; - const ALiteral* idx = (*++i)->to*>(); - THROW_IF(!idx, call->loc, "the 2nd argument to `.' must be a literal integer"); + ATuple::const_iterator i = call->begin(); + const AST* obj = *++i; + const AST* idx_ast = *++i; + THROW_IF(idx_ast->tag() != T_INT32, call->loc, "the 2nd argument to `.' must be a literal integer"); + const ALiteral* idx = (ALiteral*)idx_ast; + resp_constrain(tenv, c, obj); const AType* retT = tenv.var(call); @@ -266,7 +268,7 @@ constrain_call(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) static void constrain_primitive(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) { - const string n = call->head()->to()->str(); + const string n = call->head()->to_symbol()->str(); enum { ARITHMETIC, BINARY, LOGICAL, COMPARISON } type; if (n == "+" || n == "-" || n == "*" || n == "/") type = ARITHMETIC; @@ -322,7 +324,7 @@ constrain_primitive(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) static void constrain_tuple(TEnv& tenv, Constraints& c, const ATuple* tup) throw(Error) { - const ASymbol* const sym = tup->head()->to(); + const ASymbol* const sym = tup->head()->to_symbol(); if (!sym) { constrain_call(tenv, c, tup); return; @@ -374,10 +376,10 @@ resp_constrain(TEnv& tenv, Constraints& c, const AST* ast) throw(Error) c.constrain(tenv, ast, tenv.named("String")); break; case T_SYMBOL: - constrain_symbol(tenv, c, ast->as()); + constrain_symbol(tenv, c, ast->as_symbol()); break; case T_TUPLE: - constrain_tuple(tenv, c, ast->as()); + constrain_tuple(tenv, c, ast->as_tuple()); break; } } diff --git a/src/cps.cpp b/src/cps.cpp index 889a716..f7c3892 100644 --- a/src/cps.cpp +++ b/src/cps.cpp @@ -66,7 +66,7 @@ ATuple::cps(TEnv& tenv, AST* cont) const AFn* firstFn = NULL; ssize_t index = 0; FOREACHP(const_iterator, i, this) { - if (!(*i)->to()) { + if (!(*i)->to_tuple()) { funcs.push_back(make_pair((AFn*)NULL, (*i))); } else { arg = tenv.penv.gensym("a"); @@ -114,8 +114,8 @@ ATuple::cps(TEnv& tenv, AST* cont) const AST* ADef::cps(TEnv& tenv, AST* cont) const { - AST* val = body()->cps(tenv, cont); - ATuple* valCall = val->to(); + AST* val = body()->cps(tenv, cont); + ATuple* valCall = val->to_tuple(); ATuple::iterator i = valCall->begin(); return tup(loc, tenv.penv.sym("def"), sym(), *++i, 0); } diff --git a/src/gc.cpp b/src/gc.cpp index 8ed0fb2..cff4f0a 100644 --- a/src/gc.cpp +++ b/src/gc.cpp @@ -57,7 +57,7 @@ mark(const Object* obj) obj->mark(true); if (obj->tag() != T_UNKNOWN) { - const ATuple* tup = ((const AST*)obj)->to(); + const ATuple* tup = ((const AST*)obj)->to_tuple(); if (tup) FOREACHP(ATuple::const_iterator, i, tup) mark(*i); @@ -80,8 +80,9 @@ GC::collect(const Roots& roots) (*i)->mark(false); assert(!(*i)->marked()); } else { - if ((*i)->tag() != T_UNKNOWN) - ((AST*)*i)->~AST(); + const Tag tag = (*i)->tag(); + if (tag == T_TUPLE || tag == T_TYPE) + free(((ATuple*)*i)->_vec); tlsf_free((tlsf_t*)_pool, ((char*)(*i) - sizeof(Object::Header))); _heap.erase(i); diff --git a/src/lift.cpp b/src/lift.cpp index df34d7a..04bf61b 100644 --- a/src/lift.cpp +++ b/src/lift.cpp @@ -28,7 +28,7 @@ using namespace std; static AST* -lift_symbol(CEnv& cenv, Code& code, ASymbol* sym) throw() +lift_symbol(CEnv& cenv, Code& code, const ASymbol* sym) throw() { const std::string& cppstr = sym->cppstr; if (!cenv.liftStack.empty() && cppstr == cenv.name(cenv.liftStack.top().fn)) { @@ -45,7 +45,7 @@ lift_symbol(CEnv& cenv, Code& code, ASymbol* sym) throw() new ALiteral(T_INT32, index, Cursor()), NULL); } else { - return sym; + return const_cast(sym); } } @@ -64,16 +64,18 @@ lift_fn(CEnv& cenv, Code& code, ATuple* fn) throw() cenv.push(); const AType* type = cenv.type(fn); AType::const_iterator tp = type->prot()->begin(); - AType* implProtT = new AType(*type->prot()->as()); + AType* implProtT = new AType(*type->prot()->as_type()); ATuple::iterator ip = implProtT->begin(); for (ATuple::const_iterator p = fn->prot()->begin(); p != fn->prot()->end(); ++p) { - const AType* paramType = (*tp++)->as(); + const AType* paramType = (*tp++)->as_type(); if (paramType->kind == AType::EXPR && *paramType->head() == *cenv.tenv.Fn) { AType* fnType = new AType(*paramType); - fnType->set_prot(new AType(const_cast(cenv.tenv.var()), fnType->prot()->as(), Cursor())); + fnType->set_prot(new AType(const_cast(cenv.tenv.var()), + const_cast(fnType->prot()->as_type()), + Cursor())); paramType = tup((*p)->loc, cenv.tenv.Tup, fnType, NULL); } - cenv.def((*p)->as(), *p, paramType, NULL); + cenv.def((*p)->as_symbol(), *p, paramType, NULL); *ip++ = new AType(*paramType); } @@ -111,7 +113,7 @@ lift_fn(CEnv& cenv, Code& code, ATuple* fn) throw() const CEnv::FreeVars& freeVars = cenv.liftStack.top(); for (CEnv::FreeVars::const_iterator i = freeVars.begin(); i != freeVars.end(); ++i) { - cons.push_back(*i); + cons.push_back(const_cast(*i)); tupT.push_back(const_cast(cenv.type(*i))); consT.push_back(const_cast(cenv.type(*i))); } @@ -143,7 +145,7 @@ lift_call(CEnv& cenv, Code& code, ATuple* call) throw() const AType* copyT = NULL; - ASymbol* sym = call->head()->to(); + const ASymbol* sym = call->head()->to_symbol(); if (sym && !cenv.liftStack.empty() && sym->cppstr == cenv.name(cenv.liftStack.top().fn)) { /* Recursive call to innermost function, call implementation directly, * reusing the current "_me" closure parameter (no cons or .). @@ -157,11 +159,11 @@ lift_call(CEnv& cenv, Code& code, ATuple* call) throw() * closure as the first parameter: * (_impl (Fn _impl ...) ...) */ - ATuple* closure = copy.head->list_ref(0)->as(); - ASymbol* implSym = closure->list_ref(1)->as(); + ATuple* closure = copy.head->list_ref(0)->as_tuple(); + ASymbol* implSym = const_cast(closure->list_ref(1)->as_symbol()); const AType* implT = cenv.type(cenv.resolve(implSym)); copy.push_front(implSym); - copyT = implT->list_ref(2)->as(); + copyT = implT->list_ref(2)->as_type(); } else { // Call to a closure, prepend code to access implementation function ATuple* getFn = tup(call->loc, cenv.penv.sym("."), @@ -169,10 +171,10 @@ lift_call(CEnv& cenv, Code& code, ATuple* call) throw() new ALiteral(T_INT32, 0, Cursor()), NULL); const AType* calleeT = cenv.type(copy.head->head()); assert(**calleeT->begin() == *cenv.tenv.Tup); - const AType* implT = calleeT->list_ref(1)->as(); + const AType* implT = calleeT->list_ref(1)->as_type(); copy.push_front(getFn); cenv.setType(getFn, implT); - copyT = implT->list_ref(2)->as(); + copyT = implT->list_ref(2)->as_type(); } cenv.setType(copy, copyT); @@ -183,13 +185,13 @@ static AST* lift_def(CEnv& cenv, Code& code, ATuple* def) throw() { // Define stub first for recursion - const ASymbol* const sym = def->list_ref(1)->as(); + const ASymbol* const sym = def->list_ref(1)->as_symbol(); AST* const body = def->list_ref(2); cenv.def(sym, body, cenv.type(body), NULL); if (is_form(body, "fn")) - cenv.setName(body->as(), sym->str()); + cenv.setName(body->as_tuple(), sym->str()); - assert(def->list_ref(1)->to()); + assert(def->list_ref(1)->to_symbol()); List copy; copy.push_back(def->head()); copy.push_back(resp_lift(cenv, code, def->list_ref(1))); @@ -201,7 +203,7 @@ lift_def(CEnv& cenv, Code& code, ATuple* def) throw() if (copy.head->list_ref(1) == copy.head->list_ref(2)) return NULL; // Definition created by lift_fn when body was lifted - cenv.def(copy.head->list_ref(1)->as(), + cenv.def(copy.head->list_ref(1)->as_symbol(), copy.head->list_ref(2), cenv.type(copy.head->list_ref(2)), NULL); @@ -225,13 +227,13 @@ lift_builtin_call(CEnv& cenv, Code& code, ATuple* call) throw() AST* resp_lift(CEnv& cenv, Code& code, AST* ast) throw() { - ASymbol* const sym = ast->to(); + const ASymbol* const sym = ast->to_symbol(); if (sym) return lift_symbol(cenv, code, sym); - ATuple* const call = ast->to(); + ATuple* const call = ast->to_tuple(); if (call) { - const ASymbol* const sym = call->head()->to(); + const ASymbol* const sym = call->head()->to_symbol(); const std::string form = sym ? sym->cppstr : ""; if (is_primitive(cenv.penv, call)) return lift_builtin_call(cenv, code, call); diff --git a/src/llvm.cpp b/src/llvm.cpp index 31e6f6d..eabe508 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -99,14 +99,14 @@ struct LLVMEngine : public Engine { throw Error(t->loc, string("Unknown primitive type `") + t->str() + "'"); } else if (t->kind == AType::EXPR && t->head()->str() == "Fn") { AType::const_iterator i = t->begin(); - const ATuple* protT = (*++i)->to(); - const AType* retT = (*++i)->as(); + const ATuple* protT = (*++i)->to_tuple(); + const AType* retT = (*++i)->as_type(); if (!llType(retT)) return NULL; vector cprot; FOREACHP(ATuple::const_iterator, i, protT) { - const Type* lt = llType((*i)->to()); + const Type* lt = llType((*i)->to_type()); if (!lt) return NULL; cprot.push_back(lt); @@ -117,7 +117,7 @@ struct LLVMEngine : public Engine { vector ctypes; ctypes.push_back(PointerType::get(Type::getInt8Ty(context), NULL)); // RTTI for (AType::const_iterator i = t->iter_at(1); i != t->end(); ++i) { - const Type* lt = llType((*i)->to()); + const Type* lt = llType((*i)->to_type()); if (!lt) return NULL; ctypes.push_back(lt); @@ -131,14 +131,14 @@ struct LLVMEngine : public Engine { CFunc startFunction(CEnv& cenv, const std::string& name, const ATuple* args, const AType* type) { - const AType* argsT = type->prot()->as(); - const AType* retT = type->list_last()->as(); + const AType* argsT = type->prot()->as_type(); + const AType* retT = type->list_last()->as_type(); Function::LinkageTypes linkage = Function::ExternalLinkage; vector cprot; FOREACHP(ATuple::const_iterator, i, argsT) { - const AType* at = (*i)->as(); + const AType* at = (*i)->as_type(); THROW_IF(!llType(at), Cursor(), string("non-concrete parameter :: ") + at->str()) cprot.push_back(llType(at)); @@ -158,7 +158,7 @@ struct LLVMEngine : public Engine { // Set argument names in generated code Function::arg_iterator a = f->arg_begin(); for (ATuple::const_iterator i = args->begin(); i != args->end(); ++a, ++i) - a->setName((*i)->as()->cppstr); + a->setName((*i)->as_symbol()->cppstr); BasicBlock* bb = BasicBlock::Create(context, "entry", f); builder.SetInsertPoint(bb); @@ -186,7 +186,7 @@ struct LLVMEngine : public Engine { CVal compileCall(CEnv& cenv, CFunc f, const AType* funcT, const vector& args) { vector llArgs(*reinterpret_cast*>(&args)); Value* closure = builder.CreateBitCast(llArgs[0], - llType(funcT->prot()->head()->as()), + llType(funcT->prot()->head()->as_type()), cenv.penv.gensymstr("you")); llArgs[0] = closure; return builder.CreateCall(llFunc(f), llArgs.begin(), llArgs.end()); @@ -279,7 +279,7 @@ LLVMEngine::compileTup(CEnv& cenv, const AType* type, CVal rtti, const vectorgetTargetData()->getTypeSizeInBits(PointerType::get(Type::getInt8Ty(context), NULL)); assert(type->begin() != type->end()); for (AType::const_iterator i = type->iter_at(1); i != type->end(); ++i) - s += engine->getTargetData()->getTypeSizeInBits(llType((*i)->as())); + s += engine->getTargetData()->getTypeSizeInBits(llType((*i)->as_type())); // Allocate struct Value* structSize = ConstantInt::get(Type::getInt32Ty(context), bitsToBytes(s)); @@ -308,19 +308,16 @@ LLVMEngine::compileDot(CEnv& cenv, CVal tup, int32_t index) CVal LLVMEngine::compileLiteral(CEnv& cenv, const AST* lit) { - const ALiteral* ilit = dynamic_cast*>(lit); - if (ilit) - return ConstantInt::get(Type::getInt32Ty(context), ilit->val, true); - - const ALiteral* flit = dynamic_cast*>(lit); - if (flit) - return ConstantFP::get(Type::getFloatTy(context), flit->val); - - const ALiteral* blit = dynamic_cast*>(lit); - if (blit) - return ConstantInt::get(Type::getInt1Ty(context), blit->val); - - throw Error(lit->loc, "Unknown literal type"); + switch (lit->tag()) { + case T_BOOL: + return ConstantInt::get(Type::getInt1Ty(context), ((const ALiteral*)lit)->val); + case T_FLOAT: + return ConstantFP::get(Type::getFloatTy(context), ((const ALiteral*)lit)->val); + case T_INT32: + return ConstantInt::get(Type::getInt32Ty(context), ((const ALiteral*)lit)->val, true); + default: + throw Error(lit->loc, "Unknown literal type"); + } } CVal @@ -334,7 +331,7 @@ LLVMEngine::pushFunctionArgs(CEnv& cenv, const ATuple* fn, const AType* type, CF { cenv.push(); - const AType* argsT = type->prot()->as(); + const AType* argsT = type->prot()->as_type(); // Bind argument values in CEnv vector args; @@ -343,10 +340,10 @@ LLVMEngine::pushFunctionArgs(CEnv& cenv, const ATuple* fn, const AType* type, CF assert(fn->prot()->size() == argsT->size()); assert(fn->prot()->size() == f->num_args()); for (Function::arg_iterator a = llFunc(f)->arg_begin(); a != llFunc(f)->arg_end(); ++a, ++p, ++pT) { - const AType* t = (*pT)->as(); + const AType* t = (*pT)->as_type(); const Type* lt = llType(t); THROW_IF(!lt, fn->loc, "untyped parameter\n"); - cenv.def((*p)->as(), *p, t, &*a); + cenv.def((*p)->as_symbol(), *p, t, &*a); } } @@ -419,7 +416,7 @@ LLVMEngine::compileMatch(CEnv& cenv, const ATuple* match) for (ATuple::const_iterator i = match->iter_at(2); i != match->end(); ++idx) { const AST* pat = *i++; const AST* body = *i++; - const ASymbol* sym = pat->to()->head()->as(); + const ASymbol* sym = pat->to_tuple()->head()->as_symbol(); const AType* patT = tup(Cursor(), const_cast(sym), 0); Value* typeV = llVal(resp_compile(cenv, patT)); @@ -465,7 +462,7 @@ LLVMEngine::compilePrimitive(CEnv& cenv, const ATuple* prim) bool isFloat = cenv.type(*++i)->str() == "Float"; Value* a = llVal(resp_compile(cenv, *i++)); Value* b = llVal(resp_compile(cenv, *i++)); - const string n = prim->head()->to()->str(); + const string n = prim->head()->to_symbol()->str(); // Binary arithmetic operations Instruction::BinaryOps op = (Instruction::BinaryOps)0; diff --git a/src/parse.cpp b/src/parse.cpp index a9527ea..7f107aa 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -35,22 +35,22 @@ parseTuple(PEnv& penv, const ATuple* e) AST* PEnv::parse(const AST* exp) { - const ATuple* tup = exp->to(); + const ATuple* tup = exp->to_tuple(); if (tup) { THROW_IF(tup->empty(), exp->loc, "Call to empty list"); - const ALexeme* form = tup->head()->to(); + const ALexeme* form = tup->head()->to_lexeme(); if (form) { MF mf = mac(*form); if (mf) { - exp = mf(*this, exp)->as(); // Apply macro - tup = exp->to(); + exp = mf(*this, exp)->as_tuple(); // Apply macro + tup = exp->to_tuple(); } } } if (tup) { THROW_IF(tup->empty(), exp->loc, "Call to empty list"); - const ALexeme* form = tup->head()->to(); + const ALexeme* form = tup->head()->to_lexeme(); if (form) { const PEnv::Handler* h = handler(true, form->cppstr); if (h) @@ -63,7 +63,7 @@ PEnv::parse(const AST* exp) return parseTuple(*this, tup); // Parse regular call } - const ALexeme* lex = exp->to(); + const ALexeme* lex = exp->to_lexeme(); assert(lex); if (isdigit(lex->cppstr[0])) { const std::string& s = lex->cppstr; @@ -89,16 +89,16 @@ PEnv::parse(const AST* exp) inline AST* macDef(PEnv& penv, const AST* exp) { - const ATuple* tup = exp->to(); + const ATuple* tup = exp->to_tuple(); ATuple::const_iterator i = tup->begin(); THROW_IF(i == tup->end(), tup->loc, "Unexpected end of `def' macro call"); const AST* arg1 = *(++i); THROW_IF(i == tup->end(), arg1->loc, "Unexpected end of `def' macro call"); - if (arg1->to()) { + if (arg1->to_lexeme()) { return const_cast(exp); } else { // (def (f x) y) => (def f (fn (x) y)) - const ATuple* pat = arg1->to(); + const ATuple* pat = arg1->to_tuple(); List argsExp; ATuple::const_iterator j = pat->begin(); @@ -131,7 +131,7 @@ macDef(PEnv& penv, const AST* exp) inline AST* parseCall(PEnv& penv, const AST* exp, void* arg) { - return parseTuple(penv, exp->to()); + return parseTuple(penv, exp->to_tuple()); } inline AST* @@ -143,10 +143,10 @@ parseBool(PEnv& penv, const AST* exp, void* arg) inline AST* parseFn(PEnv& penv, const AST* exp, void* arg) { - const ATuple* texp = exp->to(); + const ATuple* texp = exp->to_tuple(); ATuple::const_iterator a = texp->begin(); THROW_IF(++a == texp->end(), exp->loc, "Unexpected end of `fn' form"); - ATuple* prot = parseTuple(penv, (*a++)->to()); + ATuple* prot = parseTuple(penv, (*a++)->to_tuple()); List ret(new ATuple(penv.sym("fn"), NULL, Cursor())); ret.push_back(prot); while (a != texp->end()) @@ -158,9 +158,9 @@ parseFn(PEnv& penv, const AST* exp, void* arg) inline AST* parseQuote(PEnv& penv, const AST* exp, void* arg) { - const ATuple* texp = exp->to(); + const ATuple* texp = exp->to_tuple(); THROW_IF(texp->list_len() != 2, exp->loc, "`quote' requires exactly 1 argument"); - const ALexeme* quotee = texp->list_ref(1)->to(); + const ALexeme* quotee = texp->list_ref(1)->to_lexeme(); THROW_IF(!quotee, exp->loc, "`quote' argument is not a lexeme"); ATuple* ret = tup(texp->loc, penv.sym("quote"), quotee, NULL); return ret; diff --git a/src/pprint.cpp b/src/pprint.cpp index 2f4180b..528683f 100644 --- a/src/pprint.cpp +++ b/src/pprint.cpp @@ -60,32 +60,12 @@ print_tuple(ostream& out, const ATuple* tup, ATuple::const_iterator i, ostream& print_to(ostream& out, const AST* ast, unsigned indent, CEnv* cenv, bool types) { - const ALexeme* lexeme = ast->to(); - if (lexeme) - return out << lexeme->cppstr; - - const ALiteral* flit = ast->to*>(); - if (flit) - return out << showpoint << flit->val; - - const ALiteral* ilit = ast->to*>(); - if (ilit) - return out << ilit->val; - - const ALiteral* blit = ast->to*>(); - if (blit) - return out << (blit->val ? "#t" : "#f"); - - const AString* str = ast->to(); - if (str) - return out << '"' << str->cppstr << '"'; - - const ASymbol* sym = ast->to(); - if (sym) - return out << sym->cppstr; - - const AType* type = ast->to(); - if (type) { + switch (ast->tag()) { + case T_UNKNOWN: + return out << "?"; + case T_TYPE: + { + const AType* type = ast->as_type(); switch (type->kind) { case AType::VAR: return out << "?" << type->id; case AType::NAME: return out << type->head(); @@ -93,20 +73,20 @@ print_to(ostream& out, const AST* ast, unsigned indent, CEnv* cenv, bool types) case AType::DOTS: return out << "..."; case AType::EXPR: break; // will catch Tuple case below } - } - - const ATuple* tup = ast->to(); - if (tup) { + } + case T_TUPLE: + { + const ATuple* tup = ast->as_tuple(); out << "("; ATuple::const_iterator i = tup->begin(); std::string form = ""; if (i != tup->end()) { - const ASymbol* sym = (*i)->to(); + const ASymbol* sym = (*i)->to_symbol(); if (sym) { form = sym->cppstr; } else { - const ALexeme* lexeme = (*i)->to(); + const ALexeme* lexeme = (*i)->to_lexeme(); if (lexeme) form = lexeme->cppstr; } @@ -127,7 +107,7 @@ print_to(ostream& out, const AST* ast, unsigned indent, CEnv* cenv, bool types) } else if (form == "fn") { out << (*i++) << " "; - const ATuple* pat = (*i++)->as(); + const ATuple* pat = (*i++)->as_tuple(); // Print prototype (possibly with parameter type annotations) out << "("; @@ -161,6 +141,20 @@ print_to(ostream& out, const AST* ast, unsigned indent, CEnv* cenv, bool types) } else { return print_tuple(out, tup, i, indent + 1, false, cenv, types, false); } + break; + } + case T_BOOL: + return out << showpoint << ((const ALiteral*)ast)->val; + case T_FLOAT: + return out << showpoint << ((const ALiteral*)ast)->val; + case T_INT32: + return out << showpoint << ((const ALiteral*)ast)->val; + case T_LEXEME: + return out << ((const ALexeme*)ast)->cppstr; + case T_STRING: + return out << '"' << ((const AString*)ast)->cppstr << '"'; + case T_SYMBOL: + return out << ((const ASymbol*)ast)->cppstr; } return out << "?"; diff --git a/src/repl.cpp b/src/repl.cpp index f6f8a26..0ec644c 100644 --- a/src/repl.cpp +++ b/src/repl.cpp @@ -36,7 +36,7 @@ readParseType(CEnv& cenv, Cursor& cursor, istream& is, AST*& exp, AST*& ast) throw e; } - if (exp->to() && exp->to()->empty()) + if (exp->to_tuple() && exp->to_tuple()->empty()) return false; ast = cenv.penv.parse(exp); // Parse input @@ -114,12 +114,12 @@ eval(CEnv& cenv, Cursor& cursor, istream& is, bool execute) // Compile top-level (lifted) functions Code exprs; for (Code::const_iterator i = lifted.begin(); i != lifted.end(); ++i) { - const ATuple* call = (*i)->to(); + const ATuple* call = (*i)->to_tuple(); if (call && is_form(call, "def") && is_form(call->list_ref(2), "fn")) { val = resp_compile(cenv, call); } else { assert(*i); - ATuple* tup = (*i)->to(); + ATuple* tup = (*i)->to_tuple(); if (!tup || (tup->tup_len() > 0)) exprs.push_back(*i); } diff --git a/src/resp.cpp b/src/resp.cpp index 611de0d..eb70e62 100644 --- a/src/resp.cpp +++ b/src/resp.cpp @@ -31,11 +31,11 @@ GC Object::pool(8 * 1024 * 1024); bool is_form(const AST* ast, const std::string& form) { - const ATuple* call = ast->to(); + const ATuple* call = ast->to_tuple(); if (!call) return false; - const ASymbol* const sym = call->head()->to(); + const ASymbol* const sym = call->head()->to_symbol(); if (!sym) return false; @@ -45,11 +45,11 @@ is_form(const AST* ast, const std::string& form) bool is_primitive(const PEnv& penv, const AST* ast) { - const ATuple* call = ast->to(); + const ATuple* call = ast->to_tuple(); if (!call) return false; - const ASymbol* const sym = call->head()->to(); + const ASymbol* const sym = call->head()->to_symbol(); if (!sym) return false; @@ -144,7 +144,7 @@ main(int argc, char** argv) while (is.good() && !is.eof()) { Cursor loc(*f); AST* exp = readExpression(loc, is); - if (!exp || (exp->as() && exp->as()->tup_len() == 1)) + if (!exp || (exp->as_tuple() && exp->as_tuple()->tup_len() == 1)) break; AST* ast = penv.parse(exp); diff --git a/src/resp.hpp b/src/resp.hpp index a092fb9..e4caac5 100644 --- a/src/resp.hpp +++ b/src/resp.hpp @@ -206,22 +206,67 @@ extern ostream& operator<<(ostream& out, const AST* ast); typedef list Code; +struct ATuple; +struct ASymbol; +struct AType; +struct ALexeme; + /// Base class for all AST nodes struct AST : public Object { AST(Tag t, Cursor c=Cursor()) : loc(c) { this->tag(t); } - virtual ~AST() {} bool operator==(const AST& o) const; string str() const { ostringstream ss; ss << this; return ss.str(); } - template T to() { return dynamic_cast(this); } - template T const to() const { return dynamic_cast(this); } - template T as() { - T t = dynamic_cast(this); - return t ? t : throw Error(loc, "internal error: bad cast"); + + ATuple* as_tuple() { + assert(tag() == T_TUPLE || tag() == T_TYPE); + return (ATuple*)this; + } + const ATuple* as_tuple() const { + assert(tag() == T_TUPLE || tag() == T_TYPE); + return (ATuple*)this; + } + + ATuple* to_tuple() { + if (tag() == T_TUPLE || tag() == T_TYPE) + return (ATuple*)this; + return NULL; + } + const ATuple* to_tuple() const { + if (tag() == T_TUPLE || tag() == T_TYPE) + return (const ATuple*)this; + return NULL; + } + + template + T* as_a(Tag t) { + assert(tag() == t); + return (T*)this; + } + template + T* as_a(Tag t) const { + assert(tag() == t); + return (T*)this; + } + + template + T* to_a(Tag t) { + if (tag() == t) + return (T*)this; + return NULL; } - template T const as() const { - T const t = dynamic_cast(this); - return t ? t : throw Error(loc, "internal error: bad cast"); + template + T* to_a(Tag t) const { + if (tag() == t) + return (T*)this; + return NULL; } + + const ASymbol* as_symbol() const { return as_a(T_SYMBOL); } + const ASymbol* to_symbol() const { return to_a(T_SYMBOL); } + const ALexeme* to_lexeme() const { return to_a(T_LEXEME); } + const AType* as_type() const { return as_a(T_TYPE); } + const AType* to_type() const { return to_a(T_TYPE); } + Cursor loc; }; @@ -290,7 +335,6 @@ struct ATuple : public AST { } } - ~ATuple() { free(_vec); } const AST* head() const { assert(_len > 0); return _vec[0]; } AST*& head() { assert(_len > 0); return _vec[0]; } const AST* last() const { return _vec[_len - 1]; } @@ -328,7 +372,7 @@ struct ATuple : public AST { } inline void increment() { if (node->last()) - node = node->last()->as(); + node = node->last()->as_tuple(); else node = NULL; } @@ -358,7 +402,7 @@ struct ATuple : public AST { const_iterator(const iterator& i) : node(i.node) {} inline void increment() { if (node->last()) - node = node->last()->as(); + node = node->last()->as_tuple(); else node = NULL; } @@ -407,11 +451,12 @@ struct ATuple : public AST { AST*& list_ref(unsigned index) { return *iter_at(index); } const AST* list_ref(unsigned index) const { return *iter_at(index); } - const ATuple* prot() const { return list_ref(1)->as(); } - ATuple* prot() { return list_ref(1)->as(); } + const ATuple* prot() const { return list_ref(1)->as_tuple(); } + ATuple* prot() { return list_ref(1)->as_tuple(); } void set_prot(ATuple* prot) { *iter_at(1) = prot; } private: + friend class GC; size_t _len; AST** _vec; }; @@ -425,7 +470,7 @@ list_contains(const ATuple* head, const AST* child) { if (**p == *child) return true; - const ATuple* tup = (*p)->to(); + const ATuple* tup = (*p)->to_tuple(); if (tup && list_contains(tup, child)) return true; } @@ -450,7 +495,7 @@ struct AType : public ATuple { case PRIM: return head()->str() != "Nothing"; case EXPR: FOREACHP(const_iterator, t, this) { - const AType* kid = (*t)->to(); + const AType* kid = (*t)->to_type(); if (kid && !kid->concrete()) return false; } @@ -526,21 +571,21 @@ AST::operator==(const AST& rhs) const switch (tag) { case T_BOOL: - return literal_equals(this->as*>(), rhs.as*>()); + return literal_equals((const ALiteral*)this, (const ALiteral*)&rhs); case T_FLOAT: - return literal_equals(this->as*>(), rhs.as*>()); + return literal_equals((const ALiteral*)this, (const ALiteral*)&rhs); case T_INT32: - return literal_equals(this->as*>(), rhs.as*>()); + return literal_equals((const ALiteral*)this, (const ALiteral*)&rhs); case T_TUPLE: { - const ATuple* me = this->as(); - const ATuple* rt = rhs.to(); + const ATuple* me = this->as_tuple(); + const ATuple* rt = rhs.to_tuple(); return list_equals(me, rt); } case T_TYPE: { - const AType* me = this->as(); - const AType* rt = rhs.to(); + const AType* me = this->as_type(); + const AType* rt = rhs.to_type(); if (!rt || me->kind != rt->kind) { assert(str() != rt->str()); return false; @@ -640,15 +685,15 @@ struct Subst : public list { if (in->kind == AType::EXPR) { TList out; for (ATuple::const_iterator i = in->begin(); i != in->end(); ++i) - out.push_back(const_cast(apply((*i)->as()))); + out.push_back(const_cast(apply((*i)->as_type()))); out.head->loc = in->loc; return out.head; } else { const_iterator i = find(in); if (i != end()) { - const AType* out = i->second->as(); + const AType* out = i->second->as_type(); if (out->kind == AType::EXPR && !out->concrete()) - out = const_cast(apply(out->as())); + out = const_cast(apply(out->as_type())); return out; } else { return new AType(*in); @@ -790,7 +835,7 @@ struct CEnv { } const AType* type(const AST* ast, const Subst& subst = Subst()) const { const AType* ret = NULL; - const ASymbol* sym = ast->to(); + const ASymbol* sym = ast->to_symbol(); if (sym) { const AType** rec = tenv.ref(sym); if (rec) @@ -799,7 +844,7 @@ struct CEnv { if (!ret) ret = tenv.vars[ast]; if (ret) - return tsubst.apply(subst.apply(ret))->to(); + return tsubst.apply(subst.apply(ret))->to_type(); return NULL; } void def(const ASymbol* sym, const AST* c, const AType* t, CVal v) { @@ -808,7 +853,7 @@ struct CEnv { vals.def(sym, v); } const AST* resolve(const AST* ast) { - const ASymbol* sym = ast->to(); + const ASymbol* sym = ast->to_symbol(); const AST** rec = code.ref(sym); return rec ? *rec : ast; } @@ -846,11 +891,11 @@ struct CEnv { CFunc currentFn; ///< Currently compiling function - struct FreeVars : public std::vector { + struct FreeVars : public std::vector { FreeVars(ATuple* f, const std::string& n) : fn(f), implName(n) {} ATuple* const fn; const std::string implName; - int32_t index(ASymbol* sym) { + int32_t index(const ASymbol* sym) { const_iterator i = find(begin(), end(), sym); if (i != end()) { return i - begin() + 1; diff --git a/src/unify.cpp b/src/unify.cpp index ec5aa9a..51179d9 100644 --- a/src/unify.cpp +++ b/src/unify.cpp @@ -31,19 +31,19 @@ TEnv::buildSubst(const AType* genericT, const AType& argsT) Subst subst; // Build substitution to apply to generic type - const ATuple* genericProtT = genericT->list_ref(1)->as(); + const ATuple* genericProtT = genericT->list_ref(1)->as_tuple(); ATuple::const_iterator g = genericProtT->begin(); AType::const_iterator a = argsT.begin(); for (; a != argsT.end(); ++a, ++g) { - const AType* genericArgT = (*g)->to(); - const AType* callArgT = (*a)->to(); + const AType* genericArgT = (*g)->to_type(); + const AType* callArgT = (*a)->to_type(); if (callArgT->kind == AType::EXPR) { assert(genericArgT->kind == AType::EXPR); ATuple::const_iterator gi = genericArgT->begin(); ATuple::const_iterator ci = callArgT->begin(); for (; gi != genericArgT->end(); ++gi, ++ci) { - const AType* gT = (*gi)->to(); - const AType* aT = (*ci)->to(); + const AType* gT = (*gi)->to_type(); + const AType* aT = (*ci)->to_type(); if (gT && aT) subst.add(gT, aT); } @@ -60,7 +60,7 @@ Constraints::constrain(TEnv& tenv, const AST* o, const AType* t) { assert(o); assert(t); - assert(!o->to()); + assert(!o->to_type()); push_back(Constraint(tenv.var(o), t)); } @@ -75,13 +75,13 @@ substitute(const AType* tup, const AType* from, const AType* to) type->loc = (*i)->loc; ret.push_back(type); } else if (*i != to) { - const AType* elem = (*i)->as(); + const AType* elem = (*i)->as_type(); if (elem->kind == AType::EXPR) ret.push_back(const_cast(substitute(elem, from, to))); else ret.push_back(const_cast(elem)); } else { - ret.push_back(const_cast((*i)->as())); + ret.push_back(const_cast((*i)->as_type())); } } return ret.head; @@ -148,15 +148,15 @@ unify(const Constraints& constraints) AType::const_iterator si = s->begin(); AType::const_iterator ti = t->begin(); for (; si != s->end() && ti != t->end(); ++si, ++ti) { - const AType* st = (*si)->as(); - const AType* tt = (*ti)->as(); + const AType* st = (*si)->as_type(); + const AType* tt = (*ti)->as_type(); if (st->kind == AType::DOTS || tt->kind == AType::DOTS) return unify(cp); else cp.push_back(Constraint(st, tt)); } - if ( (si == s->end() && (ti == t->end() || (*ti)->as()->kind == AType::DOTS)) - || (ti == t->end() && (*si)->as()->kind == AType::DOTS)) + if ( (si == s->end() && (ti == t->end() || (*ti)->as_type()->kind == AType::DOTS)) + || (ti == t->end() && (*si)->as_type()->kind == AType::DOTS)) return unify(cp); } throw Error(s->loc, -- cgit v1.2.1