
Hi Elvio,
Couldn't this be solved with an Iteratee approach?
Thanks for your reply! I'm now looking into this solution; is there a standardised Enumerat{or,ee}/Iteratee library? Or is the situation still as it was discussed in the following URL? https://john-millikin.com/articles/understanding-iteratees/
An Enumerator produces values from your VM, an Enumeratee checks that only enough pass (enough to disassemble 'this' instruction) and an Iteratee chews the memory into the final value.
Cheers!
I'm writing this without the time to actually develop it, I'm sorry for not providing any examples.
I'll come back when/if I manage it :) Arlen
On Mon, 2011-05-09 at 18:41 +1000, Arlen Cuss wrote:
Hi all,
I'm currently trying to write a very simple VM in order to learn and stretch my Haskell. I'm currently up against a problem.
I'm using an (IOUArray Int Word32) to represent the memory of a VM instance. This is all fine so far, but now I'm trying to write a 'disassemble' function that will disassemble an instruction starting from a given location in memory.
Ideally I could write a function that would lazily yield successive elements from memory, sort of like this:
readVMFrom :: VM -> Address -> IO [Word32] readVMFrom v f = do i <- readArray (memory v) f rest <- readVMFrom v (succ f) return $ i : readVMFrom v (succ f)
Of course, this isn't lazy, and so happily runs off the end of memory each time. (I could stop that, but that's not the point!) I'm not sure how to lazily construct a list in IO.
My next thought is to instead make a function to return an action that yields successive values of memory, given some start, i.e. something like:
readVMFrom :: VM -> Address -> IO Word32
.. but I'm thinking I might have to do some StateT nonsense in order to actually keep track of which index we want to read next. (subtext: I don't know how to do that!)
So I then think that perhaps I can do this by having readVMFrom return an action which yields a) the next value, b) the address of the next value (so we know how much we ate), and c) an action to yield the next value and action and so on, so on. I managed that this way (WARNING, BEGINNER HASKELL CODE FOLLOWS):
newtype RVFResult = RVFResult { getRVFResult :: (Word32, Address, IO RVFResult) }
readVMFrom :: VM -> Address -> IO RVFResult readVMFrom v f = do i <- readArray (memory v) f return $ RVFResult (i, succ f, readVMFrom v $ succ f)
A function can then take an argument of type RVFResult as an indication it wants 1..n sequential values from memory:
disassemble :: RVFResult -> IO (Instruction, Address) disassemble r = do let (i, p, a) = getRVFResult r case i of 0x01 -> return (Push, p) 0x02 -> return (Pop, p) 0x03 -> return (Call, p) 0x04 -> do r <- a let (v, p, a) = getRVFResult r return (Out v, p)
Here you can see how we consume an additional value by executing the returned action 'a'. It's damn ugly, and this almost looks like the place for a monad (possibly something involving StateT, though, I don't know!).
Ideally I'd manage a lazily constructed list -- somehow I feel that's most "Haskelly" -- but does anyone else have any ideas? I kinda fleshed this last solution out as I wrote this email, so it's kinda cruddy.
Cheers,
Arlen _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners