Evil Splicer only *thought* he was evil until this commit happened.
So many nasty hacks!
This commit is contained in:
		
					parent
					
						
							
								ce11c339e6
							
						
					
				
			
			
				commit
				
					
						35f2e01c23
					
				
			
		
					 2 changed files with 91 additions and 31 deletions
				
			
		| 
						 | 
					@ -185,11 +185,6 @@ splicesExtractor = rights <$> many extract
 | 
				
			||||||
 - splices on the same line is not currently supported.
 | 
					 - splices on the same line is not currently supported.
 | 
				
			||||||
 - This means that a splice can modify the logical lines within its block
 | 
					 - This means that a splice can modify the logical lines within its block
 | 
				
			||||||
 - as it likes, without interfering with the Coords of other splices.
 | 
					 - as it likes, without interfering with the Coords of other splices.
 | 
				
			||||||
 - 
 | 
					 | 
				
			||||||
 - When splicing in declarations, they are not placed on the line
 | 
					 | 
				
			||||||
 - that defined them, because at least with Yesod, that line has another TH
 | 
					 | 
				
			||||||
 - splice, and things would get mixed up. Since declarations are stand
 | 
					 | 
				
			||||||
 - alone, they can go anywhere, and are added to the very end of the file.
 | 
					 | 
				
			||||||
 -
 | 
					 -
 | 
				
			||||||
 - As well as expanding splices, this can add a block of imports to the
 | 
					 - As well as expanding splices, this can add a block of imports to the
 | 
				
			||||||
 - file. These are put right before the first line in the file that
 | 
					 - file. These are put right before the first line in the file that
 | 
				
			||||||
| 
						 | 
					@ -201,23 +196,16 @@ applySplices destdir imports splices@(first:_) = do
 | 
				
			||||||
	let dest = (destdir </> f)
 | 
						let dest = (destdir </> f)
 | 
				
			||||||
	lls <- map (++ "\n") . lines <$> readFileStrict f
 | 
						lls <- map (++ "\n") . lines <$> readFileStrict f
 | 
				
			||||||
	createDirectoryIfMissing True (parentDir dest)
 | 
						createDirectoryIfMissing True (parentDir dest)
 | 
				
			||||||
	let newcontent = concat $ addimports $
 | 
						let newcontent = concat $ addimports $ expand lls splices
 | 
				
			||||||
		expanddeclarations declarationsplices $
 | 
					 | 
				
			||||||
		expandexpressions lls expressionsplices
 | 
					 | 
				
			||||||
	oldcontent <- catchMaybeIO $ readFileStrict dest
 | 
						oldcontent <- catchMaybeIO $ readFileStrict dest
 | 
				
			||||||
	when (oldcontent /= Just newcontent) $ do
 | 
						when (oldcontent /= Just newcontent) $ do
 | 
				
			||||||
		putStrLn $ "splicing " ++ f
 | 
							putStrLn $ "splicing " ++ f
 | 
				
			||||||
		writeFile dest newcontent
 | 
							writeFile dest newcontent
 | 
				
			||||||
  where
 | 
					  where
 | 
				
			||||||
	(expressionsplices, declarationsplices) =
 | 
					  	expand lls [] = lls
 | 
				
			||||||
		partition isExpressionSplice splices
 | 
					  	expand lls (s:rest)
 | 
				
			||||||
 | 
							| isExpressionSplice s = expand (expandExpressionSplice s lls) rest
 | 
				
			||||||
  	expandexpressions lls [] = lls
 | 
							| otherwise = expand (expandDeclarationSplice s lls) rest
 | 
				
			||||||
  	expandexpressions lls (s:rest) =
 | 
					 | 
				
			||||||
		expandexpressions (expandExpressionSplice s lls) rest
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	expanddeclarations [] lls = lls
 | 
					 | 
				
			||||||
	expanddeclarations l lls = lls ++ map (mangleCode . splicedCode) l
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	addimports lls = case imports of
 | 
						addimports lls = case imports of
 | 
				
			||||||
		Nothing -> lls
 | 
							Nothing -> lls
 | 
				
			||||||
| 
						 | 
					@ -231,6 +219,18 @@ applySplices destdir imports splices@(first:_) = do
 | 
				
			||||||
					, end
 | 
										, end
 | 
				
			||||||
					]
 | 
										]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{- Declaration splices are expanded to replace their whole line. -}
 | 
				
			||||||
 | 
					expandDeclarationSplice :: Splice -> [String] -> [String]
 | 
				
			||||||
 | 
					expandDeclarationSplice s lls = concat [before, [splice], end]
 | 
				
			||||||
 | 
					  where
 | 
				
			||||||
 | 
						cs = spliceStart s
 | 
				
			||||||
 | 
						ce = spliceEnd s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						(before, rest) = splitAt (coordLine cs - 1) lls
 | 
				
			||||||
 | 
						(_oldlines, end) = splitAt (1 + coordLine (offsetCoord ce cs)) rest
 | 
				
			||||||
 | 
						splice = mangleCode $ splicedCode s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{- Expression splices are expanded within their line. -}
 | 
				
			||||||
