|
|
@ -1,9 +1,10 @@ |
|
|
|
from dataclasses import replace |
|
|
|
from enum import Enum |
|
|
|
from gbso.cpu.regs import R16, R16_WITHOUT_SP, R8 |
|
|
|
from random import choice, randint, random, randrange |
|
|
|
from typing import List, Tuple, Type, TypeVar, Union |
|
|
|
|
|
|
|
from gbso.cpu.insn import ALL_INSN_CLASSES, Insn, Operand, UNUSED, get_signature_class |
|
|
|
from gbso.cpu.regs import R16, R16_WITHOUT_SP, R8 |
|
|
|
from gbso.program.program import Program |
|
|
|
|
|
|
|
|
|
|
@ -31,19 +32,16 @@ def mutate_program( |
|
|
|
] |
|
|
|
) |
|
|
|
new_prgm = prgm |
|
|
|
print("======") |
|
|
|
|
|
|
|
if mutation == Mutation.OPCODE: |
|
|
|
print("OPCODE") |
|
|
|
new_prgm = mutate_opcode(prgm) |
|
|
|
elif mutation == Mutation.OPERAND: |
|
|
|
print("OPERAND") |
|
|
|
new_prgm = mutate_operand(prgm) |
|
|
|
elif mutation == Mutation.SWAP: |
|
|
|
print("SWAP") |
|
|
|
new_prgm = mutate_swap(prgm) |
|
|
|
elif mutation == Mutation.INSTRUCTION: |
|
|
|
print("INSN") |
|
|
|
new_prgm = mutate_insn(prgm, prob_insn_unused) |
|
|
|
|
|
|
|
return new_prgm |
|
|
|
|
|
|
|
|
|
|
@ -57,9 +55,22 @@ def mutate_opcode(prgm: Program) -> Program: |
|
|
|
return Program(insns=insns) |
|
|
|
|
|
|
|
|
|
|
|
# TODO: Implement |
|
|
|
# God, this is ugly... a better approach would be to store operands as a tuple |
|
|
|
# instead of individual named fields. |
|
|
|
def mutate_operand(prgm: Program) -> Program: |
|
|
|
return prgm |
|
|
|
insn_index = randrange(len(prgm.insns)) |
|
|
|
insn = prgm.insns[insn_index] |
|
|
|
|
|
|
|
operand_index = randrange(len(insn.signature())) |
|
|
|
operand_type = insn.signature()[operand_index] |
|
|
|
operand_name = list(vars(insn).keys())[operand_index] |
|
|
|
|
|
|
|
insns = prgm.insns.copy() |
|
|
|
insns[insn_index] = replace( |
|
|
|
insn, **{operand_name: create_random_operand(operand_type)} |
|
|
|
) |
|
|
|
|
|
|
|
return Program(insns=insns) |
|
|
|
|
|
|
|
|
|
|
|
def mutate_swap(prgm: Program) -> Program: |
|
|
|