Start exercising grow code, breaking the VM
This commit is contained in:
@@ -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
64
grow/grow.go
Normal 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
|
||||||
|
}
|
||||||
@@ -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
24
grow/sample.go
Normal 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
|
||||||
|
}
|
||||||
@@ -73,13 +73,25 @@ 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) {
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user