I'm making a stack based pseudo-assembler virtual machine. Here are some custom types used in the problem function:
type Program = Array Int Opcode
type Labels = Map String Int
type Stack = [Integer]
type Memory = Map String Integer
type VarList = [(String, Integer)]
Here's the problem function; there are about 20 other cases, but I'm only going to put the 3 that seem relevant to this problem:
runFrom :: Int -> Program -> VarList -> String
runFrom i p vars = step i [] (fromList vars) [] where
labels = labelMap p
step i stack mem out =
case ((Array.!) p i, stack) of
(CALL name, s) -> step ((Map.!) labels name) ((i+1):s) mem out
(INT n, s) -> step (i+1) (n:s) mem out
(J name, s) -> step ((Map.!) labels name) s mem out
First of all, the problem is the "CALL" case; the other two cases work fine when "CALL" is commented out. For the sake of clarity, "INT Integer" pushes an Integer onto the stack, and "J String" unconditionally jumps to the instruction that is mapped to the String name. "CALL String" is supposed to push onto the stack the index of the next instruction (i+1) and unconditionally jump to the label name. However, if I try to load the code above, GHC complains about not being able to match the expected Integer type against the inferred Int type in second argument of step for the "INT" case. Since "INT" works fine when "CALL" is commented out, I assume something screwy is going on in CALL (perhaps the ((i+1):s) ?). Can someone help me fix CALL?
Opcode
may matter. – user395760type Labels = Map String Int
so labels map toInt
whereasStack
,Memory
, andVarList
use integers.CALL
forces the first argument ofstep
to be anInt
which is at odds with the use ofInt
andJ
. – vivian(Array.!) p i
and(Map.!) labels name
syntax is beyond weird. Why not use infix functions the way they were meant to be used, e.g. asp Array.! i
andlabels Map.! name
? – Daniel Wagner