7 个不稳定版本 (3 个破坏性更新)
0.4.3 | 2020 年 8 月 2 日 |
---|---|
0.4.2 | 2020 年 8 月 2 日 |
0.3.0 | 2020 年 7 月 24 日 |
0.2.0 | 2020 年 7 月 24 日 |
0.1.0 | 2020 年 7 月 24 日 |
#465 在 编程语言
105KB
1.5K SLoC
DarkVM
一个专注于在不牺牲速度和简单性的前提下提供当前功能的虚拟机。
这个项目也是我学习更多关于虚拟机和编译器的一种方式。
DarkVM 详细信息
DarkVM 在栈上运行并使用不同的操作来操作它。
DarkVM 中的类型
目前,DarkVM 支持以下类型
- void
- any
- int
- float
- boolean
- string
指令集
在本节中,将对每个指令进行详细说明,并附上示例
DarkVM 当前支持的指令
- push
- pop
- peek
- add
- sub
- mul
- div
- lt
- lte
- gt
- gte
- eq
- neq
- jmp
- rjmp
- jmpt
- jmpf
- set
- call
Push 指令
Push 指令接受一个参数:要压入栈的值。
示例
push 1
Push 指令接受一个 int 类型的值 1,并将其压入栈中。
示例
push 1
执行此指令后,栈将看起来像这样
[1]
Pop 指令
Pop 指令不接受任何参数。
示例
pop
Pop 指令从栈中移除顶部值并返回此值。
示例
push 1
pop
执行此指令后,栈将看起来像这样
[]
返回的值将是 int 类型的 1。
Peek 指令
Peek 指令不接受任何参数。
示例
peek
Peek 指令返回栈顶的值。它不会从栈中移除它。
示例
push 1
peek
执行此指令后,栈将看起来像这样
[1]
返回的值将是 int 类型的 1。
Add 指令
Add 指令不接受任何参数。
示例
add
Add 指令从栈中移除顶部两个值并将它们相加。然后返回此值。
示例
push 1
push 2
add
执行此指令后,栈将看起来像这样
[]
返回的值将是 int 类型的 3。
Sub 指令
Sub 指令不接受任何参数。
示例
sub
Sub 指令从栈中移除顶部两个值并从它们中减去。然后返回此值。
示例
push 1
push 2
sub
执行此指令后,栈将看起来像这样
[]
返回的值将是 int 类型的 1。
Mul 指令
Mul 指令不接受任何参数。
示例
mul
Mul 指令从栈中移除顶部两个值并将它们相乘。然后返回此值。
示例
push 1
push 2
mul
执行此指令后,栈将看起来像这样
[]
返回的值将是 int 类型的 2。
Div 指令
Div 指令不接受任何参数。
示例
div
div 指令从栈中弹出两个值并执行除法操作。然后返回这个值。
示例
push 1
push 2
div
执行此指令后,栈将看起来像这样
[]
返回的值将是整数 0,因为 1 除以 2 等于 0(整数除法)。如果使用浮点除法,结果将是 0.5。
Lt 指令
Lt 指令接受两个参数。
示例
lt 1 5
Lt 指令检查第一个参数是否小于第二个参数。然后返回一个表示比较结果的布尔值。
示例
lt 1 5
执行此指令后,栈将看起来像这样
[]
返回的值将是布尔值 true,因为 1 小于 5。
Lte 指令
Lte 指令接受两个参数。
示例
lte 1 5
Lte 指令检查第一个参数是否小于或等于第二个参数。然后返回一个表示比较结果的布尔值。
示例
lte 5 5
执行此指令后,栈将看起来像这样
[]
返回的值将是布尔值 true,因为 5 小于或等于 5。
Gt 指令
Gt 指令接受两个参数。
示例
gt 1 5
Gt 指令检查第一个参数是否大于第二个参数。然后返回一个表示比较结果的布尔值。
示例
gt 1 5
执行此指令后,栈将看起来像这样
[]
返回的值将是布尔值 false,因为 1 小于 5。
Gte 指令
Gte 指令接受两个参数。
示例
gte 1 5
Gte 指令检查第一个参数是否大于或等于第二个参数。然后返回一个表示比较结果的布尔值。
示例
gte 5 5
执行此指令后,栈将看起来像这样
[]
返回的值将是布尔值 true,因为 5 大于或等于 5。
Eq 指令
Eq 指令接受两个参数。
示例
eq 1 5
Eq 指令检查第一个参数是否等于第二个参数。然后返回一个表示比较结果的布尔值。
示例
eq 1 5
执行此指令后,栈将看起来像这样
[]
返回的值将是布尔值 false,因为 1 不等于 5。
Neq 指令
Neq 指令接受两个参数。
示例
neq 1 5
Neq 指令检查第一个参数是否不等于第二个参数。然后返回一个表示比较结果的布尔值。
示例
neq 5 5
执行此指令后,栈将看起来像这样
[]
返回的值将是布尔值 false,因为 5 等于 5。
Jmp 指令
Jmp 指令接受一个参数。
示例
jmp 1
Jmp 指令检查传入的参数是否在程序范围内,如果是,则跳转到指定的位置。
示例
jmp 4
push "Failed"
push "Succeeded"
执行此指令后,栈将看起来像这样
["Succeeded"]
Jmp 指令不返回任何值。
Rjmp 指令
Rjmp 指令接受一个参数。
示例
rjmp 1
Rjmp 指令检查当前位置加上传入的参数是否在程序范围内,如果是,则跳转到当前位置加上指定的位置。这个参数可以是正数或负数,只要它们的和在范围内。
示例
rjmp 4
push "Failed"
push "Succeeded"
执行此指令后,栈将看起来像这样
["Succeeded"]
Rjmp 指令不返回任何值。
Jmpt 指令
Jmpt 指令接受一个参数。
示例
push true
jmpt 3
Jmpt 指令首先检查栈顶的值是否为 true。如果是,它检查传入的参数是否在程序范围内,如果是,则跳转到指定的位置。
示例
push true
jmpt 6
push "Failed"
push "Succeeded"
执行此指令后,栈将看起来像这样
["Succeeded", true]
Jmpt 指令不返回任何值。
Jmpf 指令
Jmpf 指令接受一个参数。
示例
push false
jmpf 3
Jmpf 指令首先检查栈顶的值是否为 false。如果是,它检查传入的参数是否在程序范围内,如果是,则跳转到指定的位置。
示例
push false
jmpf 6
push "Failed"
push "Succeeded"
执行此指令后,栈将看起来像这样
["Succeeded", false]
Jmpf 指令不返回任何值。
Print 指令
Print 指令接受一个参数。
示例
print "Hello, World!"
Print 指令输出参数。然而,它不会在后面打印换行符。如果您需要这种行为,请查看 "printn" 指令。
示例
push 1
push 1
push add
print "1 + 1 = "
print pop
执行此指令后,栈将看起来像这样
[]
Print 指令不返回任何值。
Printn 指令
打印指令(Printn Instruction)需要一个参数。
示例
printn "Hello, World!"
打印指令(printn instruction)将参数打印出来,并在后面添加换行符。
示例
printn "Hello, World!"
push 1
push 1
push add
printn "1 + 1 = "
printn pop
执行此指令后,栈将看起来像这样
[]
Print 指令不返回任何值。
设置指令(Set Instruction)
设置指令(Set Instruction)需要两个参数。
示例
set message "Hello, World!"
设置指令(set instruction)使用第一个参数的名称定义一个变量,在这个例子中是 message。这个变量的值是第二个参数。
示例
set message "Hello, World!"
printn message
执行此指令后,栈将看起来像这样
[]
设置指令(set instruction)不会返回任何值。
调用指令(Call Instruction)
调用指令(Call Instruction)需要一个参数。
示例
call greet
调用指令(call instruction)调用传入的标签。有关标签的更多信息,请访问专门的章节。
示例
call greet
@greet
printn "Hello, World!"
end
在上面的例子中,运行了 greet 标签内的代码。因此,“Hello, World!”被打印到屏幕上。在标签内的代码执行完毕后,代码从函数调用之后的点继续执行。
执行此指令后,栈将看起来像这样
[]
调用指令(call instruction)不会返回任何值。
DarkVM中的标签(Labels In DarkVM)
在 DarkVM 中,标签提供了局部作用域。根据上下文,可以将其视为方法或块。以下是如何定义标签的方法:
@label_name
end
在这里,您可以看到标签以 @ 开头,然后是标签的名称。最后,它们有 end 关键字。标签名称和 end 关键字之间可以放置任意数量的代码。
标签可以访问父作用域和局部作用域。这意味着什么?如果标签是在另一个标签内部定义的,那么子标签可以访问父标签内部的所有变量。否则,它只能访问自己的作用域。尽管子标签可以访问父标签,但父标签不能访问子标签。
DarkVM中的注释(Comments In DarkVM)
DarkVM 支持单行和多行注释。
可以使用以下语法创建单行注释:
-- This is a comment.
可以使用以下语法创建多行注释:
-!
This is a multiline comment.
I can write anything I want here.
!-