Разрешение имен в «выражении пути» в компиляторе, например ‘person.name ‘

#java #compiler-construction #semantic-analysis

#java #компилятор-построение #семантический анализ

Вопрос:

Я некоторое время ломал голову над этим и не могу в этом разобраться.

У меня есть какой-то подобный код на моем c-подобном языке:

 struct PersonInfo {
    int numFriends;
    int favColour;
}

struct Person {
    PersonInfo info;
    string firstName;
    string lastName;
};

Person john;

john.info.numFriends; // <- specifically this part here!
  

Как я могу проверить, что выражение пути ‘john.info.numFriends’ является
правильно, т. е. все символы существуют. джон существует, джон является экземпляром
структуры Person, и мы получаем доступ к существующему полю ‘info’,
а также содержит поле ‘numFriends’.

Какой общий алгоритм / подход используется для выполнения такого типа проверки ошибок в компиляторах?

Комментарии:

1. Способ, которым Python (по общему признанию, как интерпретируемый язык, а не скомпилированный) делает это, заключается в том, что каждый раз, когда библиотека или модуль загружаются в память, им присваивается словарь ключевых слов для ссылок. Я полагаю, что проверка этого была бы такой: (1) посмотрите на Person ‘s dict (2) есть ли у него ключ info ? (3) Посмотрите на PersonInfo ‘s dict (4) есть ли у него ключ numFriends ? Итак, в принципе, просто рекурсивно проверьте, существует ли ссылка. Есть ли причина, по которой здесь не сработало бы?

2. @GreenCloakGuy Это имеет смысл, я просто не могу уловить суть помещения этого в код. У меня есть таблица символов, но все, что она делает, это сообщает мне, существует ли символ, например ‘john’. Я предполагаю, что мне нужно было бы сохранить тип ‘john’ (Person) рядом с символом? Кроме того, вы знаете, какая терминология для этого? Разрешение символов для a … выражение оператора dot?

Ответ №1:

Правило ввода для этого будет выглядеть примерно так: Для любого идентификатора memberName и любого выражения exp : Если exp это выражение типа, T где T это структура с именем элемента memberName , то выражение exp.memberName правильно типизировано и имеет тип T.memberName . В противном случае выражение неверно типизировано.

С точки зрения реализации, это не сильно отличается от реализации других частей средства проверки типов: Вы повторяете подвыражение, проверяете, имеет ли оно соответствующий тип, выдаете ошибку типа, если нет, и возвращаете правильный тип в противном случае. Единственное, что следует учитывать, это то, что вам нужно отслеживать, какие типы структур определяют, какие члены. Код может выглядеть примерно так:

 TypeInfo visitDotExpression(MemberAccess exp) {
    TypeInfo leftType = visit(exp.leftOperand);
    if (leftType.isStructType()) {
        if (leftType.memberTypes.containsKey(exp.memberName)) {
            return leftType.memberTypes.get(exp.memberName);
        } else {
            // produce a type error because the struct doesn't have a member
            // with the given name
        }             
    } else {
        // Produce a type error because left operand of `.` is not a struct
    }
}