From 8d34db74b87c2cab5ff6f837f4bc6feb35ba03e9 Mon Sep 17 00:00:00 2001
From: Rowan Torbitzky-Lane <rat23h@umsystem.edu>
Date: Wed, 15 Jan 2025 20:29:51 -0600
Subject: [PATCH] add execDoRange and ExecDup

---
 src/Push.hs  | 30 ++++++++++++++++++++++++++++++
 src/Tests.hs | 19 +++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/src/Push.hs b/src/Push.hs
index a609d7e..f50c9e3 100644
--- a/src/Push.hs
+++ b/src/Push.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE DataKinds #-}
 module Push where
 
 -- import Debug.Trace (trace, traceStack)
@@ -17,6 +18,17 @@ data Gene
   | Close
   | Block [Gene]
 
+-- Not going to have instances for Block or StateFunc
+instance Eq Gene where
+  IntGene x == IntGene y = x == y
+  FloatGene x == FloatGene y = x == y
+  BoolGene x == BoolGene y = x == y
+  StringGene x == StringGene y = x == y
+  PlaceInput x == PlaceInput y = x == y
+  Close == Close = True
+  StateFunc x == StateFunc y = True -- This line is probably not the best thing to do
+  Block [x] == Block [y] = [x] == [y]
+  
 data State = State
   { exec :: [Gene],
     int :: [Int],
@@ -67,6 +79,24 @@ instructionExecIf (State (e1 : e2 : es) is fs (b : bs) ss ps im) =
     False -> State (e2 : es) is fs bs ss ps im
 instructionExecIf state = state
 
+instructionExecDup :: State -> State
+instructionExecDup (State alles@(e0 : es) is fs bs ss pm im) =
+  State (e0 : alles) is fs bs ss pm im
+instructionExecDup state = state
+
+instructionExecDoRange :: State -> State
+instructionExecDoRange (State (e1 : es) (i0 : i1 : is) fs bs ss ps im) =
+  if increment i0 i1 /= 0
+  then State (IntGene i1 : Block [IntGene (i1 + increment i0 i1), IntGene i0, StateFunc instructionExecDoRange] : es) (i1 : is) fs bs ss ps im
+  else State (e1 : es) (i1 : is) fs bs ss ps im
+  where
+    increment :: Int -> Int -> Int
+    increment destIdx currentIdx
+      | currentIdx < destIdx = 1
+      | currentIdx > destIdx = -1
+      | otherwise = 0
+instructionExecDoRange state = state
+
 -- This is one of the push genome functions itself, not infrastructure.
 -- Optionally, split this off into independent functions
 instructionParameterLoad :: State -> State
diff --git a/src/Tests.hs b/src/Tests.hs
index 1027dab..60c1590 100644
--- a/src/Tests.hs
+++ b/src/Tests.hs
@@ -14,6 +14,17 @@ exampleState =
       input = Map.fromList [("in0" , IntGene 1)]
     }
 
+doRangeState =
+  State
+    { exec = [Block [IntGene 1, IntGene 6, StateFunc instructionIntAdd], Block [IntGene 4, IntGene 1, StateFunc instructionExecDoRange]]
+    , int = []
+    , float = []
+    , string = ["abc"]
+    , bool = []
+    , parameter = []
+    , input = Map.empty
+  }
+
 testResult1 = [8, 3] == int (instructionIntAdd exampleState)
 
 testResult2 = [4, 3] == int (instructionIntSub exampleState)
@@ -33,7 +44,15 @@ testResult7 = [6, 5] == int (interpretExec loadedState2)
 loadedState3 = loadProgram [BoolGene False, StateFunc instructionExecIf, Block [IntGene 5, IntGene 6], Block [IntGene 7, IntGene 8]] emptyState
 testResult8 = [8, 7] == int (interpretExec loadedState3)
 
+-- Tests input map
 loadedState4 = loadProgram [BoolGene False, PlaceInput "in0", StateFunc instructionIntAdd] exampleState
 testResult9 = [3, 6, 3] == int (interpretExec loadedState4)
 
+-- Tests execDup
+loadedState5 = instructionExecDup exampleState
+testResult10 = exec loadedState5 !! 0 == IntGene 5 && exec loadedState5 !! 1 == IntGene 5
+
+-- Tests execDoRange
+testResult11 = [1, 4, 7] == int (interpretExec doRangeState)
+
 allTests = and [testResult1, testResult2, testResult3, testResult4, testResult5, testResult6, testResult7, testResult8, testResult9]