Beispiel #1
0
bool Type::isNativeMemberPure(bool ignoreStaticMembers)
{
    //if (!attr.isNative)
    //	return false;

    for (UTsize i = 0; i < members.size(); i++)
    {
        MemberInfo *memberInfo = members.at(i);

        if (ignoreStaticMembers && memberInfo->isStatic())
        {
            continue;
        }

        if (memberInfo->isConstructor())
        {
            ConstructorInfo *cinfo = (ConstructorInfo *)memberInfo;
            if (cinfo->defaultConstructor)
            {
                continue;
            }
        }

        if (memberInfo->isConstructor() || memberInfo->isMethod())
        {
            if (!((MethodBase *)memberInfo)->isNative())
            {
                return false;
            }
        }

        if (memberInfo->isProperty())
        {
            PropertyInfo *pinfo = (PropertyInfo *)memberInfo;
            if (pinfo->getGetMethod() && !pinfo->getGetMethod()->isNative())
            {
                return false;
            }
            if (pinfo->getSetMethod() && !pinfo->getSetMethod()->isNative())
            {
                return false;
            }
        }

        if (memberInfo->isField())
        {
            if (!memberInfo->getOrdinal())
            {
                return false;
            }
        }
    }

    if (baseType)
    {
        return baseType->isNativeMemberPure();
    }

    return true;
}
Beispiel #2
0
PropertyInfo *Type::findPropertyInfoByName(const char *name)
{
    MemberInfo *mi = findMember(name);

    if (mi && mi->isProperty())
    {
        return (PropertyInfo *)mi;
    }

    return NULL;
}
Beispiel #3
0
void Type::findMembers(const MemberTypes& memberTypes,
                       utArray<MemberInfo *>& membersOut, bool includeBases, bool includePropertyGetterSetters)
{
    if (!includeBases)
    {
        membersOut.clear();
    }

    for (size_t i = 0; i < members.size(); i++)
    {
        MemberInfo *m = members.at((int)i);

        if (m->isConstructor() && memberTypes.constructor)
        {
            membersOut.push_back(m);
        }

        if (m->isMethod() && memberTypes.method)
        {
            membersOut.push_back(m);
        }

        if (m->isField() && memberTypes.field)
        {
            membersOut.push_back(m);
        }

        if (m->isProperty() && memberTypes.property)
        {
            membersOut.push_back(m);

            if (includePropertyGetterSetters)
            {
                PropertyInfo *p = (PropertyInfo *)m;

                if (p->getter && (p->getter->getDeclaringType() == p->getDeclaringType()))
                {
                    membersOut.push_back(p->getter);
                }

                if (p->setter && (p->setter->getDeclaringType() == p->getDeclaringType()))
                {
                    membersOut.push_back(p->setter);
                }
            }
        }
    }

    if (baseType && includeBases)
    {
        baseType->findMembers(memberTypes, membersOut, true, includePropertyGetterSetters);
    }
}
Beispiel #4
0
static int lsr_instanceindex(lua_State *L)
{
    // we hit the instance index metamethod when we can't find a value
    // in the instance's table, this is a native or a bound method

    lua_rawgeti(L, 1, LSINDEXTYPE);
    Type *type = (Type *)lua_topointer(L, -1);
    lua_pop(L, 1);

    lmAssert(type, "Missing type on instance index");

    if (lua_isnumber(L, 2))
    {
        int ordinal = (int)lua_tonumber(L, 2);

        MemberInfo *mi = type->getMemberInfoByOrdinal(ordinal);

        lmAssert(mi, "Unable to find ordinal %s %i", type->getFullName().c_str(), ordinal);

        if (mi->isStatic())
        {
            lua_rawgeti(L, 1, LSINDEXCLASS);
            lua_replace(L, 1);
            lua_gettable(L, 1);
            return 1;
        }

        // we need to look in the class, the result will be cached to instance

        MethodBase *method = NULL;

        if (mi->isMethod())
        {
            method = (MethodBase *)mi;
        }

        if (method)
        {
            lua_rawgeti(L, 1, LSINDEXCLASS);
            assert(!lua_isnil(L, -1));

            int clsIdx = lua_gettop(L);

            if (!method->isStatic())
            {
                if (method->isFastCall())
                {
                    // get the fast call structure pointer
                    lua_pushlightuserdata(L, method->getFastCall());

                    // get the the "this"
                    if (lua_type(L, 1) == LUA_TTABLE)
                    {
                        lua_rawgeti(L, 1, LSINDEXNATIVE);
                    }
                    else
                    {
                        lua_pushvalue(L, 1);
                    }

                    // unwrap this
                    Detail::UserdataPtr *p1 = (Detail::UserdataPtr *)lua_topointer(L, -1);
                    lua_pushlightuserdata(L, p1->getPointer());
                    lua_replace(L, -2);

                    lua_pushnumber(L, ordinal);
                    lua_gettable(L, clsIdx);
                }
                else
                {
                    lua_pushlightuserdata(L, method);
                    lua_pushvalue(L, 1);
                    lua_pushnumber(L, ordinal);
                    lua_gettable(L, clsIdx);
                }

                assert(!lua_isnil(L, -1));

                int nup = 3;

                int fd = method->getFirstDefaultParm();
                if (fd != -1)
                {
                    utString dname;
                    if (method->isConstructor())
                    {
                        dname = "__ls_constructor";
                    }
                    else
                    {
                        dname = method->getName();
                    }

                    dname += "__default_args";

                    lua_getfield(L, clsIdx, dname.c_str());

                    int dargs = lua_gettop(L);

                    for (int i = fd; i < method->getNumParameters(); i++)
                    {
                        lua_pushnumber(L, i);
                        lua_gettable(L, dargs);
                        nup++;
                    }

                    lua_remove(L, dargs);
                }

                // check for fast path
                if (method->isFastCall())
                {
                    if (method->getNumParameters())
                    {
                        // setter
                        lua_pushcclosure(L, lsr_method_fastcall_set, nup);
                    }
                    else
                    {
                        // getter
                        lua_pushcclosure(L, lsr_method_fastcall_get, nup);
                    }
                }
                else
                {
                    // bind the instance method
                    lua_pushcclosure(L, lsr_method, nup);
                }

                // store to method lookup, this is worth it
                // as only happens once per instance method bind
                // and can now lookup MethodBase on any function
                // in one table lookup
                lua_rawgeti(L, LUA_GLOBALSINDEX, LSINDEXMETHODLOOKUP);
                lua_pushvalue(L, -2);
                lua_pushlightuserdata(L, method);
                lua_rawset(L, -3);
                lua_pop(L, 1);

                // cache to instance
                lua_pushvalue(L, -1);
                lua_rawseti(L, 1, ordinal);


                return 1;
            }
            else
            {
                assert(0);
            }
        }

        FieldInfo *field = NULL;

        if (mi->isField())
        {
            field = (FieldInfo *)mi;
        }

        if (field && field->isNative())
        {
            // for primitive fields, we could generate
            // a direct lookup in the LSINDEXNATIVE table
            // in bytecode gen, however this only saves for
            // native vars and not properties
            // (which should be using fast path anyway and complicates bytecode)

            // get the native userdata
            lua_rawgeti(L, 1, LSINDEXNATIVE);
            lua_pushnumber(L, field->getOrdinal());
            lua_gettable(L, -2);

            // if we are native we need to wrap
            if (lua_isuserdata(L, -1))
            {
                lualoom_pushnative_userdata(L, field->getType(), -1);
            }

            return 1;
        }

        // if we get here the value actually is null
        lua_pushnil(L);
        return 1;
    }

    // if we hit here, this should be an interface access where we have to
    // look up by string (and cache as these are only ever instance methods)

    const char *name  = lua_tostring(L, 2);
    const char *pname = name;
    MemberInfo *mi    = NULL;

    if (!strncmp(name, "__pget_", 7))
    {
        pname = &name[7];
        mi    = type->findMember(pname, true);
        lmAssert(mi && mi->isProperty(), "Could not find property getter for '%s' on type '%s'", pname, type->getFullName().c_str());
        mi = ((PropertyInfo *)mi)->getGetMethod();
        lmAssert(mi, "Found NULL property getter for '%s' on type '%s'", pname, type->getFullName().c_str());
    }
    else if (!strncmp(name, "__pset_", 7))
    {
        pname = &name[7];
        mi    = type->findMember(pname, true);
        lmAssert(mi && mi->isProperty(), "Could not find property setter for '%s' on type '%s'", pname, type->getFullName().c_str());
        mi = ((PropertyInfo *)mi)->getSetMethod();
        lmAssert(mi, "Found NULL property setter for '%s' on type '%s'", pname, type->getFullName().c_str());
    }
    else
    {
        mi = type->findMember(name, true);
        lmAssert(mi, "Unable to find member '%s' via string on instance of type %s", name, type->getFullName().c_str());
        assert(mi);
        assert(mi->isMethod());
        assert(mi->getOrdinal());
    }

    lua_pushnumber(L, mi->getOrdinal());
    lua_gettable(L, 1);
    lua_pushstring(L, name);
    lua_pushvalue(L, -2);
    lua_rawset(L, 1);

    return 1;
}