Beispiel #1
0
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;
    }
}
Beispiel #2
0
NODE_IMPLEMENTATION(DynamicPartialEvaluate::node, Pointer)
{
    typedef FunctionSpecializer Generator;

    FunctionObject* f = NODE_ARG_OBJECT(1, FunctionObject);
    Generator::ArgumentVector args(f->function()->numArgs() +
                                   f->function()->numFreeVariables());
    Generator::ArgumentMask   mask(args.size());
    Process* p = NODE_THREAD.process();
    Context* c = p->context();

    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);
        }
    }

    try
    {
        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 evaluation of ";
        exc.message() += f->function()->name().c_str();
        throw exc;
    }
}
Beispiel #3
0
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;
    }
}