[Haskell-cafe] generics-sop equivalent of everywhere/mkT?

Scott Michel scooter.phd at gmail.com
Tue Feb 26 01:36:34 UTC 2019


The corresponding gensop.cabal:

cabal-version:  >= 1.12
name:           gensop
version:        0.1
build-type:     Simple
description:    No description.
license:        GPL-3

executable gensop
  default-language:     Haskell2010
  main-is: Main.hs
  build-depends:
    base,
    containers,
    bytestring,
    generics-sop,
    syb,
    text,
    unordered-containers

  default-extensions:
    OverloadedStrings,
    FlexibleInstances

  ghc-options: -Wall


On Mon, Feb 25, 2019 at 4:51 PM Scott Michel <scooter.phd at gmail.com> wrote:

> Here's the cut down code. I'd like to replace the "everywhere (mkT
> fixupSymbol)" in the main with an equivalent Generics.SOP construction,
> which effectively recurses into the product to replace/transform the
> AbsAddr with a SymAddr if the hash table lookup succeeds. While I don't
> object to SYB, it seems awkward to "mix and match" the two generic
> libraries.
>
>
> V/R
> -scooter
>
> {-# LANGUAGE DataKinds            #-}
> {-# LANGUAGE TypeFamilies         #-}
> {-# LANGUAGE TemplateHaskell      #-}
> {-# LANGUAGE DeriveDataTypeable #-}
>
> module Main where
>
> import Data.Data
> import Data.Foldable (foldl)
> import Data.Int
> import Data.Word (Word8, Word16)
> import Data.Text (Text)
> import qualified Data.Text as T
> import qualified Data.Text.IO as T
> import Text.Printf
> import Generics.SOP
> import Generics.SOP.TH (deriveGeneric)
> import Data.Generics.Aliases (mkT)
> import Data.Generics.Schemes (everywhere)
> import Data.HashMap.Strict (HashMap)
> import qualified Data.HashMap.Strict as H
> import Data.Sequence (Seq, (><), (|>))
> import qualified Data.Sequence as Seq
>
>
> type Z80addr = Word16
> type Z80word = Word8
>
> class Z80operand x where
>   formatOperand :: x -> Text
>
> main :: IO()
> main = mapM_ T.putStrLn (foldl printIns Seq.empty $ everywhere (mkT
> fixupSymbol) insnSeq)
> -- -------------------------------------------------^ Does this have a
> Generics.SOP equivalent?
>   where
>     printIns accum ins = accum |> T.concat ([mnemonic, gFormatOperands]
> <*> [ins])
>
>     mnemonic (LD _)   = "LD   "
>     mnemonic (CALL _) = "CALL "
>
>     -- Generics.SOP: Fairly straightforward
>     gFormatOperands {-elt-} =
>       T.intercalate ", " . hcollapse . hcmap disOperandProxy (mapIK
> formatOperand) . from {-elt-}
>       where
>         disOperandProxy = Proxy :: Proxy Z80operand
>
>     -- Translate an absolute address, generally hidden inside an
> instruction operand, into a symbolic address
>     -- if present in the symbol table.
>     fixupSymbol addr@(AbsAddr absAddr) = maybe addr SymAddr (absAddr
> `H.lookup` symtab)
>     fixupSymbol other                  = other
>
>     insnSeq :: Seq Z80instruction
>     insnSeq = Seq.singleton (LD (Reg8Imm B 0x0))
>               |> (LD (Reg8Indirect C (AbsAddr 0x1234)))
>               |> (CALL (AbsAddr 0x4567))
>
>     symtab :: HashMap Z80addr Text
>     symtab = H.fromList [ (0x1234, "label1"), (0x4567, "label2")]
>
> -- | Symbolic and absolute addresses. Absolute addresses can be translated
> into symbolic
> -- labels.
> data SymAbsAddr  = AbsAddr Z80addr | SymAddr Text
>   deriving (Eq, Ord, Typeable, Data)
>
> data Z80reg8 = A | B | C
>   deriving (Eq, Ord, Typeable, Data)
>
> -- | Cut down version of the Z80 instruction set
> data Z80instruction = LD OperLD | CALL SymAbsAddr
>   deriving (Eq, Ord, Typeable, Data)
>
> -- | Load operands
> data OperLD = Reg8Imm Z80reg8 Z80word | Reg8Indirect Z80reg8 SymAbsAddr
>   deriving (Eq, Ord, Typeable, Data)
>
> $(deriveGeneric ''SymAbsAddr)
> $(deriveGeneric ''Z80reg8)
> $(deriveGeneric ''Z80instruction)
> $(deriveGeneric ''OperLD)
>
> instance Z80operand Z80word where
>   formatOperand word = T.pack $ printf "0x%04x" word
>
> instance Z80operand SymAbsAddr where
>   formatOperand (AbsAddr addr)  = T.pack $ printf "0x04x" addr
>   formatOperand (SymAddr label) = label
>
> instance Z80operand Z80reg8 where
>   formatOperand A = "A"
>   formatOperand B = "B"
>   formatOperand C = "C"
>
> instance Z80operand OperLD where
>   formatOperand (Reg8Imm reg imm) = T.concat [formatOperand reg, ", ",
> formatOperand imm]
>   formatOperand (Reg8Indirect reg addr) = T.concat [formatOperand reg, ",
> ", formatOperand addr]
>
>
> On Sun, Feb 24, 2019 at 10:07 PM Scott Michel <scooter.phd at gmail.com>
> wrote:
>
>> Before I cut down my code to a test case, are there any examples of a
>> generics-sop equivalent of syb's everywhere/mkT? What's the way to operate
>> on a product, replace the "I" argument with a compatible argument and walk
>> back through the isomorphism, i.e. "to $ <something> $ from".
>>
>> I'm hacking on a Z80 system emulator (TRS-80 Model I system, more
>> specifically). There are a couple of places where it'd be smoother in the
>> disassembler to transform the disassembled instruction sequence (converting
>> addresses to labels) before output. Consequently, cutting down code to an
>> example is a bit painful -- examples would help.
>>
>>
>> -scooter
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20190225/f6ab8996/attachment.html>


More information about the Haskell-Cafe mailing list