Skip to content

Commit

Permalink
Update ADAX to ADDA and MVAX to MOVA
Browse files Browse the repository at this point in the history
  • Loading branch information
aleury committed Aug 18, 2023
1 parent 3c67b0f commit 40a6c3f
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 21 deletions.
59 changes: 45 additions & 14 deletions gmachine.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,34 @@ const (
OpOUTA
OpINCA
OpDECA
OpADAX
OpMVAX
OpADDA
OpMOVA
OpSETA
OpPSHA
OpPOPA
OpJUMP
)

const (
RegA Word = iota
RegX
)

const (
ExceptionOK Word = iota
ExceptionIllegalInstruction
ExceptionOutOfMemory
)

var ErrInvalidNumber error = errors.New("invalid number")
var ErrInvalidRegister error = errors.New("invalid register")
var ErrUndefinedInstruction error = errors.New("undefined instruction")

var registers = map[string]Word{
"A": RegA,
"X": RegX,
}

type Word uint64

type Machine struct {
Expand All @@ -65,10 +76,15 @@ func New(out io.Writer) *Machine {
}
}

func (g *Machine) Next() Word {
word := g.Memory[g.MemOffset+g.P]
g.P++
return word
}

func (g *Machine) Run() {
for {
instruction := g.Memory[g.MemOffset+g.P]
g.P++
instruction := g.Next()
if g.MemOffset+g.P >= MemSize {
g.E = ExceptionOutOfMemory
return
Expand All @@ -85,13 +101,20 @@ func (g *Machine) Run() {
g.A++
case OpDECA:
g.A--
case OpADAX:
g.A += g.X
case OpMVAX:
g.X = g.A
case OpADDA:
reg := g.Next()
switch reg {
case RegX:
g.A += g.X
}
case OpMOVA:
reg := g.Next()
switch reg {
case RegX:
g.X = g.A
}
case OpSETA:
g.A = g.Memory[g.MemOffset+g.P]
g.P++
g.A = g.Next()
case OpPSHA:
g.Memory[g.S] = g.A
g.S++
Expand Down Expand Up @@ -135,10 +158,18 @@ func Assemble(input string) ([]Word, error) {
program = append(program, OpPSHA)
case "POPA":
program = append(program, OpPOPA)
case "ADAX":
program = append(program, OpADAX)
case "MVAX":
program = append(program, OpMVAX)
case "ADDA":
reg, ok := registers[parts[1]]
if !ok {
return nil, fmt.Errorf("%w: %s at line %d", ErrInvalidRegister, parts[1], lineNo+1)
}
program = append(program, OpADDA, reg)
case "MOVA":
reg, ok := registers[parts[1]]
if !ok {
return nil, fmt.Errorf("%w: %s at line %d", ErrInvalidRegister, parts[1], lineNo+1)
}
program = append(program, OpMOVA, reg)
case "SETA":
var operand Word
if strings.HasPrefix(parts[1], "'") && strings.HasSuffix(parts[1], "'") {
Expand Down
40 changes: 33 additions & 7 deletions gmachine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,10 +323,10 @@ POPA
}
}

func TestMVAX(t *testing.T) {
func TestMOVA(t *testing.T) {
t.Parallel()
g := gmachine.New(nil)
err := g.AssembleAndRun("SETA 42\nMVAX\n")
err := g.AssembleAndRun("SETA 42\nMOVA X\n")
if err != nil {
t.Fatal("didn't expect an error:", err)
}
Expand All @@ -336,15 +336,28 @@ func TestMVAX(t *testing.T) {
}
}

func TestADAX(t *testing.T) {
func TestMOVA_FailsForInvalidRegister(t *testing.T) {
t.Parallel()
g := gmachine.New(nil)
err := g.AssembleAndRun("MOVA Z")
wantErr := gmachine.ErrInvalidRegister
if err == nil {
t.Fatal("expected an error to be returned for invalid argument to MOVA")
}
if !errors.Is(err, wantErr) {
t.Errorf("wanted error %v, got %v", wantErr, err)
}
}

func TestADDA(t *testing.T) {
t.Parallel()
g := gmachine.New(nil)
var wantA gmachine.Word = 10
err := g.AssembleAndRun(`
SETA 6
MVAX
MOVA X
SETA 4
ADAX
ADDA X
`)
if err != nil {
t.Fatal("didn't expect an error:", err)
Expand All @@ -354,6 +367,19 @@ ADAX
}
}

func TestADDA_FailsForInvalidRegister(t *testing.T) {
t.Parallel()
g := gmachine.New(nil)
err := g.AssembleAndRun("ADDA Z")
wantErr := gmachine.ErrInvalidRegister
if err == nil {
t.Fatal("expected an error to be returned for invalid argument to ADDA")
}
if !errors.Is(err, wantErr) {
t.Errorf("wanted error %v, got %v", wantErr, err)
}
}

func TestAddTwoNumbers(t *testing.T) {
t.Parallel()
g := gmachine.New(nil)
Expand All @@ -365,9 +391,9 @@ SETA 6
PSHA
; add x y
POPA
MVAX
MOVA X
POPA
ADAX
ADDA X
`)
if err != nil {
t.Fatal("didn't expect an error:", err)
Expand Down

0 comments on commit 40a6c3f

Please sign in to comment.