Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
|
|
@ -0,0 +1,303 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type code = byte
|
||||
|
||||
const (
|
||||
fetch code = iota
|
||||
store
|
||||
push
|
||||
add
|
||||
sub
|
||||
mul
|
||||
div
|
||||
mod
|
||||
lt
|
||||
gt
|
||||
le
|
||||
ge
|
||||
eq
|
||||
ne
|
||||
and
|
||||
or
|
||||
neg
|
||||
not
|
||||
jmp
|
||||
jz
|
||||
prtc
|
||||
prts
|
||||
prti
|
||||
halt
|
||||
)
|
||||
|
||||
var codeMap = map[string]code{
|
||||
"fetch": fetch,
|
||||
"store": store,
|
||||
"push": push,
|
||||
"add": add,
|
||||
"sub": sub,
|
||||
"mul": mul,
|
||||
"div": div,
|
||||
"mod": mod,
|
||||
"lt": lt,
|
||||
"gt": gt,
|
||||
"le": le,
|
||||
"ge": ge,
|
||||
"eq": eq,
|
||||
"ne": ne,
|
||||
"and": and,
|
||||
"or": or,
|
||||
"neg": neg,
|
||||
"not": not,
|
||||
"jmp": jmp,
|
||||
"jz": jz,
|
||||
"prtc": prtc,
|
||||
"prts": prts,
|
||||
"prti": prti,
|
||||
"halt": halt,
|
||||
}
|
||||
|
||||
var (
|
||||
err error
|
||||
scanner *bufio.Scanner
|
||||
object []code
|
||||
stringPool []string
|
||||
)
|
||||
|
||||
func reportError(msg string) {
|
||||
log.Fatalf("error : %s\n", msg)
|
||||
}
|
||||
|
||||
func check(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func btoi(b bool) int32 {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func itob(i int32) bool {
|
||||
if i != 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func emitByte(c code) {
|
||||
object = append(object, c)
|
||||
}
|
||||
|
||||
func emitWord(n int) {
|
||||
bs := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(bs, uint32(n))
|
||||
for _, b := range bs {
|
||||
emitByte(code(b))
|
||||
}
|
||||
}
|
||||
|
||||
/*** Virtual Machine interpreter ***/
|
||||
func runVM(dataSize int) {
|
||||
stack := make([]int32, dataSize+1)
|
||||
pc := int32(0)
|
||||
for {
|
||||
op := object[pc]
|
||||
pc++
|
||||
switch op {
|
||||
case fetch:
|
||||
x := int32(binary.LittleEndian.Uint32(object[pc : pc+4]))
|
||||
stack = append(stack, stack[x])
|
||||
pc += 4
|
||||
case store:
|
||||
x := int32(binary.LittleEndian.Uint32(object[pc : pc+4]))
|
||||
ln := len(stack)
|
||||
stack[x] = stack[ln-1]
|
||||
stack = stack[:ln-1]
|
||||
pc += 4
|
||||
case push:
|
||||
x := int32(binary.LittleEndian.Uint32(object[pc : pc+4]))
|
||||
stack = append(stack, x)
|
||||
pc += 4
|
||||
case add:
|
||||
ln := len(stack)
|
||||
stack[ln-2] += stack[ln-1]
|
||||
stack = stack[:ln-1]
|
||||
case sub:
|
||||
ln := len(stack)
|
||||
stack[ln-2] -= stack[ln-1]
|
||||
stack = stack[:ln-1]
|
||||
case mul:
|
||||
ln := len(stack)
|
||||
stack[ln-2] *= stack[ln-1]
|
||||
stack = stack[:ln-1]
|
||||
case div:
|
||||
ln := len(stack)
|
||||
stack[ln-2] = int32(float64(stack[ln-2]) / float64(stack[ln-1]))
|
||||
stack = stack[:ln-1]
|
||||
case mod:
|
||||
ln := len(stack)
|
||||
stack[ln-2] = int32(math.Mod(float64(stack[ln-2]), float64(stack[ln-1])))
|
||||
stack = stack[:ln-1]
|
||||
case lt:
|
||||
ln := len(stack)
|
||||
stack[ln-2] = btoi(stack[ln-2] < stack[ln-1])
|
||||
stack = stack[:ln-1]
|
||||
case gt:
|
||||
ln := len(stack)
|
||||
stack[ln-2] = btoi(stack[ln-2] > stack[ln-1])
|
||||
stack = stack[:ln-1]
|
||||
case le:
|
||||
ln := len(stack)
|
||||
stack[ln-2] = btoi(stack[ln-2] <= stack[ln-1])
|
||||
stack = stack[:ln-1]
|
||||
case ge:
|
||||
ln := len(stack)
|
||||
stack[ln-2] = btoi(stack[ln-2] >= stack[ln-1])
|
||||
stack = stack[:ln-1]
|
||||
case eq:
|
||||
ln := len(stack)
|
||||
stack[ln-2] = btoi(stack[ln-2] == stack[ln-1])
|
||||
stack = stack[:ln-1]
|
||||
case ne:
|
||||
ln := len(stack)
|
||||
stack[ln-2] = btoi(stack[ln-2] != stack[ln-1])
|
||||
stack = stack[:ln-1]
|
||||
case and:
|
||||
ln := len(stack)
|
||||
stack[ln-2] = btoi(itob(stack[ln-2]) && itob(stack[ln-1]))
|
||||
stack = stack[:ln-1]
|
||||
case or:
|
||||
ln := len(stack)
|
||||
stack[ln-2] = btoi(itob(stack[ln-2]) || itob(stack[ln-1]))
|
||||
stack = stack[:ln-1]
|
||||
case neg:
|
||||
ln := len(stack)
|
||||
stack[ln-1] = -stack[ln-1]
|
||||
case not:
|
||||
ln := len(stack)
|
||||
stack[ln-1] = btoi(!itob(stack[ln-1]))
|
||||
case jmp:
|
||||
x := int32(binary.LittleEndian.Uint32(object[pc : pc+4]))
|
||||
pc += x
|
||||
case jz:
|
||||
ln := len(stack)
|
||||
v := stack[ln-1]
|
||||
stack = stack[:ln-1]
|
||||
if v != 0 {
|
||||
pc += 4
|
||||
} else {
|
||||
x := int32(binary.LittleEndian.Uint32(object[pc : pc+4]))
|
||||
pc += x
|
||||
}
|
||||
case prtc:
|
||||
ln := len(stack)
|
||||
fmt.Printf("%c", stack[ln-1])
|
||||
stack = stack[:ln-1]
|
||||
case prts:
|
||||
ln := len(stack)
|
||||
fmt.Printf("%s", stringPool[stack[ln-1]])
|
||||
stack = stack[:ln-1]
|
||||
case prti:
|
||||
ln := len(stack)
|
||||
fmt.Printf("%d", stack[ln-1])
|
||||
stack = stack[:ln-1]
|
||||
case halt:
|
||||
return
|
||||
default:
|
||||
reportError(fmt.Sprintf("Unknown opcode %d\n", op))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func translate(s string) string {
|
||||
var d strings.Builder
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == '\\' && (i+1) < len(s) {
|
||||
if s[i+1] == 'n' {
|
||||
d.WriteByte('\n')
|
||||
i++
|
||||
} else if s[i+1] == '\\' {
|
||||
d.WriteByte('\\')
|
||||
i++
|
||||
}
|
||||
} else {
|
||||
d.WriteByte(s[i])
|
||||
}
|
||||
}
|
||||
return d.String()
|
||||
}
|
||||
|
||||
func loadCode() int {
|
||||
var dataSize int
|
||||
firstLine := true
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimRight(scanner.Text(), " \t")
|
||||
if len(line) == 0 {
|
||||
if firstLine {
|
||||
reportError("empty line")
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
lineList := strings.Fields(line)
|
||||
if firstLine {
|
||||
dataSize, err = strconv.Atoi(lineList[1])
|
||||
check(err)
|
||||
nStrings, err := strconv.Atoi(lineList[3])
|
||||
check(err)
|
||||
for i := 0; i < nStrings; i++ {
|
||||
scanner.Scan()
|
||||
s := strings.Trim(scanner.Text(), "\"\n")
|
||||
stringPool = append(stringPool, translate(s))
|
||||
}
|
||||
firstLine = false
|
||||
continue
|
||||
}
|
||||
offset, err := strconv.Atoi(lineList[0])
|
||||
check(err)
|
||||
instr := lineList[1]
|
||||
opCode, ok := codeMap[instr]
|
||||
if !ok {
|
||||
reportError(fmt.Sprintf("Unknown instruction %s at %d", instr, opCode))
|
||||
}
|
||||
emitByte(opCode)
|
||||
switch opCode {
|
||||
case jmp, jz:
|
||||
p, err := strconv.Atoi(lineList[3])
|
||||
check(err)
|
||||
emitWord(p - offset - 1)
|
||||
case push:
|
||||
value, err := strconv.Atoi(lineList[2])
|
||||
check(err)
|
||||
emitWord(value)
|
||||
case fetch, store:
|
||||
value, err := strconv.Atoi(strings.Trim(lineList[2], "[]"))
|
||||
check(err)
|
||||
emitWord(value)
|
||||
}
|
||||
}
|
||||
check(scanner.Err())
|
||||
return dataSize
|
||||
}
|
||||
|
||||
func main() {
|
||||
codeGen, err := os.Open("codegen.txt")
|
||||
check(err)
|
||||
defer codeGen.Close()
|
||||
scanner = bufio.NewScanner(codeGen)
|
||||
runVM(loadCode())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue