手拉手教你实现一门编程语言|手拉手教你实现一门编程语言 Enkel, 系列 17
本文系 Creating JVM language 翻译的第 17 篇。源码 Github
原文中的代码和原文有不一致的地方均在新的代码仓库中更正过,建议参考新的代码仓库。
字节码 - JVM 语言的通用描述 所有基于 JVM 的编程语言最终被编译到字节码,然后被虚拟机加载解释执行,这意味着虚拟机并不知道是什么语言生成了字节码。只要类在 classpath 上。
这为 Enkel 调用 Java 库以及其他框架提供了具体可能性。
查找类方法和构造器 【手拉手教你实现一门编程语言|手拉手教你实现一门编程语言 Enkel, 系列 17】为了能够引用到其他类,有如下两种选择:
- 运行时 相信程序员并且不检验生成的字节码,这可能会导致如果 classpath 不存在,JVM 会抛出异常
- 编译时 在生成字节码之前验证。如果验证失败,会终止编译过程。
public class ClassPathScope { public Optional getMethodSignature(Type owner, String methodName, List arguments) {
try {
Class> methodOwnerClass = owner.getTypeClass();
Class>[] params = arguments.stream()
.map(Type::getTypeClass).toArray(Class>[]::new);
Method method = methodOwnerClass.getMethod(methodName,params);
return Optional.of(ReflectionObjectToSignatureMapper.fromMethod(method));
} catch (Exception e) {
return Optional.empty();
}
} public Optional getConstructorSignature(String className, List arguments) {
try {
Class> methodOwnerClass = Class.forName(className);
Class>[] params = arguments.stream()
.map(Type::getTypeClass).toArray(Class>[]::new);
Constructor> constructor = methodOwnerClass.getConstructor(params);
return Optional.of(ReflectionObjectToSignatureMapper.fromConstructor(constructor));
} catch (Exception e) {
return Optional.empty();
}
}
}
如果方法或者构造器不存在,会抛异常并且终止编译:
//Scope.java
return new ClassPathScope().getMethodSignature(owner.get(), methodName, argumentsTypes)
.orElseThrow(() -> new MethodSignatureNotFoundException(this,methodName,arguments));
这种方式看起来更加安全,但是同时也会慢一点。所有的依赖需要在编译的时候通过反射的方式来解决依赖。
示例 调用其他 Enkel 类
下面我们从 Client 类中调用 Library 的方法:
Client {
start {
print "Client: Calling my own 'Library' class:"
var myLibrary = new Library()
var addition = myLibrary.add(5,2)
print "Client: Result returned from 'Library.add' = " + addition
}
}
Library {int add(int x,int y) {
print "Library: add() method called"
return x+y
}}
这里我们需要先编译 Library(我们目前不支持多文件同时编译),否则 Client 没办法编译通过。
kuba@kuba-laptop:~/repos/Enkel-JVM-language$ java -classpath compiler/target/compiler-1.0-SNAPSHOT-jar-with-dependencies.jar:. com.kubadziworski.compiler.Compiler EnkelExamples/ClassPathCalls/Library.enk
kuba@kuba-laptop:~/repos/Enkel-JVM-language$ java -classpath compiler/target/compiler-1.0-SNAPSHOT-jar-with-dependencies.jar:. com.kubadziworski.compiler.Compiler EnkelExamples/ClassPathCalls/Client.enk
kuba@kuba-laptop:~/repos/Enkel-JVM-language$ java Client
Client: Calling my own 'Library' class:
Library: add() method called
Client: Result returned from 'Library.add' = 7
调用 Java 的 API
start {
var someString = "someString"
print someString + " to upper case : " +someString.toUpperCase()
}}
$ java Client
cos to upper case = COS
推荐阅读
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- MybatisPlus使用queryWrapper如何实现复杂查询
- python学习之|python学习之 实现QQ自动发送消息
- 孩子不是实现父母欲望的工具——林哈夫
- opencv|opencv C++模板匹配的简单实现
- Node.js中readline模块实现终端输入
- java中如何实现重建二叉树
- 人脸识别|【人脸识别系列】| 实现自动化妆
- paddle|动手从头实现LSTM
- pytorch|使用pytorch从头实现多层LSTM