expandExpressionSplice :: Splice -> [String] -> [String]
 | 
					expandExpressionSplice :: Splice -> [String] -> [String]
 | 
				
			||||||
expandExpressionSplice s lls = concat [before, spliced:padding, end]
 | 
					expandExpressionSplice s lls = concat [before, spliced:padding, end]
 | 
				
			||||||
  where
 | 
					  where
 | 
				
			||||||
| 
						 | 
					@ -290,12 +290,22 @@ expandExpressionSplice s lls = concat [before, spliced:padding, end]
 | 
				
			||||||
mangleCode :: String -> String
 | 
					mangleCode :: String -> String
 | 
				
			||||||
mangleCode = declaration_parens
 | 
					mangleCode = declaration_parens
 | 
				
			||||||
	. remove_declaration_splices
 | 
						. remove_declaration_splices
 | 
				
			||||||
 | 
						. yesod_url_render_hack
 | 
				
			||||||
	. nested_instances 
 | 
						. nested_instances 
 | 
				
			||||||
	. fix_bad_escape 
 | 
						. collapse_multiline_strings
 | 
				
			||||||
	. remove_package_version
 | 
						. remove_package_version
 | 
				
			||||||
  where
 | 
					  where
 | 
				
			||||||
	{- GHC may incorrectly escape "}" within a multi-line string. -}
 | 
					  	{- For some reason, GHC sometimes doesn't like the multiline
 | 
				
			||||||
	fix_bad_escape = replace " \\}" " }"
 | 
						 - strings it creates. It seems to get hung up on \{ at the
 | 
				
			||||||
 | 
						 - start of a new line sometimes, wanting it to not be escaped.
 | 
				
			||||||
 | 
						 -
 | 
				
			||||||
 | 
						 - To work around what is likely a GHC bug, just collapse
 | 
				
			||||||
 | 
						 - multiline strings. -}
 | 
				
			||||||
 | 
						collapse_multiline_strings = parsecAndReplace $ do
 | 
				
			||||||
 | 
							string "\\\n"
 | 
				
			||||||
 | 
							many1 $ oneOf " \t"
 | 
				
			||||||
 | 
							string "\\"
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	{- GHC may output this:
 | 
						{- GHC may output this:
 | 
				
			||||||
	 -
 | 
						 -
 | 
				
			||||||
| 
						 | 
					@ -328,14 +338,12 @@ mangleCode = declaration_parens
 | 
				
			||||||
	 -   "blaze-html-0.4.3.1:Text.Blaze.Internal.preEscapedText" 
 | 
						 -   "blaze-html-0.4.3.1:Text.Blaze.Internal.preEscapedText" 
 | 
				
			||||||
	 -   "ghc-prim:GHC.Types.:"
 | 
						 -   "ghc-prim:GHC.Types.:"
 | 
				
			||||||
	 -}
 | 
						 -}
 | 
				
			||||||
	remove_package_version s = case parse findQualifiedSymbols "" s of
 | 
						remove_package_version = parsecAndReplace $
 | 
				
			||||||
		Left e -> s
 | 
							mangleSymbol <$> qualifiedSymbol
 | 
				
			||||||
		Right symbols -> concat $ 
 | 
					 | 
				
			||||||
			map (either (\c -> [c]) mangleSymbol) symbols
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	findQualifiedSymbols :: Parser [Either Char String]
 | 
						mangleSymbol "GHC.Types." = ""
 | 
				
			||||||
	findQualifiedSymbols = many $
 | 
						mangleSymbol "GHC.Tuple." = ""
 | 
				
			||||||
		try (Right <$> qualifiedSymbol) <|> (Left <$> anyChar)
 | 
						mangleSymbol s = s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	qualifiedSymbol :: Parser String
 | 
						qualifiedSymbol :: Parser String
 | 
				
			||||||
	qualifiedSymbol = do
 | 
						qualifiedSymbol = do
 | 
				
			||||||
| 
						 | 
					@ -346,9 +354,60 @@ mangleCode = declaration_parens
 | 
				
			||||||
	token :: Parser String
 | 
						token :: Parser String
 | 
				
			||||||
	token = many1 $ satisfy isAlphaNum <|> oneOf "-.'"
 | 
						token = many1 $ satisfy isAlphaNum <|> oneOf "-.'"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mangleSymbol "GHC.Types." = ""
 | 
					{- This works around a problem in the expanded template haskell for Yesod
 | 
				
			||||||
	mangleSymbol "GHC.Tuple.()" = "()"
 | 
					 - type-safe url rendering.
 | 
				
			||||||
	mangleSymbol s = s
 | 
					 -
 | 
				
			||||||
 | 
					 - It generates code like this:
 | 
				
			||||||
 | 
					 - 
 | 
				
			||||||
 | 
					 -                                  (toHtml
 | 
				
			||||||
 | 
					 -                                     (\ u_a2ehE -> urender_a2ehD u_a2ehE []
 | 
				
			||||||
 | 
					 -                                        (CloseAlert aid)))));
 | 
				
			||||||
 | 
					 -
 | 
				
			||||||
 | 
					 - Where urender_a2ehD is the function returned by getUrlRenderParams.
 | 
				
			||||||
 | 
					 - But, that function that only takes 2 params, not 3.
 | 
				
			||||||
 | 
					 - And toHtml doesn't take a parameter at all!
 | 
				
			||||||
 | 
					 - 
 | 
				
			||||||
 | 
					 - So, this modifes the code, to look like this:
 | 
				
			||||||
 | 
					 - 
 | 
				
			||||||
 | 
					 -                                  (toHtml
 | 
				
			||||||
 | 
					 -                                     (flip urender_a2ehD []
 | 
				
			||||||
 | 
					 -                                        (CloseAlert aid)))));
 | 
				
			||||||
 | 
					 - 
 | 
				
			||||||
 | 
					 - FIXME: Investigate and fix this properly.
 | 
				
			||||||
 | 
					 -}
 | 
				
			||||||
 | 
					yesod_url_render_hack :: String -> String
 | 
				
			||||||
 | 
					yesod_url_render_hack = parsecAndReplace $ do
 | 
				
			||||||
 | 
						string "(toHtml"
 | 
				
			||||||
 | 
						whitespace
 | 
				
			||||||
 | 
						string "(\\"
 | 
				
			||||||
 | 
						whitespace
 | 
				
			||||||
 | 
						token
 | 
				
			||||||
 | 
						whitespace
 | 
				
			||||||
 | 
						string "->"
 | 
				
			||||||
 | 
						whitespace
 | 
				
			||||||
 | 
						renderer <- token
 | 
				
			||||||
 | 
						whitespace
 | 
				
			||||||
 | 
						token
 | 
				
			||||||
 | 
						whitespace
 | 
				
			||||||
 | 
						return $ "(toHtml (flip " ++ renderer ++ " "
 | 
				
			||||||
 | 
					  where
 | 
				
			||||||
 | 
						whitespace :: Parser String
 | 
				
			||||||
 | 
						whitespace = many $ oneOf " \t\r\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						token :: Parser String
 | 
				
			||||||
 | 
						token = many1 $ satisfy isAlphaNum <|> oneOf "_"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{- Given a Parser that finds strings it wants to modify,
 | 
				
			||||||
 | 
					 - and returns the modified string, does a mass 
 | 
				
			||||||
 | 
					 - find and replace throughout the input string.
 | 
				
			||||||
 | 
					 - Rather slow, but crazy powerful. -}
 | 
				
			||||||
 | 
					parsecAndReplace :: Parser String -> String -> String
 | 
				
			||||||
 | 
					parsecAndReplace p s = case parse find "" s of
 | 
				
			||||||
 | 
						Left e -> s
 | 
				
			||||||
 | 
						Right l -> concatMap (either (\c -> [c]) id) l
 | 
				
			||||||
 | 
					  where
 | 
				
			||||||
 | 
					  	find :: Parser [Either Char String]
 | 
				
			||||||
 | 
						find = many $ try (Right <$> p) <|> (Left <$> anyChar)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
