Как таблица символов связана со статическими цепочками и областью видимости?
Я сейчас изучаю основы языков программирования, но не могу понять, насколько я понимаю. Это не домашняя работа, а просто вопрос общей концепции.
В нашем классе мы говорили о статических цепях и дисплеях. Я думаю, что понимаю, зачем нам это нужно. Иначе, когда у нас есть вложенные методы, мы не можем понять, о какой переменной мы говорим, когда у нас есть вложенные методы.
Мой профессор также говорил о таблице символов. Мой вопрос: для чего используется таблица символов? Какое отношение это имеет к статическим цепям?
Я дам некоторые справки (пожалуйста, поправьте меня, если я ошибаюсь).
(Я собираюсь определить несколько вещей, чтобы облегчить объяснение)
Предположим, у нас есть этот код:
main(){
int i;
int j;
int k;
a(){
int i;
int j;
innerA(){
int i = 5;
print(i);
print(j);
print(k);
}
}
b(){
...
}
...
}
И этот стек:
| innerA |
| a |
| b |
| main |
-----------
Краткое описание статических цепочек как освежителей.
Статические цепочки используются, чтобы найти, какая переменная должна использоваться, когда переменные переопределяются внутри внутренней функции. В показанном выше стеке каждый кадр будет иметь указатель на метод, который его содержит. Так:
| innerA | \\ pointer to a
| a | \\ pointer to main
| b | \\ pointer to main
| main | \\ pointer to global variables
-----------
(Предполагая статическую область видимости, для динамической области видимости я думаю, что каждый кадр стека будет просто указывать на тот, что ниже)
Я думаю, что когда мы выполняем print(<something>)
внутри innerA
Метод это произойдет:
currentStackframe = innerAStackFrame;
while(true){
if(<something> is declared in currentStackFrame)
print(<something>);
break;
else{
currentStackFrame = currentStackFrame.containedIn();
}
}
Быстрое обновление таблицы символов
Я не совсем уверен, для чего таблица символов. Но вот как это выглядит:
Index is has value,
Value is reference.
__
| |
|--| --------------------------------------------------
| | --------------------> | link to next | name | type | scope level | other |
|--| --------------------------------------------------
| | |
|--| ---------------
| | |
|--| | --------------------------------------------------
| | -------> | link to next | name | type | scope level | other |
|--| --------------------------------------------------
| |
|--|
- ссылка на следующее - если более чем одна вещь имеет одинаковое хеш-значение, это ссылка
- name - имя элемента (примеры: i, j, a, int)
- тип - что это такое (примеры: переменная, функция, параметр)
- уровень охвата - не уверен на 100%, как это определяется. Я думаю что:
- 0 будут встроены
- 1 будет глобальным
- 2 будет основным методом
- 3 будет а и б
- 4 будет внутренняя
Просто чтобы переформулировать мои вопросы:
- Для чего используется таблица символов?
- Какое отношение это имеет к статическим цепям?
- Зачем нам нужны статические цепочки, поскольку информация о области видимости находится в таблице символов.
2 ответа
Обратите внимание, что "таблица символов" может означать две разные вещи: это может означать внутреннюю структуру, используемую компилятором для определения, какой псевдоним переменной имеет область видимости, или это может означать список символов, экспортируемых библиотекой своим пользователям при загрузке. время. Здесь вы используете первое определение.
Таблица символов используется для определения того, на какой адрес памяти ссылается пользователь, когда использует определенное имя. Когда вы говорите "х", какой псевдоним "х" вы хотите?
Причина, по которой вам нужно сохранять как статическую цепочку, так и таблицу символов, заключается в следующем: когда компилятору необходимо определить, какие переменные видимы в определенной области, он должен "снять маску" с переменных, ранее имевших псевдоним во внутренней области. Например, при переходе от innerA
вернуться к a
переменная i
меняет адрес своей памяти. То же самое происходит снова с a
в main
, Если компилятор не поддерживает статическую цепочку, он должен пройти через всю таблицу символов. Это дорого, если у тебя много имен. В случае статических цепочек компилятор просто просматривает текущий уровень, удаляет последнее определение каждой переменной, содержащейся в нем, а затем переходит по ссылке на одну область видимости. Если, с другой стороны, у вас не было таблицы символов, то при каждом доступе к переменной, не входящей в локальную область, компилятору придется обходить статическую цепочку.
Подводя итог, вы можете восстановить таблицу символов из статической цепочки, и наоборот. Но вы действительно хотите, чтобы и то и другое быстро выполнялось. Если вам не хватает таблицы символов, компиляция займет больше времени, потому что для каждой переменной доступа не в локальной области потребуется восхождение по статической цепочке. Если вам не хватает статической цепочки, компиляция займет больше времени, потому что для выхода из области потребуется пройти таблицу символов, чтобы удалить несуществующие записи.
Кстати, если вы еще не используете прагматику языка программирования Майкла Скотта, вам стоит взглянуть на это. На сегодняшний день это лучший учебник по этой теме, который я видел.
Это, очевидно, относится к какой-то конкретной реализации класса, и чтобы понять это, я настоятельно рекомендую поговорить с кем-то, связанным с классом.
Таблица символов - это то, что переводит идентификаторы исходного кода в то, что может использовать компилятор. Хранит необходимые описания. Как правило, он используется на протяжении всего процесса компиляции. Упоминаемый вами "тип" выглядит так, как будто он предназначен для синтаксического анализа, и, несомненно, будет больше записей (в "другом") для последующих этапов.
Трудно понять, как они связаны со статическими цепочками или зачем они нужны, поскольку вы даже не знаете, что такое "уровень охвата". Тем не менее, обратите внимание, что оба a()
а также b()
может иметь переменную i
Кажется, вы думаете, что у них одинаковый уровень охвата, поэтому вам нужно что-то для их дифференциации.
Кроме того, статическая цепочка часто является оптимизацией, поэтому компилятор знает, какие записи таблицы символов следует принять. Без статической цепочки компилятор должен был бы выполнить некоторые поиски, чтобы отклонить запись в b
за то, что встречается в innerA
,
Чтобы получить что-то более полезное, вам нужно будет объяснить больше о том, что происходит (я настоятельно рекомендую поговорить с инструктором, ТП или кем-то еще) и, возможно, задать более конкретные вопросы.