Как работает компиляция циклических зависимостей?
Я сделал пример на Java, но я думаю (не протестирован), что он работает в другом (все?) языки.
у вас есть 2 файла. Во-первых, M.java
:
public class MType {
XType x;
MType() {x = null;}
}
во-вторых, другой файл (в том же каталоге), XType.java
:
public class XType {
MType m;
public XType(MType m) {this.m = m;}
}
Ok это плохое программирование, но если вы запустите javac XType
он компилирует: компилирует даже MType
, потому что XType
в ней нуждается. Но... MType
должен XType
... как это работает? Как компилятор знает, что такое происходит?
Я хотел бы знать, как компилятор (javac или любые другие компиляторы, которые вы знаете) управляет этой ситуацией, а не как ее избежать.
Я спрашиваю, потому что я пишу прекомпилятор, и я хотел бы управлять этой ситуацией.
2 ответов
вам нужно взять 2-пасс, или multi-pass подход:
языки, такие как Java, требуют многопроходного компилятора, так как определение x не требуется перед использованием:
public class Example {
public static void main(String [] args) {
assert(x==0);
x++;
assert(x==1);
}
static int x=0;
}
существуют различные подходы, например, вы можете сделать следующее:
первый проход может искать все объявления переменных, второй-объявления методов и т. д. пока последний проход не использует всю эту информацию для скомпилируйте окончательный код.
первый файл не должен ничего знать о XType, кроме того, что это тип, и аналогично для MType во втором файле. Кроме того, в Java все объекты фактически имеют одинаковый размер (потому что все доступно через ссылки), поэтому размер объекта не нужен. Это не так на других языках - ваш код, как он стоит, не будет компилироваться на C++, например (синтаксис языка отдельно).