-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathprimary_instructions.go
More file actions
156 lines (138 loc) · 3.87 KB
/
Copy pathprimary_instructions.go
File metadata and controls
156 lines (138 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package main
import "fmt"
func push(vm *VM, inst Inst) {
vm.STACK[vm.stack_size] = inst.Operand
vm.stack_size += 1
vm.inst_ptr += 1
}
func peek(vm *VM) Value_Holder {
if vm.stack_size == 0 {
exit_with_one("Empty Stack")
}
return vm.STACK[vm.stack_size-1]
}
func jmp(vm *VM, inst Inst) {
if inst.Operand.int64holder < 0 {
exit_with_one("Wrong Jump Instruction. Underflow")
}
if inst.Operand.int64holder >= vm.program_size {
exit_with_one("Wrong Jump Instruction. Overflow")
}
vm.inst_ptr = inst.Operand.int64holder
}
func nop(vm *VM) {
vm.inst_ptr += 1
}
func print(vm *VM) {
if vm.stack_size < 1 {
exit_with_one("Not enough values on the stack to print")
}
type_of_operand := get_operand_type_by_name(vm.STACK[vm.stack_size-1])
switch type_of_operand {
case "int64":
fmt.Printf("%d\n", vm.STACK[vm.stack_size-1].int64holder)
case "float64":
fmt.Printf("%f\n", vm.STACK[vm.stack_size-1].float64holder)
default:
fmt.Printf("%s\n", vm.STACK[vm.stack_size-1].pointer)
}
vm.stack_size -= 1
vm.inst_ptr += 1
}
func print_asc(vm *VM) {
if vm.stack_size < 1 {
exit_with_one("Not enough values on the stack to print")
}
type_of_operand := get_operand_type_by_name(vm.STACK[vm.stack_size-1])
switch type_of_operand {
case "int64":
fmt.Printf("%s", string(rune(vm.STACK[vm.stack_size-1].int64holder)))
default:
fmt.Printf("\nERROR: Runtime error: Instruction `%s` failed: Expected type `integer` on top of stack but found `%s`\n", vm.PROGRAM[vm.inst_ptr].Name, type_of_operand)
}
vm.stack_size -= 1
vm.inst_ptr += 1
}
func halt(vm *VM) {
vm.vm_halt = 1
}
func drop(vm *VM) {
if vm.stack_size < 1 {
exit_with_one("STACK UNDERFLOW")
}
vm.stack_size -= 1
vm.inst_ptr += 1
}
func ret(vm *VM) {
if vm.stack_size < 1 {
exit_with_one("Stack Underflow")
}
vm.inst_ptr = vm.STACK[vm.stack_size-1].int64holder
vm.stack_size -= 1
}
func call(vm *VM, inst Inst) {
if vm.stack_size >= STACK_CAPACITY {
exit_with_one("Stack Overflow")
}
reset_operand_except(&vm.STACK[vm.stack_size], "int64")
vm.STACK[vm.stack_size].int64holder = vm.inst_ptr + 1
vm.stack_size += 1
vm.inst_ptr = inst.Operand.int64holder
}
func dup(vm *VM, inst Inst) {
if vm.stack_size >= STACK_CAPACITY {
exit_with_one("Stack Overflow")
}
if vm.stack_size-inst.Operand.int64holder <= 0 {
exit_with_one("Stack Underflow")
}
inst_name_to_be_assigned := get_operand_type_by_name(vm.STACK[vm.stack_size-1-inst.Operand.int64holder])
if inst_name_to_be_assigned == "float64" {
reset_operand_except(&vm.STACK[vm.stack_size], "float64")
vm.STACK[vm.stack_size].float64holder = vm.STACK[vm.stack_size-1-inst.Operand.int64holder].float64holder
}
if inst_name_to_be_assigned == "int64" {
reset_operand_except(&vm.STACK[vm.stack_size], "int64")
vm.STACK[vm.stack_size].int64holder = vm.STACK[vm.stack_size-1-inst.Operand.int64holder].int64holder
}
vm.stack_size += 1
vm.inst_ptr += 1
}
func swap(vm *VM, inst Inst) {
if inst.Operand.int64holder >= vm.stack_size {
exit_with_one("Stack Underflow")
}
a := vm.stack_size - 1
b := vm.stack_size - 1 - inst.Operand.int64holder
t := vm.STACK[a]
vm.STACK[a] = vm.STACK[b]
vm.STACK[b] = t
vm.inst_ptr += 1
}
func jmp_if(vm *VM, inst Inst) {
if inst.Operand.int64holder >= vm.program_size {
exit_with_one("Wrong Jump_If Instruction. Overflow")
}
if vm.stack_size < 1 {
exit_with_one("Wrong Jump_If Instruction. Underflow")
}
tmp_chk := operand_type_check(vm.STACK[vm.stack_size-1], "int64") && inst.Operand.int64holder != 0
if tmp_chk {
vm.inst_ptr = inst.Operand.int64holder
} else {
vm.inst_ptr += 1
}
vm.stack_size -= 1
}
func not(vm *VM) {
if vm.stack_size < 0 {
exit_with_one("Stack Underflow")
}
tmp_chk := operand_type_check(vm.STACK[vm.stack_size-1], "int64")
if tmp_chk && vm.STACK[vm.stack_size-1].int64holder != 0 {
vm.STACK[vm.stack_size-1].int64holder = 0
} else {
vm.STACK[vm.stack_size-1].int64holder = 1
}
vm.inst_ptr += 1
}