haskell - Clean way to do rewrite rules -


i have following toy language:

module lang  data op = move int -- move pointer n steps         | add  int -- add n value under pointer         | skip     -- skip next op if value under pointer 0         | halt     -- end execution         deriving (show, eq)  type program = [op] 

the language has finite tape of memory cells wraps around, , pointer points @ cell. cells zero. program executed repeatedly until halt instruction read.

now write function optimizes given program. here optimizations perform:

| original code       | optimization   | |---------------------|----------------| | move : move b : x | move (a+b) : x | | add  : add  b : x | add  (a+b) : x | | move 0 : x          | x              | | add  0 : x          | x              | | skip : skip : x : y | x : y          | | halt : _            | halt           | 

additionally, can optimization on code not directly after skip, because doing change meaning of program.

is repeatedly pattern matching on list until no more optimizations can performed best/cleanest way this?

what if decide want perform more advanced rewrites these:

| original code                                          | optimization                                   | |--------------------------------------------------------|------------------------------------------------| | if program begins (skip : a)                  | move end of program              | | move x ++ no_skips : move -x ++ no_skips' : move w : q | move x ++ no_skips ++ no_skips' : move w-x : q | 

use maybe's!

@user2407038 told me use maybe in comment

module maybeprog  import lang import control.monad  type opt = program -> maybe program  optimize = untilfail step   step p | p' <- ateverybutskipnextwhen (==skip) rewrite                      . atevery   delnopskip                      $ untilfail moveskips p                , p /= p' = p'                | otherwise = nothing         rewrite = tryall [joinmoves, joinadds, delnopmov, delnopadd, termhalt, reorder]  joinmoves  p = (move : move b : x) <- pure p; $ move (a+b) : x joinadds   p = (add  : add  b : x) <- pure p; $ add  (a+b) : x delnopmov  p = (move 0          : x) <- pure p; x delnopadd  p = (add  0          : x) <- pure p; x delnopskip p = (skip   : skip   : x) <- pure p; x termhalt   p = (halt            : _) <- pure p; [halt] moveskips  p = (skip   : x : y  : z) <- pure p; $ y : z ++ [skip, x]  reorder p =   (move x : rst)      <- pure p   (as, move y : rst') <- break' ismove rst   guard $ x == -y && (/=skip)   (bs, move w :   q ) <- break' ismove rst'   guard $ (/=skip) bs   return $ move x : ++ bs ++ move (w-x) : q  ismove (move _) = true        ismove _        = false  --------  untilfail :: opt -> program -> program untilfail o p | p' <- o p = untilfail o p'               | otherwise   = p  atevery :: opt -> program -> program atevery o p | (x:xs) <- untilfail o p = x : atevery o xs             | otherwise               = []  ateverybutskipnextwhen c o p@(h:_)   | not $ c h   , (x:xs) <- untilfail o p = x : ateverybutskipnextwhen c o xs   | (p1:p2:ps) <- p = p1:p2:ateverybutskipnextwhen c o ps   | otherwise = p ateverybutskipnextwhen _ _ [] = []  tryall :: [opt] -> opt tryall os p =   x : _ <- pure . dropwhile (==nothing) $ ($p) <$> os   return x  break' f p | (x, y) <- break f p            , not $ null y = (x, y)            | otherwise = nothing 

Comments

Popular posts from this blog

ubuntu - PHP script to find files of certain extensions in a directory, returns populated array when run in browser, but empty array when run from terminal -

php - How can i create a user dashboard -

javascript - How to detect toggling of the fullscreen-toolbar in jQuery Mobile? -