从零用Go实现一个python简单解释器

Hana ·
更新时间:2024-09-21
· 914 次阅读

编译型语言和解释型语言 和其他编译型语言类似,要 执行python代码 会经历几个步骤。

在这里插入图片描述
分别是这三个步骤:
1. 词法分析
2. 语法解析
3. 编译
解释型语言区别于编译型型语言,他有一个很大的缺点由于不需要事前先编译成机器码,而是在动态执行的时候在解释器运行期间那一条解释一条,这些被解释完成的代码 会在内存中存放 python中称为 code object(代码对象),写python的小伙伴应该经常能看见 个__pycache__ 这个文件夹 里面或有一些 和代码相对应的.pyc相对应的文件。这些就是解释器将内存里的 代码对象保存到 本地磁盘 以便下一次调用是能够复用这些被编译过的代码,加快编译器的执行效率。当我们外部引入一些不需要修改的包,直接使用编译好的代码对象,解释器就能加快速度。当然当我们对代码修改时他会检查 最近修改时间,和pyc生成时间 如果发生改变 那么不会使用原来的pyc,但并不是所有的文件python解释器都认为值得缓存 代码对象.pyc 。另外解释性语言 是没法检查一些例如类型错误 他只能在执行的时候才能发现。
动态类型语言:动态类型语言是指在运行期间才去做数据类型检查的语言,也就是说,在用动态类型的语言编程时,永远也不用给任何变量指定数据类型,该语言会在你第一次赋值给变量时,在内部将数据类型记录下来。Python和Ruby就是一种典型的动态类型语言
静态类型语言:静态类型语言与动态类型语言刚好相反,它的数据类型是在编译其间检查的,也就是说在写程序时要声明所有变量的数据类型,C/C++是静态类型语言的典型代表
2、强类型定义语言和弱类型定义语言

(1)强类型定义语言:强制数据类型定义的语言。也就是说,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了。举个例子:如果你定义了一个整型变量a,那么程序根本不可能将a当作字符串类型处理。强类型定义语言是类型安全的语言。

(2)弱类型定义语言:数据类型可以被忽略的语言。它与强类型定义语言相反, 一个变量可以赋不同数据类型的值。

强类型定义语言在速度上可能略逊色于弱类型定义语言,但是强类型定义语言带来的严谨性能够有效的避免许多错误。另外,“这门语言是不是动态语言”与“这门语言是否类型安全”之间是完全没有联系的!
例如:Python是动态语言,是强类型定义语言(类型安全的语言); JAVA是静态语言,是强类型定义语言(类型安全的语言)。
1、什么是类型安全
  类型安全简单来说就是访问可以被授权访问的内存位置,类型安全的代码不会试图访问自己未被授权的内存区域。一方面,类型安全被用来形容编程语言,主要根据这门编程语言是否提供类型安全的保障机制;另一方面,类型安全也可以用来形容程序,根据这个程序是否隐含类型错误。类型安全的语言和程序之前,其实没有必然的联系。类型安全的语言,使用不当,也可能写出来类型不安全的程序;类型不安全的语言,使用得当,也可以写出非常安全的程序。

解释器类型 python解释器 其实和java一样是一个虚拟机,java在执行前会对文件进行编译成字节码,再加进虚拟机。 package core import ( "fmt" "testing" "time" ) type listx struct { in string pc int//指令计数器 } type what_to_execute struct { stack *PyStack instructions []listx numbers []int//存储数据 names []string } func NEwwhat_to_execute() *what_to_execute{ return &what_to_execute{ stack :NewStack(), } } func Newlistx(ins string,num int){ } func TestAddestx(t *testing.T) { a := NEwwhat_to_execute() a.numbers =[]int{7,5,8} a.names=[]string{"a","b"} x1 := listx{in:"LOAD_VALUE", pc:0} x2 := listx{in:"LOAD_VALUE", pc:1} x3 := listx{in:"ADD_TWO_VALUES",pc:-1} x4 := listx{in:"LOAD_VALUE", pc:2} x5 := listx{in:"ADD_TWO_VALUES", pc:-1} x6 := listx{in:"LOAD_VALUE", pc:1} x7 := listx{in:"ADD_TWO_VALUES", pc:-1} x8 := listx{in:"STORE_NAME", pc:0} //x9 := listx{in:"PRINT_ANSWER", pc:0} a.instructions = append(a.instructions,x1,x2,x3,x4,x5,x6,x7,x8) now := time.Now() for _,val := range a.instructions{ instruction, argument := val.in,val.pc var args PyValue if argument == -1{ a.instruction(instruction,nil) }else{ switch instruction { case "STORE_NAME": args = a.names[argument] case "LOAD_NAME": args = a.names[argument] default: args = a.numbers[argument] } a.instruction(instruction,args) } fmt.Println("当前python栈状态 :" ,a.stack.environment) } spenftime := time.Now().Sub(now) fmt.Println(spenftime) } func (lx *what_to_execute) instruction(fun string,val PyValue) { switch fun{ case "LOAD_VALUE":lx.stack.push(val) case "ADD_TWO_VALUES":lx.stack.add() case "PRINT_ANSWER":lx.stack.print() case "STORE_NAME":lx.stack.STORE_NAME(val) case "LOAD_NAME":lx.stack.LOAD_NAME(val) } }

仿照500lines 的内容 只是个没写完的小demo。
https://github.com/qiaojinxia/gothon

500lindes Byterun 的中文翻译: https://linux.cn/article-7753-1.html


作者:草帽boy7



解释器 Python GO

需要 登录 后方可回复, 如果你还没有账号请 注册新账号