Skip to content

Instantly share code, notes, and snippets.

@galchinsky
Created November 10, 2012 17:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save galchinsky/4051770 to your computer and use it in GitHub Desktop.
Save galchinsky/4051770 to your computer and use it in GitHub Desktop.
MatchResultPtr matchInvoke(OverloadPtr overload,
ObjectPtr callable,
llvm::ArrayRef<TypePtr> argsKey)
{
initializePatterns(overload);
PatternReseter reseter(overload);
if (!unifyPatternObj(overload->callablePattern, callable))
return new MatchCallableError(overload->target, callable);
CodePtr code = overload->code;
if (code->hasVarArg) {
if (argsKey.size() < code->formalArgs.size()-1)
return new MatchArityError(code->formalArgs.size(), argsKey.size(), true);
}
else {
if (code->formalArgs.size() != argsKey.size())
return new MatchArityError(code->formalArgs.size(), argsKey.size(), false);
}
llvm::ArrayRef<FormalArgPtr> formalArgs = code->formalArgs;
unsigned varArgSize = argsKey.size()-formalArgs.size()+1;
for (unsigned i = 0, j = 0; i < formalArgs.size(); ++i) {
FormalArgPtr x = formalArgs[i];
if (x->varArg) {
if (x->type.ptr()) {
MultiStaticPtr types = new MultiStatic();
for (; j < varArgSize; ++j)
types->add(argsKey[i+j].ptr());
--j;
MultiPatternPtr pattern = overload->varArgPattern;
if (!unifyMulti(pattern, types))
return new MatchMultiArgumentError(formalArgs.size(), types, x);
} else {
j = varArgSize-1;
}
} else {
if (x->type.ptr()) {
PatternPtr pattern = overload->argPatterns[i];
if (!unifyPatternObj(pattern, argsKey[i+j].ptr()))
return new MatchArgumentError(i+j, argsKey[i+j], x);
}
}
}
EnvPtr staticEnv = new Env(overload->env);
llvm::ArrayRef<PatternVar> pvars = code->patternVars;
for (unsigned i = 0; i < pvars.size(); ++i) {
if (pvars[i].isMulti) {
MultiStaticPtr ms = derefDeep(overload->multiCells[i].ptr());
if (!ms)
error(pvars[i].name, "unbound pattern variable");
addLocal(staticEnv, pvars[i].name, ms.ptr());
}
else {
ObjectPtr v = derefDeep(overload->cells[i].ptr());
if (!v)
error(pvars[i].name, "unbound pattern variable");
addLocal(staticEnv, pvars[i].name, v.ptr());
}
}
reseter.reset();
/***********************************start from here***********************/
static llvm::StringMap<bool> cache;
if (code->predicate.ptr()) {
HiResTimer predTimer;
predTimer.start();
bool res;
llvm::SmallString<1024> buf;
llvm::raw_svector_ostream ostr(buf);
ostr << code->predicate;
llvm::StringMap<ObjectPtr>::iterator x = staticEnv->entries.begin();
for (; x != staticEnv->entries.end(); ++x) {
ostr << x->getKey();
ostr << x->second;
}
llvm::StringMap<bool>::iterator y = cache.find(ostr.str());
if (y != cache.end()){
res = y->second;}
else {
res = evaluateBool(code->predicate, staticEnv);
cache[ostr.str()] = res;
}
predTimer.stop();
if (compiling)
compilepredtime += predTimer.elapsedMillis();
else
loadpredtime += predTimer.elapsedMillis();
if (!res)
return new MatchPredicateError(code->predicate);
}
MatchSuccessPtr result = new MatchSuccess(
overload->callByName, overload->isInline, code, staticEnv,
callable, argsKey
);
for (unsigned i = 0, j = 0; i < formalArgs.size(); ++i) {
FormalArgPtr x = formalArgs[i];
if (x->varArg) {
result->varArgName = x->name;
result->varArgPosition = i;
for (; j < varArgSize; ++j) {
result->varArgTypes.push_back(argsKey[i+j]);
}
--j;
} else {
result->fixedArgNames.push_back(x->name);
result->fixedArgTypes.push_back(argsKey[i+j]);
}
}
if(!code->hasVarArg) result->varArgPosition = result->fixedArgNames.size();
return result.ptr();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment