Exemple #1
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;
    }
}
Exemple #2
0
NODE_IMPLEMENTATION(Curry::node, Pointer)
{
    Process*                 p = NODE_THREAD.process();
    Context*                 c = p->context();
    FunctionObject*          o = NODE_ARG_OBJECT(1, FunctionObject);
    bool                     d = NODE_ARG(2, bool);
    const Function*          F = o->function();
    Function::ArgumentVector args(F->numArgs() + F->numFreeVariables());
    vector<bool>             mask(args.size());

    for (int i=0, s=args.size(); i < s; i++)
    {
        mask[i] = NODE_THIS.argNode(i+3)->symbol() != c->noop();

        if (mask[i])
        {
            args[i] = NODE_ANY_TYPE_ARG(i+3);
        }
    }

    NODE_RETURN(Pointer(evaluate(NODE_THREAD, o, args, mask, d)));
}
Exemple #3
0
bool ExecutionContext::deleteProperty(String *name)
{
    Scope scope(this);
    bool hasWith = false;
    for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
        if (ctx->d()->type == Type_WithContext) {
            hasWith = true;
            WithContext *w = static_cast<WithContext *>(ctx);
            if (w->d()->withObject->hasProperty(name))
                return w->d()->withObject->deleteProperty(name);
        } else if (ctx->d()->type == Type_CatchContext) {
            CatchContext *c = static_cast<CatchContext *>(ctx);
            if (c->d()->exceptionVarName->isEqualTo(name))
                return false;
        } else if (ctx->d()->type >= Type_CallContext) {
            CallContext *c = static_cast<CallContext *>(ctx);
            FunctionObject *f = c->d()->function;
            if (f->needsActivation() || hasWith) {
                uint index = f->function()->internalClass->find(name);
                if (index < UINT_MAX)
                    // ### throw in strict mode?
                    return false;
            }
            if (c->d()->activation && c->d()->activation->hasProperty(name))
                return c->d()->activation->deleteProperty(name);
        } else if (ctx->d()->type == Type_GlobalContext) {
            GlobalContext *g = static_cast<GlobalContext *>(ctx);
            if (g->d()->global->hasProperty(name))
                return g->d()->global->deleteProperty(name);
        }
    }

    if (d()->strictMode)
        throwSyntaxError(QStringLiteral("Can't delete property %1").arg(name->toQString()));
    return true;
}
Exemple #4
0
ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Object *&base)
{
    Scope scope(this);
    ScopedValue v(scope);
    base = (Object *)0;
    name->makeIdentifier();

    if (name->equals(d()->engine->id_this.getPointer()))
        return d()->callData->thisObject.asReturnedValue();

    bool hasWith = false;
    bool hasCatchScope = false;
    for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
        if (ctx->d()->type == Type_WithContext) {
            Object *w = static_cast<WithContext *>(ctx)->d()->withObject;
            hasWith = true;
            bool hasProperty = false;
            v = w->get(name, &hasProperty);
            if (hasProperty) {
                base = w;
                return v.asReturnedValue();
            }
            continue;
        }

        else if (ctx->d()->type == Type_CatchContext) {
            hasCatchScope = true;
            CatchContext *c = static_cast<CatchContext *>(ctx);
            if (c->d()->exceptionVarName->isEqualTo(name))
                return c->d()->exceptionValue.asReturnedValue();
        }

        else if (ctx->d()->type >= Type_CallContext) {
            QV4::CallContext *c = static_cast<CallContext *>(ctx);
            FunctionObject *f = c->d()->function;
            if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
                uint index = f->function()->internalClass->find(name);
                if (index < UINT_MAX) {
                    if (index < c->d()->function->formalParameterCount())
                        return c->d()->callData->args[c->d()->function->formalParameterCount() - index - 1].asReturnedValue();
                    return c->d()->locals[index - c->d()->function->formalParameterCount()].asReturnedValue();
                }
            }
            if (c->d()->activation) {
                bool hasProperty = false;
                v = c->d()->activation->get(name, &hasProperty);
                if (hasProperty) {
                    if (ctx->d()->type == Type_QmlContext)
                        base = c->d()->activation;
                    return v.asReturnedValue();
                }
            }
            if (f->function() && f->function()->isNamedExpression()
                && name->equals(f->function()->name()))
                return c->d()->function->asReturnedValue();
        }

        else if (ctx->d()->type == Type_GlobalContext) {
            GlobalContext *g = static_cast<GlobalContext *>(ctx);
            bool hasProperty = false;
            v = g->d()->global->get(name, &hasProperty);
            if (hasProperty)
                return v.asReturnedValue();
        }
    }
    ScopedValue n(scope, name);
    return throwReferenceError(n);
}
Exemple #5
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;
    }
}