fostr/trans/haskell.str
Glen Whitney 804a00902a feat: Type-dependent Haskell code generation
Caveat: type is still not being assigned for the Sequence()
  constructor.

  Also fixes the parsing of literal strings (whitespace just after
  the opening quote was being ignored, and was ambiguous just
  before the opening quote).
2021-02-16 09:46:12 -08:00

84 lines
3.0 KiB
Plaintext

module haskell
imports libstrategolib signatures/- util analysis
rules
/* Approach:
A) We will define a local transformation taking a term with value strings
at each child to a value string for the node.
B) We will append IO actions needed to set up for the value progressively
to a Preactions rule (mapping () to the list of actions). There will
be a utility `add-preaction` to append a new clause to value of this
rule.
C) We will use bottomup-para to traverse the full AST with the
transformation from A so that we have access to the original expression
(and get get the Statix-associated type when we need to).
Hence the transformation in (A) must actually take a pair of
an (original) term and a term with value strings at each child,
and be certain to return a value string.
Finally, at the toplevel we emit the result of <Preactions>() before
returning the final value.
*/
hs: (_, TopLevel(val)) -> $[import System.IO
data IOStream = StdIO
gets :: Show b => a -> b -> IO a
gets s d = do
putStr(show d)
return s
getsStr :: a -> String -> IO a
getsStr s d = do
putStr(d)
return s
main = do
[<Preactions>()]return [val]]
hs: (_, Stream()) -> "StdIO"
hs: (_, Int(x)) -> x
hs: (_, LitString(x)) -> <haskLitString>x
hs: (_, Sum(x, y)) -> $[([x] + [y])]
hs: (Gets(_, xn), Gets(s, x)) -> v
with v := <newname>"_fostr_get"
; <add-preactions>[$[[v] <- [<hs_gets>(s, xn, x)]]]
hs: (To(xn, _), To(x, s)) -> v
with v := <newname>"_fostr_to"
; <add-preactions>[$[let [v] = [x]], <hs_gets>(s, xn, v)]
hs_gets: (s, xn, x ) -> $[[s] [<hs_getOp>xn] [x]]
hs_getOp = get-type; (?STRING() < !"`getsStr`" + !"`gets`")
hs: (_, Terminate(x)) -> $[[x];;]
hs: (_, Sequence(l)) -> <last>l
/* One drawback of using paramorphism is at the very leaves we have
to undouble the tuple:
*/
hs: (x, x) -> x where <is-string>x
/* 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
haskLitString = un-single-quote
; string-as-chars(escape-chars(Escape <+ Hascape))
; double-quote
haskell = rules(Preactions: () -> ""); bottomup-para(try(hs))
/* See "Approach" at top of file */
add-preactions = newp := <conc-strings>(<Preactions>(), <lines>)
; rules(Preactions: () -> newp)
// Interface haskell code generation with editor services and file system
to-haskell: (selected, _, _, path, project-path) -> (filename, result)
with filename := <guarantee-extension(|"hs")> path
; result := <haskell> selected