Extraction from streams (#25)
All checks were successful
continuous-integration/drone/push Build is passing

Add the ! postfix operator and !! expression.
  Also add the ++ string concatenation operator.
  Also allow specification of standard input in the test scheme.

  Resolves #7, #18.

Co-authored-by: Glen Whitney <glen@studioinfinity.org>
Reviewed-on: #25
Co-Authored-By: Glen Whitney <glen@nobody@nowhere.net>
Co-Committed-By: Glen Whitney <glen@nobody@nowhere.net>
This commit is contained in:
Glen Whitney 2021-03-13 19:30:23 +00:00
parent cc89ad1e93
commit 7feddbcfbe
11 changed files with 106 additions and 11 deletions

View file

@ -17,6 +17,7 @@ rules
defStream: DefGets(x) -> Gets(Stream(), x)
defStream: DefTo(x) -> To(x, Stream())
defStream: DefEmits() -> Emits(Stream())
strategies

View file

@ -23,6 +23,7 @@ rules
import System.IO
data IOStream = StdIO
-- Danger: These currently assume the stream is StdIO
gets :: Show b => a -> b -> IO a
gets s d = do
putStr(show d)
@ -33,6 +34,10 @@ rules
putStr(d)
return s
emit s = do
l <- getLine
return (l ++ "\n")
main = do
[<Preactions>()]return [val]]
@ -41,6 +46,7 @@ rules
hs: (_, LitString(x)) -> <haskLitString>x
hs: (_, EscString(x)) -> x
hs: (_, Sum(x, y)) -> $[([x] + [y])]
hs: (_, Concat(x, y)) -> $[([x] ++ [y])]
hs: (Gets(_, xn), Gets(s, x)) -> v
with v := <newname>"_fostr_get"
@ -52,6 +58,10 @@ rules
hs_gets: (s, xn, x ) -> $[[s] [<hs_getOp>xn] [x]]
hs_getOp = get-type; (?STRING() < !"`getsStr`" + !"`gets`")
hs: (_, Emits(s)) -> v
with v := <newname>"_fostr_emitted"
; <add-preactions>[$[[v] <- emit [s]]]
hs: (_, Terminate(x)) -> $[[x];;]
hs: (_, Sequence(l)) -> <last>l
/* One drawback of using paramorphism is we have to handle lists

View file

@ -3,24 +3,41 @@ imports libstrategolib signatures/- util
rules
js: TopLevel(x) -> $[// Fostr preamble
const _fostr_readline = require('readline');
const _fostr_events = require('events');
const _fostr_rl = _fostr_readline.createInterface({input: process.stdin});
const Stdio = {
gets: v => { process.stdout.write(String(v)); return Stdio; },
gets: v => { process.stdout.write(String(v)); return Stdio; },
emit: async () => {
const [line] = await _fostr_events.once(_fostr_rl, 'line');
return line + "\n"; }
}
function to(data, strm) {
strm.gets(data);
return data;
}
const _fostr_body = async () => {
// End of preamble
[x]]
[x]
// Fostr coda
_fostr_rl.close()
}
_fostr_body();
]
with line := "[line]"
js: Stream() -> $[Stdio]
js: Int(x) -> x
js: LitString(x) -> <javaLitString>x
js: EscString(x) -> x
js: Sum(x,y) -> $[[x] + [y]]
js: Sum(x, y) -> $[[x] + [y]]
js: Concat(x, y) -> $[[x] + [y]]
js: Gets(x, y) -> $[[x].gets([y])]
js: To(x, y) -> $[to([x],[y])]
js: Emits(x) -> $[(await [x].emit())]
js: Terminate(x) -> x
js: Sequence(l) -> <join(|";\n")>l

View file

@ -12,9 +12,10 @@ imports libstrategolib signatures/- util signature/TYPE analysis
rules
ml: (_, TopLevel(x)) -> $[(* fostr preamble *)
type stream = { getS: string -> stream }
type stream = { getS: string -> stream; emitS: unit -> string }
let rec stdio = {
getS = (fun s -> print_string s; stdio)
getS = (fun s -> print_string s; stdio);
emitS = (fun () -> (read_line ()) ^ "\n");
};;
(* End of preamble *)
@ -24,11 +25,15 @@ rules
ml: (_, Int(x)) -> x
ml: (_, LitString(x)) -> $[{|[<un-single-quote>x]|}]
ml: (_, EscString(x)) -> x
ml: (_, Sum(x,y)) -> $[[x] + [y]]
ml: (_, Sum(x, y)) -> $[[x] + [y]]
ml: (_, Concat(x, y)) -> $[[x] ^ [y]]
ml: (Gets(_,yn), Gets(x, y))
-> $[([x]).getS ([<ml_str>(yn,y)])]
ml: (To(xn,_), To(x, y))
-> $[let _fto = ([x]) in (ignore (([y]).getS ([<ml_str>(xn,"_fto")])); _fto)]
ml: (_, Emits(s)) -> $[[s].emitS ()]
ml: (_, Terminate(x)) -> x
ml: (_, Sequence(l)) -> <ml_seq>l

View file

@ -8,6 +8,8 @@ rules
def gets(self, v):
print(v, file=sys.stdout, end='')
return self
def emit(self):
return input() + "\n" # Python inconsistently strips when using input
def to(data,strm):
strm.gets(data)
return data
@ -21,8 +23,10 @@ rules
py: LitString(x) -> $[r[x]]
py: EscString(x) -> x
py: Sum(x,y) -> $[[x] + [y]]
py: Concat(x,y) -> $[[x] + [y]]
py: Gets(x, y) -> $[[x].gets([y])]
py: To(x, y) -> $[to([x],[y])]
py: Emits(x) -> $[[x].emit()]
py: Terminate(x) -> $[[x];]
py: Sequence(l) -> <join(|"\n")>l

View file

@ -222,6 +222,13 @@ This pattern lets us specify error messages.
type_Ex(e2) == STREAM() | error $[Items may only be sent to Streams.]@e2.
/* **/
ty_Ex(Concat(e1, e2)) = STRING() :-
type_Ex(e1) == STRING() | error $[Expression [e1] not String in concat.]@e1,
type_Ex(e2) == STRING() | error $[Expression [e2] not String in concat.]@e2.
ty_Ex(Emits(e)) = STRING() :- // At the moment, only stream is stdio
type_Ex(e) == STREAM() | error $[Only Streams may emit items.]@e.
/** md
```