Created
January 21, 2019 04:21
-
-
Save nomi-san/950e115322b0a32da526691a00ddaf70 to your computer and use it in GitHub Desktop.
Calc.vm in Go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
) | |
const ( | |
VM_OK = 0 | |
VM_ERROR = 1 | |
STACK_MAX = 50 | |
HLT = 0 // thoát | |
PSH = 1 // push | |
POP = 2 // pop | |
PUT = 3 // in giá trị | |
ADD = 4 // cộng | |
SUB = 5 // trừ | |
MUL = 6 // nhân | |
DIV = 7 // chia | |
) | |
type ( | |
Value float64 | |
Code []int | |
VM struct { | |
code Code | |
stack [STACK_MAX]Value | |
top int | |
ip int | |
} | |
) | |
var vm VM | |
func initVM(code Code) { | |
vm.top = 0 | |
vm.ip = 0 | |
vm.code = code | |
} | |
func nextCode() int { | |
code := vm.code[vm.ip] | |
vm.ip++ | |
return code | |
} | |
func pushValue(val Value) { | |
vm.stack[vm.top] = val | |
vm.top++ | |
} | |
func popValue() Value { | |
vm.top-- | |
val := vm.stack[vm.top] | |
return val | |
} | |
func runVM() int { | |
for vm.ip < len(vm.code) { | |
op := nextCode() | |
debugVM(op) | |
switch op { | |
case HLT: | |
return VM_OK | |
case PSH: | |
val := Value(nextCode()) | |
pushValue(val) | |
break | |
case POP: | |
popValue() | |
break | |
case PUT: | |
val := popValue() | |
fmt.Printf("-> %g\n", val) | |
break | |
case ADD: | |
b, a := popValue(), popValue() // a push lên trước b, nên khi pop sẽ ngược lại | |
pushValue(a + b) | |
break | |
case SUB: | |
b, a := popValue(), popValue() // tương tự | |
pushValue(a - b) | |
break | |
case MUL: | |
b, a := popValue(), popValue() | |
pushValue(a * b) | |
break | |
case DIV: | |
b, a := popValue(), popValue() | |
pushValue(a / b) | |
break | |
default: | |
fmt.Printf("unknow opcode: %d\n", op) | |
return VM_ERROR | |
} | |
} | |
return VM_ERROR | |
} | |
func debugVM(op int) { | |
switch op { | |
case HLT: | |
fmt.Print(">> on halt program!\n") | |
break | |
case PSH: | |
val := vm.code[vm.ip] | |
fmt.Printf(">> push %d to stack\n", val) | |
break | |
case POP: | |
val := vm.stack[vm.top-1] | |
fmt.Printf(">> pop %g from stack\n", val) | |
break | |
case PUT: | |
val := vm.stack[vm.top-1] | |
fmt.Printf(">> pop %g from stack and print it\n", val) | |
break | |
case ADD: | |
b, a := vm.stack[vm.top-1], vm.stack[vm.top-2] | |
fmt.Printf(">> add %g to %g, push %g\n", a, b, a+b) | |
break | |
case SUB: | |
b, a := vm.stack[vm.top-1], vm.stack[vm.top-2] | |
fmt.Printf(">> sub %g to %g, push %g\n", a, b, a-b) | |
break | |
case MUL: | |
b, a := vm.stack[vm.top-1], vm.stack[vm.top-2] | |
fmt.Printf(">> mul %g to %g, push %g\n", a, b, a*b) | |
break | |
case DIV: | |
b, a := vm.stack[vm.top-1], vm.stack[vm.top-2] | |
fmt.Printf(">> div %g to %g, push %g\n", a, b, a/b) | |
break | |
} | |
} | |
func main() { | |
// 4 + 5 | |
code1 := []int{PSH, 4, PSH, 5, ADD, PUT, HLT} | |
// 100 - 52 + 88 // 35 * 8 / 7 | |
code2 := []int{PSH, 100, PSH, 52, SUB, PSH, 88, ADD, PUT, PSH, 35, PSH, 8, MUL, PSH, 6, DIV, PUT, HLT} | |
initVM(code1) | |
if runVM() == VM_OK { | |
fmt.Print("code1: OK\n\n") | |
} else { | |
fmt.Print("code1: ERROR\n\n") | |
} | |
initVM(code2) | |
if runVM() == VM_OK { | |
fmt.Print("code2: OK\n\n") | |
} else { | |
fmt.Print("code2: ERROR\n\n") | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ go run main.go | |
>> push 4 to stack | |
>> push 5 to stack | |
>> add 4 to 5, push 9 | |
>> pop 9 from stack and print it | |
-> 9 | |
>> on halt program! | |
code1: OK | |
>> push 100 to stack | |
>> push 52 to stack | |
>> sub 100 to 52, push 48 | |
>> push 88 to stack | |
>> add 48 to 88, push 136 | |
>> pop 136 from stack and print it | |
-> 136 | |
>> push 35 to stack | |
>> push 8 to stack | |
>> mul 35 to 8, push 280 | |
>> push 6 to stack | |
>> div 280 to 6, push 46.666666666666664 | |
>> pop 46.666666666666664 from stack and print it | |
-> 46.666666666666664 | |
>> on halt program! | |
code2: OK |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment