我们在Rust'e上写一个堆栈虚拟机

哈Ha! 几周以来,我一直在开发Rust编程语言。 我想谈一谈这个行业的新手可能会面对什么,他应该知道些什么。


简史


一切始于ein的分叉,为了了解如何构建编程语言,我对其进行了分叉。 由于ein是来回解释的,因此它的执行速度不是最高,并且在我开始理解某些内容之后,我决定开始编写自己的解释器,但最终也放弃了。


但是现在绝望还为时过早! 我阅读了几篇有关VM及其内容的文章,并决定编写一个简单的堆叠式VM。


什么是“堆叠式虚拟机”,它如何工作?


在habr上有一篇有关该主题的文章 ,但是我不会简要介绍这个小东西的含义,以免影响链接。


堆栈VM对以堆栈形式存储的数据执行所有操作,每个操作检索该操作所需的数据量,执行后可以将新编号“发送”到堆栈。


开始使用


首先,您需要使用货运创建一个新项目:


cargo new habr_vm 

首先,我们需要为我们的VM创建一些基本操作:


 enum Opcode { Push(i32), Add, AddAssign(i32), Sub, SubAssign(i32), } 

这些是我们的基本操作,Push命令将向堆栈中添加一个新数字,Add和Sub将从堆栈中获取两个数字并对其执行操作(分别为加法和减法),我不需要解释AddAssign和SubAssign。


下一个任务是创建虚拟机本身,为此,我们将创建一个不复杂的结构:


 struct Vm { pub stack: Vec<i32>, } 

我们实现它:


 impl Vm { //       pub fn pop(&mut self) -> i32 { self.stack.pop().unwrap() } //      pub fn run(&mut self,program: Vec<Opcode>) { for opcode in program { //      match opcode { Opcode::Push(n) => { //      self.stack.push(n); } Opcode::Add => { //        ,       let value = self.pop() + self.pop(); self.stack.push(value); } Opcode::Sub => { //           let value = self.pop() - self.pop(); self.stack.push(value); } //        Opcode::AddAssign(n) => { let mut value = self.pop(); value += n; self.stack.push(value); } Opcode::SubAssign(n) => { let mut value = self.pop(); value -= n; self.stack.push(value); } } } } } 

我们实现了结构,下一步呢? 接下来,我们需要创建我们的“程序”。


外观如下:


 let program = vec![ Opcode::Push(2),// 2    Opcode::Push(4),//  4    Opcode::Sub,//  4 - 2 ]; 

很简单,不是吗? 如果是这样,那么让我们运行我们的程序!


 let mut vm = Vm {stack: Vec::new()}; vm.run(program); //     ,       2 for i in vm.stack() { println!("{}", i); } //  2 

对我来说,这很简单,因此您可以为所需的操作添加足够的操作码。


结论


我认为我已经很清楚地解释了如何将所有这些写在一个草稿上以及它是如何工作的。


我想补充一点,由于使用类似的VM,您可以轻松编写自己的YP,基本上只需要编写解析器,词法分析器和“编译器”,并且如果您要查看现成的项目,则可以单击此链接


存储库中提供了本文中的所有代码


哈伯,祝你好运!

Source: https://habr.com/ru/post/zh-CN416505/


All Articles