| 1932 | } |
| 1933 | |
| 1934 | void AddMemberAccessNode(const char* pos, InplaceStr varName) |
| 1935 | { |
| 1936 | CodeInfo::lastKnownStartPos = pos; |
| 1937 | |
| 1938 | unsigned int hash = GetStringHash(varName.begin, varName.end); |
| 1939 | |
| 1940 | bool unifyTwo = false; |
| 1941 | // Get variable type |
| 1942 | TypeInfo *currentType = CodeInfo::nodeList.back()->typeInfo; |
| 1943 | // For member access, we expect to see a pointer to variable on top of the stack, so the shift to a member could be made |
| 1944 | // But if structure was, for example, returned from a function, then we have it on stack "by value", so we save it to a hidden variable and take a pointer to it |
| 1945 | if(currentType->refLevel == 0) |
| 1946 | { |
| 1947 | AddInplaceVariable(pos); |
| 1948 | currentType = CodeInfo::GetReferenceType(currentType); |
| 1949 | unifyTwo = true; |
| 1950 | } |
| 1951 | CheckForImmutable(currentType, pos); |
| 1952 | |
| 1953 | // Get type after dereference |
| 1954 | currentType = currentType->subType; |
| 1955 | // If it's still a dereference, dereference it again (so that "var.member" will work if var is a pointer) |
| 1956 | if(currentType->refLevel == 1) |
| 1957 | { |
| 1958 | CodeInfo::nodeList.push_back(new NodeDereference()); |
| 1959 | currentType = CodeInfo::GetDereferenceType(currentType); |
| 1960 | } |
| 1961 | // If it's an array, only member that can be accessed is .size |
| 1962 | if(currentType->arrLevel != 0 && currentType->arrSize != TypeInfo::UNSIZED_ARRAY) |
| 1963 | { |
| 1964 | if(hash != GetStringHash("size")) |
| 1965 | ThrowError(pos, "ERROR: array doesn't have member with this name"); |
| 1966 | CodeInfo::nodeList.pop_back(); |
| 1967 | CodeInfo::nodeList.push_back(new NodeNumber((int)currentType->arrSize, typeVoid)); |
| 1968 | currentType = typeInt; |
| 1969 | if(unifyTwo) |
| 1970 | AddExtraNode(); |
| 1971 | return; |
| 1972 | } |
| 1973 | |
| 1974 | // Find member |
| 1975 | TypeInfo::MemberVariable *curr = currentType->firstVariable; |
| 1976 | for(; curr; curr = curr->next) |
| 1977 | if(curr->nameHash == hash) |
| 1978 | break; |
| 1979 | // If member variable is not found, try searching for member function |
| 1980 | FunctionInfo *memberFunc = NULL; |
| 1981 | if(!curr) |
| 1982 | { |
| 1983 | // Construct function name in a for of Class::Function |
| 1984 | unsigned int hash = currentType->nameHash; |
| 1985 | hash = StringHashContinue(hash, "::"); |
| 1986 | hash = StringHashContinue(hash, varName.begin, varName.end); |
| 1987 | |
| 1988 | // Search for it |
| 1989 | HashMap<FunctionInfo*>::Node *func = funcMap.first(hash); |
| 1990 | if(!func) |
| 1991 | { |
no test coverage detected