Java - Генерация байт-кода JVM из реализации посетителя ANTLR 4 - PullRequest
0 голосов
/ 02 апреля 2020

Я разрабатываю язык, который был реализован в Java с помощью ANTLR 4 и его шаблона посетителя. Теперь то, что я хотел бы сделать, это из реализованного кода в шаблоне посетителя сгенерировать байт-код JVM, который впоследствии можно будет выполнить на виртуальной машине Java.

Так, например, с учетом следующего кода (давайте скажем, это язык, который я создаю):

int a = 1;
int b = 2;
int c = 3;
int d = 4;
if (a == b && c == d && a == d) {
    System.out.println("b = c");
} else {
    System.out.println("No!");
}

И у меня есть следующие функции, реализованные в шаблоне посетителей ANTLR 4, который обрабатывает различные инструкции моего языка (назначение, если, логическое и реляционное сравнение , et c):

// ...
void ifStatement(...) {
    // ...
}
// &&, ||, !
void logicalComparison(...) {
    // ...
}
// ==, !=, <=, >=, <, >
void relationalComparison(...) {
    // ...
}
//...

Проблема, с которой я сталкиваюсь, заключается в том, что когда я генерирую код для оператора if, мне нужен способ запомнить положение сравнений, чтобы я мог вернитесь после генерации оператора else, чтобы разместить его положение так, чтобы переход был возможен, если условия не выполняются.

Каков наилучший способ go о генерации байт-кода?

1 Ответ

1 голос
/ 02 апреля 2020

Вы можете использовать метки вместе с байтовым кодом goto. В зависимости от того, какой инструмент генерации кода вы используете, это может быть что-то вроде

// Visit your condition so its result is pushed on the stack

// Create three new labels
int iflab   = ++labels; // Label to jump to if the condition was true
int elselab = ++labels; // Label to jump to if the condition was false
int donelab = ++labels; // Label to jump to once done executing either branches

generate("ifne label" + iflab);
generate("goto label" + elselab);

generate("label" + iflab + ":");
// visit the statement needing to be executed if the condition was true
generate("goto label" + donelab);

generate("label" + elselab + ":");
// visit the statement needing to be executed if the condition was false (if there is one)
generate("goto label" + donelab);

println("label" + donelab + ":");
// You are done with this statement, keep visiting the following statements.

Это неоптимизировано (слишком много меток создано и идет), но это должно быть ясно. Метод генерирования просто записывает байт-код в файл, я использовал Jasmin при написании этого. Это должно быть похоже на использование ASM или любого другого инструмента байт-кода JVM.

...