module haskell imports libstrategolib signatures/- util rules /* Approach: Generate code from the bottom up. At every node, we create a pair of the implementation and necessary preamble of IO actions. We concatenate preambles as we go up. Finally, at the toplevel we emit the preamble before returning the final value. */ hs: TopLevel((c,p)) -> $[import System.IO data IOStream = StdIO gets :: Show b => a -> b -> IO a gets s d = do putStr(show d) return s main = do [p]return [c]] hs: Stream() -> ("StdIO", "") hs: Int(x) -> (x, "") hs: LitString(x) -> ($["[x]"], "") hs: Sum( (c, p), (d, q)) -> ($[([c] + [d])], (p,q)) hs: Gets((c, p), (d, q)) -> (c,d,(p,q),"fosgt") hsget: (s, x, p, v) -> (v, [p, $[[v] <- [s] `gets` [x]], "\n"]) hs: To( (c, p), (d, q)) -> (c,d,(p,q),"fosto") hsto: (x, s, p, v) -> (v, [p, $[let [v] = [x]], "\n", $[[s] `gets` [v]], "\n"]) hs: Terminate((c,p)) -> ($[[c];;], p) hs: Sequence(l) -> (l, l) /* Characters we need to escape in Haskell string constants */ Hascape: ['\t' | cs ] -> ['\', 't' | cs ] /* I think I can just use ASCII constants for characters... */ Hascape: [ 0 | cs ] -> ['\', '0' | cs ] Hascape: [ 7 | cs ] -> ['\', 'a' | cs ] // Alert Hascape: [ 8 | cs ] -> ['\', 'b' | cs ] // Backspace Hascape: [ 11 | cs ] -> ['\', 'v' | cs ] // Vertical tab Hascape: [ 12 | cs ] -> ['\', 'f' | cs ] // Form feed strategies HaskellEscape = Escape <+ Hascape haskell = bottomup(try(hs)) // Interface haskell code generation with editor services and file system to-haskell: (selected, _, _, path, project-path) -> (filename, result) with filename := path ; result := selected