Start exercising grow code, breaking the VM

This commit is contained in:
Ian Gulliver
2021-11-20 19:17:35 -10:00
parent 510680d6c5
commit f6a598a559
6 changed files with 107 additions and 12 deletions

View File

@@ -10,12 +10,7 @@ type Definition struct {
Samples []*Sample `yaml:"samples"` Samples []*Sample `yaml:"samples"`
} }
type Sample struct { func NewDefinition(r io.Reader) (*Definition, error) {
GlobalMemoryInputs map[uint64]uint64 `yaml:"global_memory_inputs"`
GlobalMemoryOutputs map[uint64]uint64 `yaml:"global_memory_outputs"`
}
func loadDefinition(r io.Reader) (*Definition, error) {
dec := yaml.NewDecoder(r) dec := yaml.NewDecoder(r)
dec.SetStrict(true) dec.SetStrict(true)

64
grow/grow.go Normal file
View File

@@ -0,0 +1,64 @@
package main
import "log"
import "github.com/firestuff/subcoding/asm"
import "github.com/firestuff/subcoding/gen"
import "github.com/firestuff/subcoding/vm"
func (def *Definition) Grow() {
high_score := 0
log.Print("Starting grow run...")
// TODO: Score should be number of output criteria, not number of Samples
for high_score < len(def.Samples) {
prog := gen.RandProgram(def.GlobalMemorySize, def.FunctionMemorySize)
{
src, err := asm.Disassemble(prog)
if err != nil {
log.Fatal(err)
}
log.Print("Prog:\n%s", src)
}
score, err := def.Score(prog)
if err != nil {
log.Fatal(err)
}
if score > high_score {
high_score = score
src, err := asm.Disassemble(prog)
if err != nil {
log.Fatal(err)
}
log.Print("New high score %d / %d:\n%s", high_score, len(def.Samples), src)
}
}
}
func (def *Definition) Score(prog *vm.Program) (int, error) {
score := 0
for _, sample := range def.Samples {
state, err := vm.NewState(prog)
if err != nil {
return 0, err
}
sample.SetInputs(state)
state.Execute() // ignore error
if sample.OutputsMatch(state) {
score += 1
}
}
return score, nil
}

View File

@@ -17,10 +17,10 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
def, err := loadDefinition(defFile) def, err := NewDefinition(defFile)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
log.Printf("%+v", def) def.Grow()
} }

24
grow/sample.go Normal file
View File

@@ -0,0 +1,24 @@
package main
import "github.com/firestuff/subcoding/vm"
type Sample struct {
GlobalMemoryInputs map[uint64]uint64 `yaml:"global_memory_inputs"`
GlobalMemoryOutputs map[uint64]uint64 `yaml:"global_memory_outputs"`
}
func (s *Sample) SetInputs(state *vm.State) {
for i, val := range s.GlobalMemoryInputs {
state.GlobalMemory().WriteUnsigned(i, val)
}
}
func (s *Sample) OutputsMatch(state *vm.State) bool {
for i, val := range s.GlobalMemoryOutputs {
if state.GlobalMemory().MustReadUnsigned(i) != val {
return false
}
}
return true
}

View File

@@ -73,14 +73,26 @@ func (state *State) handleMultiply(instr *Instruction) {
func (state *State) handleDivideUnsigned(instr *Instruction) { func (state *State) handleDivideUnsigned(instr *Instruction) {
in1 := state.readUnsigned(instr.Operands[0]) in1 := state.readUnsigned(instr.Operands[0])
in2 := state.readUnsigned(instr.Operands[1]) in2 := state.readUnsigned(instr.Operands[1])
if in2 == 0 {
// Divide by zero just returns zero
state.writeUnsigned(instr.Operands[0], 0)
} else {
state.writeUnsigned(instr.Operands[0], in1/in2) state.writeUnsigned(instr.Operands[0], in1/in2)
} }
}
func (state *State) handleDivideSigned(instr *Instruction) { func (state *State) handleDivideSigned(instr *Instruction) {
in1 := state.readSigned(instr.Operands[0]) in1 := state.readSigned(instr.Operands[0])
in2 := state.readSigned(instr.Operands[1]) in2 := state.readSigned(instr.Operands[1])
if in2 == 0 {
// Divide by zero just returns zero
state.writeSigned(instr.Operands[0], 0)
} else {
state.writeSigned(instr.Operands[0], in1/in2) state.writeSigned(instr.Operands[0], in1/in2)
} }
}
func (state *State) handleNot(instr *Instruction) { func (state *State) handleNot(instr *Instruction) {
in := state.readUnsigned(instr.Operands[0]) in := state.readUnsigned(instr.Operands[0])

View File

@@ -71,11 +71,11 @@ func (state *State) processInstruction() {
state.instructionIndex += 1 state.instructionIndex += 1
instr.opHandler(state, instr) instr.opHandler(state, instr)
if state.functionIndex >= int64(len(state.program.Functions)) { if state.functionIndex < 0 || state.functionIndex >= int64(len(state.program.Functions)) {
state.ret() state.ret()
} }
if state.instructionIndex >= int64(len(fnc.Instructions)) { if state.instructionIndex < 0 || state.instructionIndex >= int64(len(fnc.Instructions)) {
state.ret() state.ret()
} }
} }