diff --git a/asm/disassemble.go b/asm/disassemble.go index 525bc4c..553c5ca 100644 --- a/asm/disassemble.go +++ b/asm/disassemble.go @@ -23,10 +23,12 @@ func Disassemble(prog *vm.Program) (string, error) { return fmt.Sprintf(`global_memory_size: %d function_memory_size: %d +instruction_limit: %d functions: %s`, prog.GlobalMemorySize, prog.FunctionMemorySize, + prog.InstructionLimit, strings.Join(fncs, ""), ), nil } diff --git a/asm/parse.go b/asm/parse.go index 78d7586..c758b9f 100644 --- a/asm/parse.go +++ b/asm/parse.go @@ -7,6 +7,7 @@ import "gopkg.in/yaml.v2" type program struct { GlobalMemorySize uint64 `yaml:"global_memory_size"` FunctionMemorySize uint64 `yaml:"function_memory_size"` + InstructionLimit uint64 `yaml:"instruction_limit"` Functions []function `yaml:"functions"` } diff --git a/gen/program.go b/gen/program.go index b793ad7..3e3e8dd 100644 --- a/gen/program.go +++ b/gen/program.go @@ -2,10 +2,11 @@ package gen import "github.com/firestuff/subcoding/vm" -func RandProgram(globalMemorySize, functionMemorySize uint64) *vm.Program { +func RandProgram(globalMemorySize, functionMemorySize, instructionLimit uint64) *vm.Program { prog := &vm.Program{ GlobalMemorySize: globalMemorySize, FunctionMemorySize: functionMemorySize, + InstructionLimit: instructionLimit, } prog.Functions = append(prog.Functions, &vm.Function{ diff --git a/grow/add_one.yaml b/grow/add_one.yaml index 1cfc267..2936eca 100644 --- a/grow/add_one.yaml +++ b/grow/add_one.yaml @@ -1,7 +1,16 @@ global_memory_size: 1 function_memory_size: 1 +instruction_limit: 2 samples: - global_memory_inputs: 0: 0 global_memory_outputs: 0: 1 +- global_memory_inputs: + 0: 1 + global_memory_outputs: + 0: 2 +- global_memory_inputs: + 0: 100 + global_memory_outputs: + 0: 101 diff --git a/grow/definition.go b/grow/definition.go index 0f048e3..712e2c4 100644 --- a/grow/definition.go +++ b/grow/definition.go @@ -7,6 +7,7 @@ import "gopkg.in/yaml.v2" type Definition struct { GlobalMemorySize uint64 `yaml:"global_memory_size"` FunctionMemorySize uint64 `yaml:"function_memory_size"` + InstructionLimit uint64 `yaml:"instruction_limit"` Samples []*Sample `yaml:"samples"` } diff --git a/grow/grow.go b/grow/grow.go index 2c64435..71cb35e 100644 --- a/grow/grow.go +++ b/grow/grow.go @@ -13,16 +13,7 @@ func (def *Definition) Grow() { // 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) - } + prog := gen.RandProgram(def.GlobalMemorySize, def.FunctionMemorySize, def.InstructionLimit) score, err := def.Score(prog) if err != nil { @@ -37,7 +28,7 @@ func (def *Definition) Grow() { log.Fatal(err) } - log.Print("New high score %d / %d:\n%s", high_score, len(def.Samples), src) + log.Printf("New high score %d / %d:\n%s", high_score, len(def.Samples), src) } } } diff --git a/test/disasm_test.go b/test/disasm_test.go index dce0fca..79d0774 100644 --- a/test/disasm_test.go +++ b/test/disasm_test.go @@ -8,6 +8,7 @@ import "github.com/firestuff/subcoding/vm" func TestRoundTrip(t *testing.T) { src := `global_memory_size: 4 function_memory_size: 4 +instruction_limit: 0 functions: - - [nop] - [mov, g0, 1] diff --git a/test/gen_test.go b/test/gen_test.go index face1d0..041484c 100644 --- a/test/gen_test.go +++ b/test/gen_test.go @@ -7,7 +7,7 @@ import "github.com/firestuff/subcoding/asm" func TestRandProgram(t *testing.T) { for i := 0; i < 100; i++ { - prog := gen.RandProgram(4, 4) + prog := gen.RandProgram(4, 4, 0) src, err := asm.Disassemble(prog) if err != nil { diff --git a/vm/program.go b/vm/program.go index 21145b6..f06eb47 100644 --- a/vm/program.go +++ b/vm/program.go @@ -3,5 +3,6 @@ package vm type Program struct { GlobalMemorySize uint64 FunctionMemorySize uint64 + InstructionLimit uint64 Functions []*Function } diff --git a/vm/state.go b/vm/state.go index ee7ec18..ba1ed6b 100644 --- a/vm/state.go +++ b/vm/state.go @@ -13,6 +13,8 @@ type State struct { comparisonResult bool globalMemory *Memory stack []*stackFrame + + instructionCount uint64 } func NewState(prog *Program) (*State, error) { @@ -70,6 +72,12 @@ func (state *State) processInstruction() { instr := fnc.Instructions[state.instructionIndex] state.instructionIndex += 1 instr.opHandler(state, instr) + state.instructionCount += 1 + + if state.program.InstructionLimit > 0 && state.instructionCount > state.program.InstructionLimit { + state.err = fmt.Errorf("Instruction limit (%d) exceeded", state.program.InstructionLimit) + state.running = false + } if state.functionIndex < 0 || state.functionIndex >= int64(len(state.program.Functions)) { state.ret()