Beispiel #1
0
Expression *TypeCompiler::visit(CallExpression *call)
{
    MethodBase *methodBase = call->methodBase;

    call->function->visitExpression(this);

    // check whether we're calling a methodbase
    if (methodBase)
    {
        lmAssert(methodBase->isMethod(), "Non-method called");

        MethodInfo *method = (MethodInfo *)methodBase;
        generateCall(&call->function->e, call->arguments, method);

        call->e = call->function->e;
    }
    else
    {
        lmAssert(call->function->type, "Untyped call");

        // if we're calling a delegate we need to load up the call method
        if (call->function->type->isDelegate())
        {
            MethodInfo *method = (MethodInfo *)call->function->type->findMember("call");
            lmAssert(method, "delegate with no call method");

            ExpDesc right;
            BC::initExpDesc(&right, VKNUM, 0);
            right.u.nval = method->getOrdinal();

            BC::expToNextReg(cs->fs, &call->function->e);
            BC::expToNextReg(cs->fs, &right);
            BC::expToVal(cs->fs, &right);
            BC::indexed(cs->fs, &call->function->e, &right);

            generateCall(&call->function->e, call->arguments, NULL);
            call->e = call->function->e;
        }
        else
        {
            // we're directly calling a local, instance (bound), or static method of type Function
            generateCall(&call->function->e, call->arguments, NULL);
            call->e = call->function->e;
        }
    }

    return call;
}
PropertyInfo *PropertyInfoReader::deserializePropertyInfo(Type   *declaringType,
                                                          json_t *json)
{
    PropertyInfo *pi = new PropertyInfo();

    MemberInfoReader::deserialize(pi, json);

    // handle attr
    json_t *marray = json_object_get(json, "propertyattributes");

    for (size_t i = 0; i < json_array_size(marray); i++)
    {
        utString modifier = json_string_value(json_array_get(marray, i));

        if (modifier == "static")
        {
            pi->attr.isStatic = true;
        }
        else if (modifier == "public")
        {
            pi->attr.isPublic = true;
        }
        else if (modifier == "private")
        {
            pi->attr.isPrivate = true;
        }
        else if (modifier == "protected")
        {
            pi->attr.isProtected = true;
        }
        else if (modifier == "native")
        {
            pi->attr.isNative = true;
        }
    }

    utString stype = json_string_value(json_object_get(json, "type"));
    if (stype.size() > 0)
    {
        // a shortcut?
        pi->type =
            declaringType->getModule()->getAssembly()->getLuaState()->getType(
                stype.c_str());
        assert(pi->type);
    }

    json_t *getter = json_object_get(json, "getter");
    json_t *setter = json_object_get(json, "setter");

    if (getter)
    {
        MethodBase *m = NULL;
        m = MethodReader::deserializeMethodInfo(declaringType, getter);
        assert(m->isMethod());
        pi->getter = (MethodInfo *)m;

        m->setPropertyInfo(pi);
    }

    if (setter)
    {
        MethodBase *m = NULL;
        m = MethodReader::deserializeMethodInfo(declaringType, setter);
        assert(m->isMethod());
        pi->setter = (MethodInfo *)m;

        m->setPropertyInfo(pi);
    }

    json_t *ttypes = json_object_get(json, "templatetypes");
    if (ttypes && json_is_object(ttypes))
    {
        TemplateInfo *info = MemberInfoReader::readTemplateTypeInfo(ttypes);
        assert(info);
        info->resolveTypes(Assembly::getAssembly(declaringType)->getLuaState());
        pi->setTemplateInfo(info);
    }


    return pi;
}
Beispiel #3
0
/*
 * Static methods use the lsr_method closure which is generated at class initialization time
 * Instance methods are bound to a generated lsr_method closure the first time the method is referenced (at runtime)
 * lsr_method is a thin wrapper which handles catching native calls for profiling, default arguments, etc
 */
int lsr_method(lua_State *L)
{
    int nargs = lua_gettop(L);

    MethodBase *method = (MethodBase *)lua_topointer(L, lua_upvalueindex(1));

    bool staticCall = method->isStatic();

    if (staticCall)
    {
        lua_pushvalue(L, lua_upvalueindex(2));
        lua_insert(L, 1); // method
    }
    else
    {
        lua_pushvalue(L, lua_upvalueindex(2));
        lua_insert(L, 1); // this (can be a loomscript table or luabridge userdata

        lua_pushvalue(L, lua_upvalueindex(3));
        lua_insert(L, 1); // method
    }


    int dargs = nargs;

    int fidx            = method->getFirstDefaultParm();
    int varArgIdx       = method->getVarArgIndex();
    int varArgVectorIdx = lua_gettop(L);

    // don't consider the varargs in when
    // checking whether we need to insert default arguments
    if ((fidx != -1) && (varArgIdx != -1))
    {
        dargs--;
    }

    if (dargs < method->getNumParameters())
    {
        // TODO: Report line numbers LOOM-603
        // if we have var args and not enough parameters, VM will insert null for ...args value
        // otherwise, we have a compiler error
        if (varArgIdx < 0)
        {
            lmAssert(fidx >= 0, "Method '%s::%s' called with too few arguments.", method->getDeclaringType()->getFullName().c_str(), method->getStringSignature().c_str());
        }

        bool inserted = false;
        for (int i = dargs; i < method->getNumParameters(); i++)
        {
            if (i == varArgIdx)
            {
                break;
            }

            lua_pushvalue(L, lua_upvalueindex(i - fidx + (staticCall ? 3 : 4)));
            inserted = true;
            nargs++;
        }

        // if we inserted *and* have var args, we
        // need to shift the var args to the end
        if (inserted && (varArgIdx != -1))
        {
            lua_pushvalue(L, varArgVectorIdx);
            lua_remove(L, varArgVectorIdx);
        }
    }

    LSLuaState *ls = LSLuaState::getLuaState(L);

    // error handling
    lua_getglobal(L, "__ls_traceback");
    lua_insert(L, 1);

    if (lua_pcall(L, nargs + (staticCall ? 0 : 1), LUA_MULTRET, 1))
    {
        ls->triggerRuntimeError("Error calling %s:%s", method->getDeclaringType()->getFullName().c_str(), method->getName());
    }

    // get rid of the traceback
    lua_remove(L, 1);

    int nreturn = lua_gettop(L);

    if (nreturn == 1)
    {
        if (method->isNative() && method->isMethod() && lua_isuserdata(L, -1))
        {
            lualoom_pushnative_userdata(L, ((MethodInfo *)method)->getReturnType(), -1);
        }
    }

    return nreturn;
}