Add gmachine

This commit is contained in:
Kasper Juul Hermansen 2022-02-23 01:31:53 +01:00
parent 64f5d8346d
commit 0948cefe10
Signed by: kjuulh
GPG Key ID: 0F95C140730F2F23
9 changed files with 246 additions and 0 deletions

8
.idea/.gitignore vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,3 @@
module gmachine
go 1.17