main :: IO ()
 | 
					main :: IO ()
 | 
				
			||||||
main = go =<< getArgs
 | 
					main = go =<< getArgs
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,8 @@
 | 
				
			||||||
 -
 | 
					 -
 | 
				
			||||||
 - ** DO NOT COMMIT ** 
 | 
					 - ** DO NOT COMMIT ** 
 | 
				
			||||||
 -}
 | 
					 -}
 | 
				
			||||||
 | 
					import qualified Data.Monoid
 | 
				
			||||||
 | 
					import qualified Data.Foldable
 | 
				
			||||||
import qualified Data.Text
 | 
					import qualified Data.Text
 | 
				
			||||||
import qualified Data.Text.Lazy.Builder
 | 
					import qualified Data.Text.Lazy.Builder
 | 
				
			||||||
import qualified Text.Shakespeare
 | 
					import qualified Text.Shakespeare
 | 
				
			||||||
| 
						 | 
					@ -12,7 +14,6 @@ import qualified Text.Hamlet
 | 
				
			||||||
import qualified Text.Julius
 | 
					import qualified Text.Julius
 | 
				
			||||||
import qualified Text.Css
 | 
					import qualified Text.Css
 | 
				
			||||||
import qualified "blaze-markup" Text.Blaze.Internal
 | 
					import qualified "blaze-markup" Text.Blaze.Internal
 | 
				
			||||||
import qualified Data.Monoid
 | 
					 | 
				
			||||||
import qualified Yesod.Widget
 | 
					import qualified Yesod.Widget
 | 
				
			||||||
import qualified Yesod.Routes.TH.Types
 | 
					import qualified Yesod.Routes.TH.Types
 | 
				
			||||||
{- End EvilSplicer headers. -}
 | 
					{- End EvilSplicer headers. -}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue