常量折叠是其中一种被很多现代编译器使用的编译器最优化技术。常量折叠是在编译时间简单化常量表达的一个过程。简单来说就是将常量表达式计算求值,并用求得的值来替换表达式,放入常量表。可以算作一种编译优化。
也就是我们最早举例子的时候说的,将2,3放入栈中,+ 进来的时候,2 3取出来进行运算,然后将运算结果放入栈中。
def constant_fold(code):
while True:
# 指令中找到两个连续的数字以及一个运算符
for i, (a, b, op) in enumerate(zip(code, code[1:], code[2:])):
if isinstance(a, int) and isinstance(b, int) and op in {"+", "-", "*", "/"}:
m = Machine((a, b, op))
m.run()
code[i:i+3] = [m.top()]
print("Constant-folded %s%s%s to %s" % (a, op, b, m.top()))
break
else:
break
return code
“读取-求值-输出”循环(英语:Read-Eval-Print Loop,简称REPL)是一个简单的,交互式的编程环境。这个词常常用于指代一个Lisp的交互式开发环境,但也能指代命令行的模式和例如APL、BASIC、Clojure、F#、Haskell、J、Julia、Perl、PHP、Prolog、Python、R、Ruby、Scala、Smalltalk、Standard ML、Tcl、Javascript这样的编程语言所拥有的类似的编程环境。这也被称做交互式顶层构件(interactive toplevel)。
read-eval-print loop
这个名字来自于以下几个Lisp用来实现这种机制的内置函数:
读入函数接收一个来自于用户的表达式,将其解析成数据结构并存入内存。例如,用户可能会输入一个s-表达式(+ 1 2 3),这句话会被解析成一个包含四个元素的链表。
求值函数负责处理内部的数据结构并对其求值。在Lisp中,求一个以函数名开头的s-表达式意味着对接下来的参数调用那个函数。所以函数"+"被在参数1 2 3上调用,产生结果6。
输出函数接受求值结果,并呈现将其给用户。尽管当前的结果“6”并不具有复杂的格式,但如果是一个较为复杂的表达式,那么它将会被精心处理,以便于更方便地被理解。
代码应当这样写:
def repl():
print('Hit CTRL+D or type "exit" to quit.')
while True:
try:
source = raw_input("> ")
code = list(parse(source))
code = constant_fold(code)
Machine(code).run()
except (RuntimeError, IndexError) as e:
print("IndexError: %s" % e)
except KeyboardInterrupt:
print("\nKeyboardInterrupt")
这样,基本上的我们就完成了一个简单的解释器,实际上它的能力很弱小,但是作为一个锻炼思考的方式,是一个不错的实践。接下来,可以给这个解释器添加更多的功能。
另外,推荐几个其他的文章:
用 Python 从零开始写一个简单的解释器
一起来写个简单的解释器
如何使用Python编写一个Lisp解释器
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-34020-5.html
呵呵三个霉菌的狗
只是为利益的流氓而已
那么物价上涨减去利率
是因为广东人吃蛆