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