java - Java - 从 ANTLR 4 访问者实现生成 JVM 字节码
问题描述
我正在开发一种在 ANTLR 4 及其访问者模式的帮助下用 Java 实现的语言。现在我想做的是从访问者模式中实现的代码中,生成以后可以在 Java 虚拟机上执行的 JVM 字节码。
因此,例如,给定以下代码(假设这是我正在创建的语言):
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 的访问者模式中实现了以下功能,它处理我的语言的不同指令(赋值、if、逻辑和关系比较等):
// ...
void ifStatement(...) {
// ...
}
// &&, ||, !
void logicalComparison(...) {
// ...
}
// ==, !=, <=, >=, <, >
void relationalComparison(...) {
// ...
}
//...
我遇到的问题是,当我为if
语句生成代码时,我需要一种方法来记住比较的位置,这样我就可以在生成else
语句后返回,放置它的位置,这样如果条件不满足。
生成字节码的最佳方法是什么?
解决方案
您可以将标签与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.
这是未优化的(创建和 goto 的标签太多),但应该很清楚。generate 方法只是将字节码写入文件,我在写这个时使用的是Jasmin 。使用ASM或任何其他 JVM 字节码工具应该是类似的。
推荐阅读
- html - Ngx 芯片填充
不显示动态提供的“名称”或“ID” - sql - Oracle SQL - 按每日、每周和每月汇总和分组数据。(缺少日期、星期和月份)
- android - 如何让搜索栏自动在录音机上移动?
- android - Expo - 使用“应用签名”证书构建 android app-bundle
- karate - 尝试在 Gatling 中运行空手道功能时出现超时异常
- python - 找到几个单词,如果删除一个字母将打印这两个单词
- ruby-on-rails - 如何在法拉第启用日志记录机构
- java - 反应原生 Amplify AWS 包与火力库冲突
- node.js - 从 mongodb 中的数组中提取数据,如果数据超过 10 分钟且临时为真
- sql - 获取薪水第二高的员工姓名