FunctionObject* Curry::evaluate(Thread& t, FunctionObject* inObj, const Function::ArgumentVector& args, const vector<bool>& mask, bool dynamicDispatch) { // // Never do partial application on the result of a lambda // expression (its too difficult to archive). Instead do partial // evaluation. The good side is that there will never be more // than one level of indirection in multiple-curried lambda // expressions. the bad side is that there will be more overhead // upfront. // Process* p = t.process(); const Function* F = inObj->function(); const bool apply = !F->isLambda(); try { if (apply) { PartialApplicator evaluator(F, p, &t, args, mask, dynamicDispatch); const FunctionType* rt = evaluator.result()->type(); FunctionObject* outObj = new FunctionObject(rt); outObj->setDependent(inObj); outObj->setFunction(evaluator.result()); return outObj; } else { FunctionSpecializer evaluator(F, p, &t); evaluator.partiallyEvaluate(args, mask); const FunctionType* rt = evaluator.result()->type(); FunctionObject* outObj = new FunctionObject(rt); outObj->setFunction(evaluator.result()); return outObj; } } catch (Exception& e) { ProgramException exc(t); exc.message() = e.message(); exc.message() += " during partial "; exc.message() += (apply ? "application" : "evaluation"); exc.message() += " of "; exc.message() += F->name().c_str(); throw exc; } }
NODE_IMPLEMENTATION(DynamicPartialApplication::node, Pointer) { // // Never do partial application on the result of a lambda // expression (its too difficult to archive). Instead do // partial evaluation. The good side is that there will never // be more than one level of indirection in multiple-curried // lambda expressions. the bad side is that there will be // more overhead upfront. // Process* p = NODE_THREAD.process(); Context* c = p->context(); FunctionObject* f = NODE_ARG_OBJECT(1, FunctionObject); bool apply = f->function()->isLambda(); try { if (apply) { typedef PartialApplicator Generator; Generator::ArgumentVector args(f->function()->numArgs() + f->function()->numFreeVariables()); Generator::ArgumentMask mask(args.size()); for (int i=0; i < args.size(); i++) { mask[i] = NODE_THIS.argNode(i+2)->symbol() != c->noop(); if (mask[i]) { args[i] = NODE_ANY_TYPE_ARG(i+2); } } Generator evaluator(f->function(), p, &NODE_THREAD, args, mask); const FunctionType* rt = evaluator.result()->type(); assert(rt == NODE_THIS.argNode(0)->type()); FunctionObject* o = new FunctionObject(rt); o->setDependent(f); o->setFunction(evaluator.result()); NODE_RETURN(Pointer(o)); } else { typedef FunctionSpecializer Generator; Generator::ArgumentVector args(f->function()->numArgs() + f->function()->numFreeVariables()); Generator::ArgumentMask mask(args.size()); for (int i=0; i < args.size(); i++) { mask[i] = NODE_THIS.argNode(i+2)->symbol() != c->noop(); if (mask[i]) { args[i] = NODE_ANY_TYPE_ARG(i+2); } } Generator evaluator(f->function(), p, &NODE_THREAD); evaluator.partiallyEvaluate(args, mask); const FunctionType* rt = evaluator.result()->type(); assert(rt == NODE_THIS.argNode(0)->type()); FunctionObject* o = new FunctionObject(rt); o->setFunction(evaluator.result()); NODE_RETURN(Pointer(o)); } } catch (Exception& e) { ProgramException exc(NODE_THREAD); exc.message() = e.message(); exc.message() += " during partial "; exc.message() += (apply ? "application" : "evaluation"); exc.message() += " of "; exc.message() += f->function()->name().c_str(); throw exc; } }