Skip to content

Commit

Permalink
Add function Interactive.useSilently
Browse files Browse the repository at this point in the history
`useSilently file` has the same effect as `use file`, but
does not print to stdout. It is particularly suitable when a
test (`.smli` file) wants to include a preamble but does not
want to include that preamble's output in its own output.

`ScriptTest` should verify that the included file generates
the correct output (e.g. identical to the input, if it is an
`.smli` file, or identical to the `.ref` for other file
types) but it does not currently verify.

Add scott dataset to `relational.smli` by including new file
`scott.smli` using `useSilently`. After the include, there
is a variable `scott` that has fields `emp`, `dept`, `bonus`,
`salgrade`, like the JDBC data source, but stored on the
heap, and in fact overshadowing the JDBC data source.
  • Loading branch information
julianhyde committed Jan 30, 2024
1 parent 37f49ed commit 295d60f
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 19 deletions.
1 change: 1 addition & 0 deletions docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ Exception:
| General.ignore | α → unit | "ignore x" always returns `unit`. The function evaluates its argument but throws away the value. |
| General.op o | (β → γ) (α → β) → α → γ | "f o g" is the function composition of `f` and `g`. Thus, `(f o g) a` is equivalent to `f (g a)`. |
| Interact.use | string → unit | "use f" loads source text from the file named `f`. |
| Interact.useSilently | string → unit | "useSilently f" loads source text from the file named `f`, without printing to stdout. |
| List.nil | α list | "nil" is the empty list. |
| List.null | α list → bool | "null l" returns `true` if the list `l` is empty. |
| List.length | α list → int | "length l" returns the number of elements in the list `l`. |
Expand Down
19 changes: 12 additions & 7 deletions src/main/java/net/hydromatic/morel/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ public void run() {
final Map<String, Binding> outBindings = new LinkedHashMap<>();
final Shell shell = new Shell(this, env, echoLines, outLines, outBindings);
session.withShell(shell, outLines, session1 ->
shell.run(session1, new BufferingReader(in)));
shell.run(session1, new BufferingReader(in), echoLines, outLines));
out.flush();
}

Expand All @@ -236,7 +236,8 @@ static class Shell implements Session.Shell {
this.bindingMap = bindingMap;
}

