aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2009-06-27 03:07:33 +0000
committerDavid Robillard <d@drobilla.net>2009-06-27 03:07:33 +0000
commit14a96af1b4554e75506621c3cc9b2c107f01a119 (patch)
tree7f1ef1d3c7bbb0e3af10b9664c9cbbee57dea0a1
parent9978c2ea1b408fb295c82577d7a14bf2d54cdb3b (diff)
downloadresp-14a96af1b4554e75506621c3cc9b2c107f01a119.tar.gz
resp-14a96af1b4554e75506621c3cc9b2c107f01a119.tar.bz2
resp-14a96af1b4554e75506621c3cc9b2c107f01a119.zip
Fix substitution of call argument types to generic function type to work with expressions (e.g. fix inferring return type from the return type of a parameter).
git-svn-id: http://svn.drobilla.net/resp/tuplr@154 ad02d1e2-f140-0410-9f75-f8b11f17cedd
-rw-r--r--gc.cpp2
-rw-r--r--llvm.cpp21
-rw-r--r--tuplr.cpp3
-rw-r--r--tuplr.hpp6
-rw-r--r--typing.cpp3
5 files changed, 30 insertions, 5 deletions
diff --git a/gc.cpp b/gc.cpp
index 6311058..3964324 100644
--- a/gc.cpp
+++ b/gc.cpp
@@ -77,9 +77,11 @@ GC::collect(const Roots& roots)
break;
case GC::TAG_AST:
AST* ast = (AST*)*i;
+ if (!ast->to<AType*>()) { // FIXME
(ast)->~AST();
free((char*)(*i) - sizeof(Object::Header));
_heap.erase(i);
+ }
break;
}
}
diff --git a/llvm.cpp b/llvm.cpp
index e963336..65632a4 100644
--- a/llvm.cpp
+++ b/llvm.cpp
@@ -234,12 +234,29 @@ AFn::liftCall(CEnv& cenv, const AType& argsT)
assert(gt != cenv.tenv.genericTypes.end());
AType* thisType = new AType(*gt->second);
Subst argsSubst;
+
if (!thisType->concrete()) {
// Build substitution to apply to generic type
assert(argsT.size() == prot()->size());
ATuple* genericProtT = gt->second->at(1)->as<ATuple*>();
- for (size_t i = 0; i < argsT.size(); ++i)
- argsSubst[genericProtT->at(i)->to<AType*>()] = argsT.at(i)->to<AType*>();
+ for (size_t i = 0; i < argsT.size(); ++i) {
+ const AType* genericArgT = genericProtT->at(i)->to<const AType*>();
+ AType* callArgT = argsT.at(i)->to<AType*>();
+ assert(genericArgT);
+ assert(callArgT);
+ if (callArgT->kind == AType::EXPR) {
+ assert(genericArgT->kind == AType::EXPR);
+ assert(callArgT->size() == genericArgT->size());
+ for (size_t i = 0; i < callArgT->size(); ++i) {
+ AType* gT = genericArgT->at(i)->to<AType*>();
+ AType* aT = callArgT->at(i)->to<AType*>();
+ if (gT && aT)
+ argsSubst[gT] = aT;
+ }
+ } else {
+ argsSubst[genericArgT] = callArgT;
+ }
+ }
// Apply substitution to get concrete type for this call
thisType = argsSubst.apply(thisType)->as<AType*>();
diff --git a/tuplr.cpp b/tuplr.cpp
index 7dd3e9b..5aaf54a 100644
--- a/tuplr.cpp
+++ b/tuplr.cpp
@@ -250,7 +250,8 @@ eval(CEnv& cenv, const string& name, istream& is)
result->constrain(cenv.tenv, c); // Constrain types
cenv.tsubst = Subst::compose(cenv.tsubst, TEnv::unify(c)); // Solve type constraints
resultType = cenv.type(result);
- result->lift(cenv); // Lift functions
+ if (resultType->concrete())
+ result->lift(cenv); // Lift functions
exprs.push_back(make_pair(exp, result));
// Add definitions as GC roots
diff --git a/tuplr.hpp b/tuplr.hpp
index 69f6bfd..382b9d4 100644
--- a/tuplr.hpp
+++ b/tuplr.hpp
@@ -345,7 +345,11 @@ struct Subst : public map<const AType*,AType*,typeLessThan> {
} else {
const_iterator i = find(in);
if (i != end()) {
- return i->second;
+ AST* out = i->second;
+ AType* outT = out->to<AType*>();
+ if (outT && outT->kind == AType::EXPR && !outT->concrete())
+ out = apply(out);
+ return out;
} else {
return in;
}
diff --git a/typing.cpp b/typing.cpp
index 4781b2e..cfc1104 100644
--- a/typing.cpp
+++ b/typing.cpp
@@ -115,7 +115,8 @@ AFn::constrain(TEnv& tenv, Constraints& c) const
subst = tsubst;
}
- c.constrain(tenv, this, new AType(*genericType));
+ AType* t = new AType(*genericType); // FIXME: deep copy
+ c.constrain(tenv, this, t);
}
void