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

编译型语言和解释型语言

和其他编译型语言类似,要 执行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

发布了85 篇原创文章 · 获赞 5 · 访问量 4707

猜你喜欢

转载自blog.csdn.net/weixin_41315492/article/details/104144683