void run(Session session, BufferingReader in2) {
void run(Session session, BufferingReader in2, Consumer<String> echoLines,
Consumer<String> outLines) {
final MorelParserImpl parser = new MorelParserImpl(in2);
final SubShell subShell =
new SubShell(main, echoLines, outLines, bindingMap, env0);
Expand Down Expand Up @@ -280,7 +281,7 @@ void run(Session session, BufferingReader in2) {
}
}

@Override public void use(String fileName, Pos pos) {
@Override public void use(String fileName, boolean silent, Pos pos) {
throw new UnsupportedOperationException();
}

Expand Down Expand Up @@ -310,7 +311,7 @@ static class SubShell extends Shell {
super(main, env0, echoLines, outLines, outBindings);
}

@Override public void use(String fileName, Pos pos) {
@Override public void use(String fileName, boolean silent, Pos pos) {
outLines.accept("[opening " + fileName + "]");
File file = new File(fileName);
if (!file.isAbsolute()) {
Expand All @@ -324,9 +325,13 @@ static class SubShell extends Shell {
+ ", No such file or directory]");
throw new Codes.MorelRuntimeException(Codes.BuiltInExn.ERROR, pos);
}
try (FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader)) {
run(main.session, new BufferingReader(bufferedReader));
final Consumer<String> echoLines2 = silent ? line -> {} : echoLines;
final Consumer<String> outLines2 = silent ? line -> {} : outLines;
try (FileReader in = new FileReader(file);
Reader bufferedReader =
buffer(main.idempotent ? stripOutLines(in) : in)) {
run(main.session, new BufferingReader(bufferedReader), echoLines2,
outLines2);
} catch (IOException e) {
e.printStackTrace();
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/net/hydromatic/morel/Shell.java
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ private class Use implements Session.Shell {
this.bindings = bindings;
}

@Override public void use(String fileName, Pos pos) {
@Override public void use(String fileName, boolean silent, Pos pos) {
outLines.accept("[opening " + fileName + "]");
File file = new File(fileName);
if (!file.isAbsolute()) {
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/net/hydromatic/morel/compile/BuiltIn.java
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,13 @@ public enum BuiltIn {
INTERACT_USE("Interact", "use", "use", ts ->
ts.fnType(STRING, UNIT)),

/** Function "Interact.useSilently" of type "string &rarr; unit"
*
* <p>"useSilently f" loads source text from the file named `f`,
* without printing to stdout. */
INTERACT_USE_SILENTLY("Interact", "useSilently", "useSilently", ts ->
ts.fnType(STRING, UNIT)),

/** Constant "String.maxSize", of type "int".
*
* <p>"The longest allowed size of a string". */
Expand Down
17 changes: 13 additions & 4 deletions src/main/java/net/hydromatic/morel/eval/Codes.java
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,12 @@ public static Code orElse(Code code0, Code code1) {
};

/** @see BuiltIn#INTERACT_USE */
private static final Applicable INTERACT_USE = new InteractUse(Pos.ZERO);
private static final Applicable INTERACT_USE =
new InteractUse(Pos.ZERO, false);

/** @see BuiltIn#INTERACT_USE_SILENTLY */
private static final Applicable INTERACT_USE_SILENTLY =
new InteractUse(Pos.ZERO, true);

/** Removes wrappers, in particular the one due to
* {@link #wrapRelList(Code)}. */
Expand All @@ -358,18 +363,21 @@ public static Code strip(Code code) {
/** Implements {@link BuiltIn#INTERACT_USE}. */
private static class InteractUse extends ApplicableImpl
implements Positioned {
InteractUse(Pos pos) {
private final boolean silent;

InteractUse(Pos pos, boolean silent) {
super(BuiltIn.INTERACT_USE, pos);
this.silent = silent;
}

@Override public Applicable withPos(Pos pos) {
return new InteractUse(pos);
return new InteractUse(pos, silent);
}

@Override public Object apply(EvalEnv env, Object arg) {
final String f = (String) arg;
final Session session = (Session) env.getOpt(EvalEnv.SESSION);
session.use(f, pos);
session.use(f, silent, pos);
return Unit.INSTANCE;
}
}
Expand Down Expand Up @@ -2783,6 +2791,7 @@ public static Applicable aggregate(Environment env0, Code aggregateCode,
.put(BuiltIn.IGNORE, IGNORE)
.put(BuiltIn.GENERAL_OP_O, GENERAL_OP_O)
.put(BuiltIn.INTERACT_USE, INTERACT_USE)
.put(BuiltIn.INTERACT_USE_SILENTLY, INTERACT_USE_SILENTLY)
.put(BuiltIn.OP_CARET, OP_CARET)
.put(BuiltIn.OP_CONS, OP_CONS)
.put(BuiltIn.OP_DIV, OP_DIV)
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/net/hydromatic/morel/eval/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ public void withoutHandlingExceptions(Consumer<Session> consumer) {
}
}

public void use(String fileName, Pos pos) {
shell.use(fileName, pos);
public void use(String fileName, boolean silent, Pos pos) {
shell.use(fileName, silent, pos);
}

public void handle(MorelException e, StringBuilder buf) {
Expand All @@ -105,7 +105,7 @@ public void handle(MorelException e, StringBuilder buf) {

/** Callback to implement "use" command. */
public interface Shell {
void use(String fileName, Pos pos);
void use(String fileName, boolean silent, Pos pos);

/** Handles an exception. Particular implementations may re-throw the
* exception, or may format the exception to a buffer that will be added to
Expand Down Expand Up @@ -136,7 +136,7 @@ private enum Shells implements Shell {
}
};

@Override public void use(String fileName, Pos pos) {
@Override public void use(String fileName, boolean silent, Pos pos) {
throw new UnsupportedOperationException();
}
}
Expand Down
9 changes: 6 additions & 3 deletions src/test/resources/script/builtIn.smli
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ General;
> val it = {ignore=fn,`op o`=fn}
> : {ignore:'a -> unit, `op o`:('b -> 'c) * ('d -> 'b) -> 'd -> 'c}
Interact;
> val it = {use=fn} : {use:string -> unit}
> val it = {use=fn,useSilently=fn}
> : {use:string -> unit, useSilently:string -> unit}
List;
> val it =
> {all=fn,app=fn,at=fn,collate=fn,concat=fn,drop=fn,exists=fn,filter=fn,
Expand Down Expand Up @@ -2703,7 +2704,8 @@ Sys.env ();
> [("EQUAL","order"),("GREATER","order"),
> ("General",
> "{ignore:forall 'a. 'a -> unit, `op o`:forall 'a 'b 'c. ('b -> 'c) * ('a -> 'b) -> 'a -> 'c}"),
> ("Interact","{use:string -> unit}"),("LESS","order"),
> ("Interact","{use:string -> unit, useSilently:string -> unit}"),
> ("LESS","order"),
> ("List",
> "{all:forall 'a. ('a -> bool) -> 'a list -> bool, app:forall 'a. ('a -> unit) -> 'a list -> unit, at:forall 'a. 'a list * 'a list -> 'a list, collate:forall 'a. ('a * 'a -> order) -> 'a list * 'a list -> order, concat:forall 'a. 'a list list -> 'a list, drop:forall 'a. 'a list * int -> 'a list, exists:forall 'a. ('a -> bool) -> 'a list -> bool, filter:forall 'a. ('a -> bool) -> 'a list -> 'a list, find:forall 'a. ('a -> bool) -> 'a list -> 'a option, foldl:forall 'a 'b. ('a * 'b -> 'b) -> 'b -> 'a list -> 'b, foldr:forall 'a 'b. ('a * 'b -> 'b) -> 'b -> 'a list -> 'b, getItem:forall 'a. 'a list -> ('a * 'a list) option, hd:forall 'a. 'a list -> 'a, last:forall 'a. 'a list -> 'a, length:forall 'a. 'a list -> int, map:forall 'a 'b. ('a -> 'b) -> 'a list -> 'b list, mapPartial:forall 'a 'b. ('a -> 'b option) -> 'a list -> 'b list, nil:forall 'a. 'a list, nth:forall 'a. 'a list * int -> 'a, null:forall 'a. 'a list -> bool, `op @`:forall 'a. 'a list * 'a list -> 'a list, partition:forall 'a. ('a -> bool) -> 'a list -> 'a list * 'a list, rev:forall 'a. 'a list -> 'a list, revAppend:forall 'a. 'a list * 'a list -> 'a list, tabulate:forall 'a. int * (int -> 'a) -> 'a list, take:forall 'a. 'a list * int -> 'a list, tl:forall 'a. 'a list -> 'a list}"),
> ("Math",
Expand Down Expand Up @@ -2766,7 +2768,8 @@ env ();
> [("EQUAL","order"),("GREATER","order"),
> ("General",
> "{ignore:forall 'a. 'a -> unit, `op o`:forall 'a 'b 'c. ('b -> 'c) * ('a -> 'b) -> 'a -> 'c}"),
> ("Interact","{use:string -> unit}"),("LESS","order"),
> ("Interact","{use:string -> unit, useSilently:string -> unit}"),
> ("LESS","order"),
> ("List",
> "{all:forall 'a. ('a -> bool) -> 'a list -> bool, app:forall 'a. ('a -> unit) -> 'a list -> unit, at:forall 'a. 'a list * 'a list -> 'a list, collate:forall 'a. ('a * 'a -> order) -> 'a list * 'a list -> order, concat:forall 'a. 'a list list -> 'a list, drop:forall 'a. 'a list * int -> 'a list, exists:forall 'a. ('a -> bool) -> 'a list -> bool, filter:forall 'a. ('a -> bool) -> 'a list -> 'a list, find:forall 'a. ('a -> bool) -> 'a list -> 'a option, foldl:forall 'a 'b. ('a * 'b -> 'b) -> 'b -> 'a list -> 'b, foldr:forall 'a 'b. ('a * 'b -> 'b) -> 'b -> 'a list -> 'b, getItem:forall 'a. 'a list -> ('a * 'a list) option, hd:forall 'a. 'a list -> 'a, last:forall 'a. 'a list -> 'a, length:forall 'a. 'a list -> int, map:forall 'a 'b. ('a -> 'b) -> 'a list -> 'b list, mapPartial:forall 'a 'b. ('a -> 'b option) -> 'a list -> 'b list, nil:forall 'a. 'a list, nth:forall 'a. 'a list * int -> 'a, null:forall 'a. 'a list -> bool, `op @`:forall 'a. 'a list * 'a list -> 'a list, partition:forall 'a. ('a -> bool) -> 'a list -> 'a list * 'a list, rev:forall 'a. 'a list -> 'a list, revAppend:forall 'a. 'a list * 'a list -> 'a list, tabulate:forall 'a. int * (int -> 'a) -> 'a list, take:forall 'a. 'a list * int -> 'a list, tl:forall 'a. 'a list -> 'a list}"),
> ("Math",
Expand Down
4 changes: 4 additions & 0 deletions src/test/resources/script/relational.smli
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ Sys.set ("printLength", 64);
Sys.set ("stringDepth", ~1);
> val it = () : unit

useSilently "scott.smli";
> [opening scott.smli]
> val it = () : unit

let val emp0 = {id = 100, name = "Fred", deptno = 10} in #id emp0 end;
> val it = 100 : int

Expand Down
99 changes: 99 additions & 0 deletions src/test/resources/script/scott.smli
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
(*
* Licensed to Julian Hyde under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Julian Hyde licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*)
Sys.set ("printLength", 64);
> val it = () : unit

val scott = {
bonus = [] : {comm:real, ename:string, job:string, sal:real} list,
emp = [
{comm = 0.0, deptno = 20, empno = 7369, ename = "SMITH", hiredate = "1980-12-16", job = "CLERK", mgr = 7902, sal = 800.0},
{comm = 300.0, deptno = 30, empno = 7499, ename = "ALLEN", hiredate = "1981-02-19", job = "SALESMAN", mgr = 7698, sal = 1600.0},
{comm = 500.0, deptno = 30, empno = 7521, ename = "WARD", hiredate = "1981-02-21", job = "SALESMAN", mgr = 7698, sal = 1250.0},
{comm = 0.0, deptno = 20, empno = 7566, ename = "JONES", hiredate = "1981-02-03", job = "MANAGER", mgr = 7839, sal = 2975.0},
{comm = 1400.0, deptno = 30, empno = 7654, ename = "MARTIN", hiredate = "1981-09-27", job = "SALESMAN", mgr = 7698, sal = 1250.0},
{comm = 0.0, deptno = 30, empno = 7698, ename = "BLAKE", hiredate = "1981-01-04", job = "MANAGER", mgr = 7839, sal = 2850.0},
{comm = 0.0, deptno = 10, empno = 7782, ename = "CLARK", hiredate = "1981-06-08", job = "MANAGER", mgr = 7839, sal = 2450.0},
{comm = 0.0, deptno = 20, empno = 7788, ename = "SCOTT", hiredate = "1987-04-18", job = "ANALYST", mgr = 7566, sal = 3000.0},
{comm = 0.0, deptno = 10, empno = 7839, ename = "KING", hiredate = "1981-11-16", job = "PRESIDENT", mgr = 0, sal = 5000.0},
{comm = 0.0, deptno = 30, empno = 7844, ename = "TURNER", hiredate = "1981-09-07", job = "SALESMAN", mgr = 7698, sal = 1500.0},
{comm = 0.0, deptno = 20, empno = 7876, ename = "ADAMS", hiredate = "1987-05-22", job = "CLERK", mgr = 7788, sal = 1100.0},
{comm = 0.0, deptno = 30, empno = 7900, ename = "JAMES", hiredate = "1981-12-02", job = "CLERK", mgr = 7698, sal = 950.0},
{comm = 0.0, deptno = 20, empno = 7902, ename = "FORD", hiredate = "1981-12-02", job = "ANALYST", mgr = 7566, sal = 3000.0},
{comm = 0.0, deptno = 10, empno = 7934, ename = "MILLER", hiredate = "1982-01-22", job = "CLERK", mgr = 7782, sal = 1300.0}],
dept = [
{deptno = 10, dname = "ACCOUNTING", loc = "NEW YORK"},
{deptno = 20, dname = "RESEARCH", loc = "DALLAS"},
{deptno = 30, dname = "SALES", loc = "CHICAGO"},
{deptno = 40, dname = "OPERATIONS", loc = "BOSTON"}],
salgrade = [
{grade = 1, hisal = 1200.0, losal = 700.0},
{grade = 2, hisal = 1400.0, losal = 1201.0},
{grade = 3, hisal = 2000.0, losal = 1401.0},
{grade = 4, hisal = 3000.0, losal = 2001.0},
{grade = 5, hisal = 9999.0, losal = 3001.0}]
};
> val scott =
> {bonus=[],
> dept=
> [{deptno=10,dname="ACCOUNTING",loc="NEW YORK"},
> {deptno=20,dname="RESEARCH",loc="DALLAS"},
> {deptno=30,dname="SALES",loc="CHICAGO"},
> {deptno=40,dname="OPERATIONS",loc="BOSTON"}],
> emp=
> [
> {comm=0.0,deptno=20,empno=7369,ename="SMITH",hiredate="1980-12-16",
> job="CLERK",mgr=7902,sal=800.0},
> {comm=300.0,deptno=30,empno=7499,ename="ALLEN",hiredate="1981-02-19",
> job="SALESMAN",mgr=7698,sal=1600.0},
> {comm=500.0,deptno=30,empno=7521,ename="WARD",hiredate="1981-02-21",
> job="SALESMAN",mgr=7698,sal=1250.0},
> {comm=0.0,deptno=20,empno=7566,ename="JONES",hiredate="1981-02-03",
> job="MANAGER",mgr=7839,sal=2975.0},
> {comm=1400.0,deptno=30,empno=7654,ename="MARTIN",hiredate="1981-09-27",
> job="SALESMAN",mgr=7698,sal=1250.0},
> {comm=0.0,deptno=30,empno=7698,ename="BLAKE",hiredate="1981-01-04",
> job="MANAGER",mgr=7839,sal=2850.0},
> {comm=0.0,deptno=10,empno=7782,ename="CLARK",hiredate="1981-06-08",
> job="MANAGER",mgr=7839,sal=2450.0},
> {comm=0.0,deptno=20,empno=7788,ename="SCOTT",hiredate="1987-04-18",
> job="ANALYST",mgr=7566,sal=3000.0},
> {comm=0.0,deptno=10,empno=7839,ename="KING",hiredate="1981-11-16",
> job="PRESIDENT",mgr=0,sal=5000.0},
> {comm=0.0,deptno=30,empno=7844,ename="TURNER",hiredate="1981-09-07",
> job="SALESMAN",mgr=7698,sal=1500.0},
> {comm=0.0,deptno=20,empno=7876,ename="ADAMS",hiredate="1987-05-22",
> job="CLERK",mgr=7788,sal=1100.0},
> {comm=0.0,deptno=30,empno=7900,ename="JAMES",hiredate="1981-12-02",
> job="CLERK",mgr=7698,sal=950.0},
> {comm=0.0,deptno=20,empno=7902,ename="FORD",hiredate="1981-12-02",
> job="ANALYST",mgr=7566,sal=3000.0},
> {comm=0.0,deptno=10,empno=7934,ename="MILLER",hiredate="1982-01-22",
> job="CLERK",mgr=7782,sal=1300.0}],
> salgrade=
> [{grade=1,hisal=1200.0,losal=700.0},{grade=2,hisal=1400.0,losal=1201.0},
> {grade=3,hisal=2000.0,losal=1401.0},{grade=4,hisal=3000.0,losal=2001.0},
> {grade=5,hisal=9999.0,losal=3001.0}]}
> : {bonus:{comm:real, ename:string, job:string, sal:real} list,
> dept:{deptno:int, dname:string, loc:string} list,
> emp:
> {comm:real, deptno:int, empno:int, ename:string, hiredate:string,
> job:string, mgr:int, sal:real} list,
> salgrade:{grade:int, hisal:real, losal:real} list}

(*) End scott.smli

0 comments on commit 295d60f

Please sign in to comment.