feat: Type-dependent Haskell code generation
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
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).
This commit is contained in:
parent
5cd75b8177
commit
804a00902a
@ -11,7 +11,8 @@ language as possible to work in, given that I inevitably will be doing a
|
|||||||
bunch of coding. The language will be centrally organized around the
|
bunch of coding. The language will be centrally organized around the
|
||||||
concept of "streams" (somewhat in the spirit of
|
concept of "streams" (somewhat in the spirit of
|
||||||
[streem](https://github.com/matz/streem) and/or
|
[streem](https://github.com/matz/streem) and/or
|
||||||
[Orc](http://orc.csres.utexas.edu/index.shtml)). In fact all higher-type
|
[Orc](http://orc.csres.utexas.edu/index.shtml), or to a lesser extent,
|
||||||
|
[Sisal-is](https://github.com/parsifal-47/sisal-is)). In fact all higher-type
|
||||||
entities will be cast in terms of streams, or in slogan form, "++f++unctions
|
entities will be cast in terms of streams, or in slogan form, "++f++unctions
|
||||||
and (binary) ++o++perators are ++str++eams" (hence the name "fostr").
|
and (binary) ++o++perators are ++str++eams" (hence the name "fostr").
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ lexical sorts
|
|||||||
|
|
||||||
lexical syntax
|
lexical syntax
|
||||||
|
|
||||||
STRING_LITERAL = ~[\']*
|
STRING_LITERAL = "'"~[\']*"'"
|
||||||
|
|
||||||
context-free sorts
|
context-free sorts
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ context-free syntax
|
|||||||
TermEx.Terminate = <<Ex>;>
|
TermEx.Terminate = <<Ex>;>
|
||||||
|
|
||||||
Ex.Int = INT
|
Ex.Int = INT
|
||||||
Ex.LitString = <'<STRING_LITERAL>'>
|
Ex.LitString = STRING_LITERAL
|
||||||
Ex.Stream = <stream>
|
Ex.Stream = <stream>
|
||||||
Ex.Sum = <<Ex> + <Ex>> {left}
|
Ex.Sum = <<Ex> + <Ex>> {left}
|
||||||
Ex.Gets = [[Ex] << [Ex]] {left}
|
Ex.Gets = [[Ex] << [Ex]] {left}
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
module basic
|
module basic
|
||||||
language fostr
|
language fostr
|
||||||
|
|
||||||
|
|
||||||
test hw1_type [[
|
test hw1_type [[
|
||||||
[[stream]] << [['Hello, world!']]
|
[[stream]] << [['Hello, world! ']] << [[3+2]] << ' times.'
|
||||||
]]
|
]]
|
||||||
run get-type on #1 to STREAM()
|
run get-type on #1 to STREAM()
|
||||||
run get-type on #2 to STRING()
|
run get-type on #2 to STRING()
|
||||||
|
run get-type on #3 to INT()
|
||||||
run get-type to STREAM()
|
run get-type to STREAM()
|
||||||
/** writes
|
/** writes
|
||||||
Hello, world!**/
|
Hello, world! 5 times.**/
|
||||||
|
|
||||||
/** md
|
/** md
|
||||||
Title: A whirlwind tour of fostr
|
Title: A whirlwind tour of fostr
|
||||||
|
@ -1,15 +1,25 @@
|
|||||||
module haskell
|
module haskell
|
||||||
imports libstrategolib signatures/- util
|
imports libstrategolib signatures/- util analysis
|
||||||
rules
|
rules
|
||||||
/* Approach: Generate code from the bottom up.
|
/* Approach:
|
||||||
At every node, we create a pair of the implementation and
|
A) We will define a local transformation taking a term with value strings
|
||||||
necessary preamble of IO actions.
|
at each child to a value string for the node.
|
||||||
We concatenate preambles as we go up.
|
B) We will append IO actions needed to set up for the value progressively
|
||||||
Finally, at the toplevel we emit the preamble before returning the
|
to a Preactions rule (mapping () to the list of actions). There will
|
||||||
final value.
|
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((c,p)) -> $[import System.IO
|
hs: (_, TopLevel(val)) -> $[import System.IO
|
||||||
data IOStream = StdIO
|
data IOStream = StdIO
|
||||||
|
|
||||||
gets :: Show b => a -> b -> IO a
|
gets :: Show b => a -> b -> IO a
|
||||||
@ -17,25 +27,35 @@ rules
|
|||||||
putStr(show d)
|
putStr(show d)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
getsStr :: a -> String -> IO a
|
||||||
|
getsStr s d = do
|
||||||
|
putStr(d)
|
||||||
|
return s
|
||||||
|
|
||||||
main = do
|
main = do
|
||||||
[p]return [c]]
|
[<Preactions>()]return [val]]
|
||||||
|
|
||||||
hs: Stream() -> ("StdIO", "")
|
hs: (_, Stream()) -> "StdIO"
|
||||||
hs: Int(x) -> (x, "")
|
hs: (_, Int(x)) -> x
|
||||||
hs: LitString(x)
|
hs: (_, LitString(x)) -> <haskLitString>x
|
||||||
-> ($["[<string-as-chars(escape-chars(HaskellEscape))>x]"], "")
|
hs: (_, Sum(x, y)) -> $[([x] + [y])]
|
||||||
hs: Sum( (c, p), (d, q)) -> ($[([c] + [d])], <conc-strings>(p,q))
|
|
||||||
|
|
||||||
hs: Gets((c, p), (d, q)) -> <hsget>(c,d,<conc-strings>(p,q),<newname>"fosgt")
|
hs: (Gets(_, xn), Gets(s, x)) -> v
|
||||||
hsget: (s, x, p, v) -> (v, <concat-strings>[p, $[[v] <- [s] `gets` [x]],
|
with v := <newname>"_fostr_get"
|
||||||
"\n"])
|
; <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: To( (c, p), (d, q)) -> <hsto>(c,d,<conc-strings>(p,q),<newname>"fosto")
|
hs_gets: (s, xn, x ) -> $[[s] [<hs_getOp>xn] [x]]
|
||||||
hsto: (x, s, p, v) -> (v, <concat-strings>[p, $[let [v] = [x]], "\n",
|
hs_getOp = get-type; (?STRING() < !"`getsStr`" + !"`gets`")
|
||||||
$[[s] `gets` [v]], "\n"])
|
|
||||||
|
|
||||||
hs: Terminate((c,p)) -> ($[[c];;], p)
|
hs: (_, Terminate(x)) -> $[[x];;]
|
||||||
hs: Sequence(l) -> (<last; Fst>l, <map(Snd); concat-strings>l)
|
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 */
|
/* Characters we need to escape in Haskell string constants */
|
||||||
Hascape: ['\t' | cs ] -> ['\', 't' | cs ]
|
Hascape: ['\t' | cs ] -> ['\', 't' | cs ]
|
||||||
@ -47,9 +67,15 @@ rules
|
|||||||
Hascape: [ 12 | cs ] -> ['\', 'f' | cs ] // Form feed
|
Hascape: [ 12 | cs ] -> ['\', 'f' | cs ] // Form feed
|
||||||
|
|
||||||
strategies
|
strategies
|
||||||
HaskellEscape = Escape <+ Hascape
|
haskLitString = un-single-quote
|
||||||
|
; string-as-chars(escape-chars(Escape <+ Hascape))
|
||||||
|
; double-quote
|
||||||
|
|
||||||
haskell = bottomup(try(hs))
|
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
|
// Interface haskell code generation with editor services and file system
|
||||||
to-haskell: (selected, _, _, path, project-path) -> (filename, result)
|
to-haskell: (selected, _, _, path, project-path) -> (filename, result)
|
||||||
|
@ -13,7 +13,7 @@ rules
|
|||||||
|
|
||||||
js: Stream() -> $[Stdio]
|
js: Stream() -> $[Stdio]
|
||||||
js: Int(x) -> x
|
js: Int(x) -> x
|
||||||
js: LitString(x) -> $['[<string-as-chars(escape-chars(JavaEscape))>x]']
|
js: LitString(x) -> <javaLitString>x
|
||||||
js: Sum(x,y) -> $[[x] + [y]]
|
js: Sum(x,y) -> $[[x] + [y]]
|
||||||
js: Gets(x, y) -> $[[x].gets([y])]
|
js: Gets(x, y) -> $[[x].gets([y])]
|
||||||
js: To(x, y) -> $[to([x],[y])]
|
js: To(x, y) -> $[to([x],[y])]
|
||||||
@ -29,7 +29,9 @@ rules
|
|||||||
Jscape: [ 12 | cs ] -> ['\', 'f' | cs ] // Form feed
|
Jscape: [ 12 | cs ] -> ['\', 'f' | cs ] // Form feed
|
||||||
|
|
||||||
strategies
|
strategies
|
||||||
JavaEscape = Escape <+ Jscape
|
javaLitString = un-single-quote
|
||||||
|
; string-as-chars(escape-chars(Escape <+ Jscape))
|
||||||
|
; single-quote
|
||||||
|
|
||||||
javascript = bottomup(try(js))
|
javascript = bottomup(try(js))
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ rules
|
|||||||
|
|
||||||
py: Stream() -> $[Stdio]
|
py: Stream() -> $[Stdio]
|
||||||
py: Int(x) -> x
|
py: Int(x) -> x
|
||||||
py: LitString(x) -> $[r'[x]']
|
py: LitString(x) -> $[r[x]]
|
||||||
py: Sum(x,y) -> $[[x] + [y]]
|
py: Sum(x,y) -> $[[x] + [y]]
|
||||||
py: Gets(x, y) -> $[[x].gets([y])]
|
py: Gets(x, y) -> $[[x].gets([y])]
|
||||||
py: To(x, y) -> $[to([x],[y])]
|
py: To(x, y) -> $[to([x],[y])]
|
||||||
|
Loading…
Reference in New Issue
Block a user