Add gmachine
This commit is contained in:
parent
64f5d8346d
commit
0948cefe10
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
9
.idea/bitfield.iml
Normal file
9
.idea/bitfield.iml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="Go" enabled="true" />
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/bitfield.iml" filepath="$PROJECT_DIR$/.idea/bitfield.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
14
gmachine/calc.go
Normal file
14
gmachine/calc.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package gmachine
|
||||||
|
|
||||||
|
func Calc() uint64 {
|
||||||
|
g := New()
|
||||||
|
g.Memory = []uint64{
|
||||||
|
OpSETA,
|
||||||
|
3,
|
||||||
|
OpDECA,
|
||||||
|
OpDECA,
|
||||||
|
OpHALT,
|
||||||
|
}
|
||||||
|
g.Run()
|
||||||
|
return g.A
|
||||||
|
}
|
15
gmachine/calc_test.go
Normal file
15
gmachine/calc_test.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package gmachine
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestCalc(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var wants uint64 = 1
|
||||||
|
|
||||||
|
got := Calc()
|
||||||
|
|
||||||
|
if wants != got {
|
||||||
|
t.Errorf("want %d, got %d", wants, got)
|
||||||
|
}
|
||||||
|
}
|
75
gmachine/gmachine.go
Normal file
75
gmachine/gmachine.go
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package gmachine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultMemSize is the number of 64-bit words of memory which will be
|
||||||
|
// allocated to a new G-machine by default.
|
||||||
|
const DefaultMemSize = 1024
|
||||||
|
|
||||||
|
const (
|
||||||
|
OpHALT uint64 = iota
|
||||||
|
OpNOOP
|
||||||
|
OpINCA
|
||||||
|
OpDECA
|
||||||
|
OpSETA
|
||||||
|
)
|
||||||
|
|
||||||
|
type gMachine struct {
|
||||||
|
// Memory 64-bit words of memory
|
||||||
|
Memory []uint64
|
||||||
|
// P (Program counter)
|
||||||
|
P uint64
|
||||||
|
// A (Register A)
|
||||||
|
A uint64
|
||||||
|
// Debugging flag, if turned on will print OpCodes
|
||||||
|
DebugOn bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *gMachine {
|
||||||
|
return &gMachine{
|
||||||
|
P: 0,
|
||||||
|
Memory: make([]uint64, DefaultMemSize),
|
||||||
|
DebugOn: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *gMachine) NewProgram(program []uint64) {
|
||||||
|
copy(m.Memory, program)
|
||||||
|
m.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *gMachine) Run() {
|
||||||
|
for {
|
||||||
|
pointer := m.P
|
||||||
|
m.P++
|
||||||
|
switch m.Memory[pointer] {
|
||||||
|
case OpHALT:
|
||||||
|
m.printIfDebug("OpHALT")
|
||||||
|
return
|
||||||
|
case OpNOOP:
|
||||||
|
m.printIfDebug("OpNOOP")
|
||||||
|
case OpINCA:
|
||||||
|
m.printIfDebug("OpINCA")
|
||||||
|
m.A++
|
||||||
|
case OpDECA:
|
||||||
|
m.printIfDebug("OpDECA")
|
||||||
|
m.A--
|
||||||
|
case OpSETA:
|
||||||
|
m.A = m.Memory[m.P]
|
||||||
|
m.P++
|
||||||
|
m.printIfDebug(fmt.Sprintf("OpSETA %d", m.A))
|
||||||
|
default:
|
||||||
|
m.printIfDebug(fmt.Sprintf("COULD NOT DETERMINE OP CODE, code:%d, pointer:%d", m.Memory[pointer], pointer))
|
||||||
|
panic(pointer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *gMachine) printIfDebug(message string) {
|
||||||
|
if m.DebugOn {
|
||||||
|
log.Println(message)
|
||||||
|
}
|
||||||
|
}
|
108
gmachine/gmachine_test.go
Normal file
108
gmachine/gmachine_test.go
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
package gmachine_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gmachine"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNew(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
g := gmachine.New()
|
||||||
|
wantMemSize := gmachine.DefaultMemSize
|
||||||
|
gotMemSize := len(g.Memory)
|
||||||
|
if wantMemSize != gotMemSize {
|
||||||
|
t.Errorf("want %d words of memory, got %d", wantMemSize, gotMemSize)
|
||||||
|
}
|
||||||
|
var wantP uint64 = 0
|
||||||
|
if wantP != g.P {
|
||||||
|
t.Errorf("want initial P value %d, got %d", wantP, g.P)
|
||||||
|
}
|
||||||
|
var wantMemValue uint64 = 0
|
||||||
|
gotMemValue := g.Memory[gmachine.DefaultMemSize-1]
|
||||||
|
if wantMemValue != gotMemValue {
|
||||||
|
t.Errorf("want last memory location to contain %d, got %d", wantMemValue, gotMemValue)
|
||||||
|
}
|
||||||
|
var wantRegisterA uint64 = 0
|
||||||
|
gotRegisterA := g.A
|
||||||
|
if wantRegisterA != gotRegisterA {
|
||||||
|
t.Errorf("want registerA with data %d, got %d", wantRegisterA, gotRegisterA)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHalt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
var wants uint64 = 1
|
||||||
|
|
||||||
|
g := gmachine.New()
|
||||||
|
g.Run()
|
||||||
|
got := g.P
|
||||||
|
|
||||||
|
if wants != got {
|
||||||
|
t.Errorf("want P == %d, got %d", wants, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNOOP(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var wants uint64 = 2
|
||||||
|
|
||||||
|
g := gmachine.New()
|
||||||
|
g.NewProgram([]uint64{
|
||||||
|
gmachine.OpNOOP,
|
||||||
|
gmachine.OpHALT,
|
||||||
|
})
|
||||||
|
got := g.P
|
||||||
|
|
||||||
|
if wants != got {
|
||||||
|
t.Errorf("want P == %d, got %d", wants, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestINCA(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var wants uint64 = 1
|
||||||
|
|
||||||
|
g := gmachine.New()
|
||||||
|
g.Memory[0] = gmachine.OpINCA
|
||||||
|
g.Run()
|
||||||
|
got := g.A
|
||||||
|
|
||||||
|
if wants != got {
|
||||||
|
t.Errorf("want A == %d, got %d", wants, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDECA(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var wants uint64 = 1
|
||||||
|
|
||||||
|
g := gmachine.New()
|
||||||
|
g.A = 2
|
||||||
|
g.Memory[0] = gmachine.OpDECA
|
||||||
|
g.Run()
|
||||||
|
got := g.A
|
||||||
|
|
||||||
|
if wants != got {
|
||||||
|
t.Errorf("want A == %d, got %d", wants, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSETA(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
var wants uint64 = 3
|
||||||
|
|
||||||
|
g := gmachine.New()
|
||||||
|
g.Memory[0] = gmachine.OpSETA
|
||||||
|
g.Memory[1] = wants
|
||||||
|
g.Run()
|
||||||
|
got := g.A
|
||||||
|
|
||||||
|
if wants != got {
|
||||||
|
t.Errorf("want A == %d, got %d", wants, got)
|
||||||
|
}
|
||||||
|
}
|
3
gmachine/go.mod
Normal file
3
gmachine/go.mod
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module gmachine
|
||||||
|
|
||||||
|
go 1.17
|
Loading…
Reference in New Issue
Block a user