📄 stepgen.lhs
字号:
\begin{code}module StepGen ( Code, Expression, gencode, doexp, docode, doline, doblock, dodebug, comment, if_, ifelse_, (|?|), (|:|), ifdef, ifdefelse, casedef, casedefined, whether_or_not, declare, for_loop, for_true_false, for_any_one_of, sum_for_any_one_of, sum_true_false, (|+|), (|-|), (|*|), (|+=|), (|-=|), (|=|), (<<), ) whereimport FiniteMapimport Monad ( liftM )\end{code}\begin{code}newtype CC a = CC (FiniteMap String Bool -> (FiniteMap String Bool, a))instance Monad CC where (CC a) >>= b = CC f where f st = let (st', x) = a st CC bb = b x in bb st' return a = CC $ \st -> (st, a)type Expression = CC Stringtype Code = CC [String]gencode :: Code -> Stringgencode (CC code) = unlines $ snd $ code emptyFM\end{code}\begin{code}for_true_false :: CODE a => String -> a -> Codefor_true_false s x = do check <- istrueCC s if check == Nothing then do docode [withCC s False $ docode x, withCC s True $ docode x] else docode xfor_any_one_of :: CODE a => [String] -> a -> Codefor_any_one_of [] x = docode xfor_any_one_of [b] x = withCC b True $ docode xfor_any_one_of (b:bs) x = do check <- istrueCC b if check == Just False then for_any_one_of bs $ docode x else docode [withCC b True $ with_all_false bs $ docode x, withCC b False $ for_any_one_of bs $ docode x]sum_true_false :: EXPRESSION a => String -> a -> Expressionsum_true_false b e = do check <- istrueCC b if check == Nothing then (withCC b True $ expression e) |+| (withCC b False $ expression e) else expression esum_for_any_one_of :: EXPRESSION a => [String] -> a -> Expressionsum_for_any_one_of [] e = expression "0"sum_for_any_one_of [b] e = withCC b True $ expression esum_for_any_one_of (b:bs) e = do check <- istrueCC b if check == Just False then sum_for_any_one_of bs $ expression e else (withCC b True $ with_all_false bs $ expression e) |+| (withCC b False $ sum_for_any_one_of bs e)with_all_false [] x = xwith_all_false (b:bs) x = withCC b False $ with_all_false bs xfor_loop :: CODE a => String -> String -> a -> Codefor_loop i num inside = ifelse_ (num++"==1") ( docode [doexp $ "const int "<<i<<" = 0", docode inside] ) ( docode [doline $ "for (int "<<i<<"=0; "<<i<<"<"<<num<<"; "<<i<<"++) {", liftM (map (" "++)) (docode inside), doline "}"] )if_ :: CODE a => String -> a -> Codeif_ b thendo = ifelseCC b (docode thendo) (return []) $ \thethen _ -> if is_empty thethen then return [] else docode [doline $ "if (" ++ b ++ ") {", return $ map (" "++) thethen, doline "}" ]ifdef :: CODE a => String -> a -> Codeifdef b thendo = ifdefelse b (docode thendo) (doexp "")ifdefelse :: CODE a => String -> a -> a -> Codeifdefelse b thendo elsedo = do check <- istrueCC b if check == Just True then docode thendo else docode elsedocasedef :: EXPRESSION a => [String] -> (String -> a) -> a -> Expressioncasedef [] _ other = expression othercasedef (b:bs) e other = do check <- istrueCC b if check == Just True then expression $ e b else casedef bs e othercasedefined :: EXPRESSION a => [String] -> (String -> a) -> a -> Expressioncasedefined [] _ other = expression othercasedefined (b:bs) e other = do check <- istrueCC b if check /= Nothing then expression $ e b else casedef bs e otherifelse_ :: (CODE a, CODE b) => String -> a -> b -> Codeifelse_ b thendo elsedo = ifelseCC b (docode thendo) (docode elsedo) $ \thethen theelse -> case (is_empty thethen, is_empty theelse) of (True,True) -> return [] (True,_) -> return theelse (_,True) -> return thethen _ -> docode [doline $ "if (" ++ b ++ ") {", return $ map (" "++) thethen, doline $ "} else { // not "++b, return $ map (" "++) theelse, doline "}" ]is_empty [] = Trueis_empty _ = Falsewhether_or_not :: CODE a => String -> a -> Codewhether_or_not s x = ifelse_ s x x(|?|) :: (EXPRESSION a, EXPRESSION b) => String -> a -> b -> Expressioninfixl 8 |?|(|?|) b x y = ifelseCC b (expression x) (expression y) $ \xx yy -> return $ "("++b++") ? "++p xx++" : "++p yy(|:|) :: a -> ainfixr 4 |:|(|:|) a = adeclare :: CODE a => String -> Bool -> a -> Codedeclare s b x = do check <- istrueCC s if check == Just (not b) then return [] else do setCC s b docode x\end{code}\begin{code}(<<) :: (EXPRESSION a, EXPRESSION b) => a -> b -> Expressioninfixr 8 <<(<<) x y = do xe <- expression x ye <- expression y return $ xe++ye(|-|) :: (EXPRESSION a, EXPRESSION b) => a -> b -> Expressioninfixr 5 |-|(|-|) x y = do xe <- expression x ye <- expression y if xe == "0" then if ye == "0" then return "0" else return $ " - "++ye else if ye == "0" then return xe else return $ padd xe++" - "++padd ye(|+|) :: (EXPRESSION a, EXPRESSION b) => a -> b -> Expressioninfixr 5 |+|(|+|) x y = do xe <- expression x ye <- expression y if xe == "0" then return ye else if ye == "0" then return xe else return $ padd xe++" + "++p ye(|+=|) :: (EXPRESSION a, EXPRESSION b) => a -> b -> Expressioninfixr 3 |+=|x |+=| y = do xe <- expression x ye <- expression y if ye == "0" then return "" else return $ xe++" += "++ye(|-=|) :: (EXPRESSION a, EXPRESSION b) => a -> b -> Expressioninfixr 3 |-=|x |-=| y = do xe <- expression x ye <- expression y if ye == "0" then return "" else return $ xe++" -= "++ye(|=|) :: (EXPRESSION a, EXPRESSION b) => a -> b -> Expressioninfixr 3 |=|x |=| y = do xe <- expression x ye <- expression y return $ xe++" = "++ye(|*|) :: (EXPRESSION a, EXPRESSION b) => a -> b -> Expressioninfixr 6 |*|(|*|) x y = do xe <- expression x ye <- expression y case (xe,ye) of ("0",_) -> return "0" (_,"0") -> return "0" ("1",_) -> return ye (_,"1") -> return xe _ -> return $ padd xe++"*"++padd yep s | '?' `elem` s = "("++s++")"p s = spadd s | '+' `elem` s = "("++s++")"padd s | '-' `elem` s = "("++s++")"padd s | '?' `elem` s = "("++s++")"padd s = s\end{code}\begin{code}class EXPRESSION s where expression :: s -> Expressioninstance EXPRESSION Expression where expression x = xinstance EXPRESSION String where expression s = return sdodebug :: EXPRESSION a => a -> Codedodebug e = do o <- expression e d <- deb return ["// "++o, "// "++d] where deb = CC $ \st -> (st, show $ fmToList st)comment :: CODE a => String -> a -> Codecomment c x = docode [return ["// "++c], docode x]doline :: EXPRESSION a => a -> Codedoline e = do o <- expression e return [o]doexp :: EXPRESSION a => a -> Codedoexp e = do o <- expression e if o == "" then return [] else return $ linebreak $ o++";"linebreak s | length (dropWhile (==' ') s) < 40 = [s]linebreak s = let spaces = takeWhile (==' ') s body = dropWhile (==' ') s in -- ( case break (==' ') $ drop 55 body of (_,"") -> [s] ("",_) -> [s] (first,second) -> (spaces++take 55 body++first) : linebreak (spaces++" "++second) doexps :: EXPRESSION a => [a] -> Codedoexps es = do os <- sequence $ map expression es return $ map (++";") os\end{code}\begin{code}class CODE s where docode :: s -> Codeinstance CODE Code where docode x = xinstance CODE a => CODE [a] where docode co = do c <- sequence $ map docode co return $ concat cdoblock :: (EXPRESSION a, CODE b) => a -> b -> Codedoblock thefor job = do j <- docode job if is_empty j then return j else docode [doline $ add_brace $ expression thefor, indent job, doline "}"] where add_brace :: Expression -> Expression add_brace = liftM (++" {")indent :: CODE a => a -> Codeindent c = liftM (map (" "++)) $ docode c\end{code}\begin{code}istrueCC :: String -> CC (Maybe Bool)istrueCC s = CC $ \st -> (st, lookupFM st s)setCC :: String -> Bool -> CC ()setCC s b = CC $ \st -> (addToFM (delFromFM st s) s b, ())withCC :: String -> Bool -> CC a -> CC awithCC s b (CC x) = CC $ \st -> (st, snd $ x $ addToFM (delFromFM st s) s b)ifelseorCC :: String -> CC a -> CC a -> CC a -> CC aifelseorCC s thendo elsedo eitherdo = do istrue <- istrueCC s case istrue of Just True -> thendo Just False -> elsedo Nothing -> eitherdoifelseCC :: Eq a => String -> CC a -> CC a -> (a -> a -> CC a) -> CC aifelseCC s thendo elsedo doif = do istrue <- istrueCC s case istrue of Just True -> thendo Just False -> elsedo Nothing -> do tt <- tryWith s True thendo ee <- tryWith s False elsedo if tt == ee then return tt else doif tt eetryWith :: String -> Bool -> CC a -> CC atryWith s b (CC x) = CC $ \st -> (st, snd $ x (addToFM (delFromFM st s) s b))\end{code}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -