基于java的脚本语言hair的开发思路3-执行

执行

经过上面的操作,我们已经根据程序生成了一个抽象语法树。此时我们需要让程序达到其预期的结果。即需要我们翻译为Java可执行的代码。实际上执行的过程很简单,既然我们已经生成了抽象语法树。我们只需要将每个节点的结果得到,最后得到根节点的结果,即为该程序的结果。所以这实际上也是一个树的遍历工作,从左边的叶节点开始遍历。依次得到上层的非叶节点的值。

针对不同的节点,我们的实现方法不同,但是我们都将其定义为eval方法,意为evaluate,即得到结果。

下面简单介绍几种类型的节点的实现:

实现

基本节点

针对一些基本节点,比如

二元运算:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
* For a binary operation, the operation symbol will be considered to process different operation.
*/
public Object eval(Environment env) {
String op = operator();
if ("=".equals(op)) {
ASTree rightTree = right();
Object rightVal = rightTree.eval(env);
return computeAssign(env, rightVal);
}
else {
Object left = left().eval(env);
Object right = right().eval(env);
return computeOp(left, op, right);
}
}

if语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
* For a if statement, condition will eval first to decide whether the if block be executed.
*/
public Object eval(Environment env) {
Object c = condition().eval(env);
if (c instanceof Integer && ((Integer)c).intValue() != FALSE)
return thenBlock().eval(env);
else {
ASTree b = elseBlock();
if (b == null)
return 0;
else
return b.eval(env);
}
}

实际上这里就是递归的执行元素的eavl方法,实际上就是遍历ast的过程。

注意这里就是脚本语言与编译语言的区别,脚本语言会直接遍历ast执行。而预编译语言会先对源码进行编译,生成可执行程序或中间二进制代码,比如C语言编译会生成对应平台的可执行程序。java会通过Java虚拟机产生javac二进制文件,以此来解决跨平台的问题。

正是因为这个预编译的过程中,会对源码进行一定的分析和运算,将可运算先运算出来,使得预编译程序的效率会远高于脚本语言。

Powered by Hexo and Hexo-theme-hiker

Copyright © 2019 - 2024 My Wonderland All Rights Reserved.

UV : | PV :