module util::Eval
Provides string-based programmatic access to a fully functional Rascal execution engine.
Usage
import util::Eval;
Dependencies
extend Exception;
extend util::Reflective;
import IO;
data Result
Results encode the output of a call to eval
.
data Result[&T]
= ok()
| result(&T val)
;
ok
reflects the execution was succesful while there was no output. For example a call toprintln
would produceok()
.result
captures a value of a certain type, which is parameterized as&T
.
data RuntimeException
data RuntimeException
= StaticError(str message, loc location)
;
eval
will throw the first static error that is blocking the execution of a command.
data RascalRuntime
A reusable instance of the Rascal runtime system configured by a specific PathConfig.
data RascalRuntime
= evaluator(
PathConfig pcfg,
void () reset,
Result[&T] (type[&T] typ, str command) eval,
type[value] (str command) staticTypeOf,
void (int duration) setTimeout
)
;
pcfg
documents the configuration parameters for this specific Rascal run-timereset()
when called clears the heap of imported modules and all the local declarations in the top-level module instance.eval(typ, command)
evaluates the command, expecting a result of typetyp
.- The
typ
parameter must be a supertype of any output expected from theeval
command. If this is not the case, then a run-time exception will be thrown. It is always safe to put#value
there. - The
command
parameter can be one of Statement, Declaration, Import, Extend or SyntaxDefinition. - For evaluating an Expression simply add a semicolon to the end:
1 + 1;
- The
- staticTypeOf(command) computes the static type of the entire command and returns it as a reified type.
- setTimeout(duration) sets the timeout in milliseconds for both the eval and the staticTypeOf function. A negative number disables the timeout feature. By default the timeout is off.
Examples
rascal>import util::Eval;
ok
rascal>e = createRascalRuntime();
RascalRuntime: evaluator(
pathConfig(),
function(|file:///home/runner/actions-runner/_work/rascal/rascal/src/org/rascalmpl/library/util/Eval.rsc|(3876,10,<91,55>,<91,65>)),
function(|file:///home/runner/actions-runner/_work/rascal/rascal/src/org/rascalmpl/library/util/Eval.rsc|(3876,10,<91,55>,<91,65>)),
function(|file:///home/runner/actions-runner/_work/rascal/rascal/src/org/rascalmpl/library/util/Eval.rsc|(3876,10,<91,55>,<91,65>)),
function(|file:///home/runner/actions-runner/_work/rascal/rascal/src/org/rascalmpl/library/util/Eval.rsc|(3876,10,<91,55>,<91,65>)))
rascal>e.eval(#int, "2 * 3;");
Result[int]: result(6)
A run-time can keep state between calls of eval
:
rascal>import util::Eval;
ok
rascal>e = createRascalRuntime();
RascalRuntime: evaluator(
pathConfig(),
function(|file:///home/runner/actions-runner/_work/rascal/rascal/src/org/rascalmpl/library/util/Eval.rsc|(3876,10,<91,55>,<91,65>)),
function(|file:///home/runner/actions-runner/_work/rascal/rascal/src/org/rascalmpl/library/util/Eval.rsc|(3876,10,<91,55>,<91,65>)),
function(|file:///home/runner/actions-runner/_work/rascal/rascal/src/org/rascalmpl/library/util/Eval.rsc|(3876,10,<91,55>,<91,65>)),
function(|file:///home/runner/actions-runner/_work/rascal/rascal/src/org/rascalmpl/library/util/Eval.rsc|(3876,10,<91,55>,<91,65>)))
rascal>e.eval(#void, "import IO;");
Result[void]: ok()
rascal>e.eval(#int, "int a = 1;");
Result[int]: result(1)
rascal>e.eval(#void, "println(a)");
1
Result[void]: ok()
Benefits
- Creating a single run-time engine is an expensive operation. By reusing it you
can safe a lot of time and space. Use
.reset()
to reuse the configuration while dropping all other state and returning to an initial runtime. - The PathConfig parameter completelu defines the configuration of the Rascal Runtime.
Pitfalls
- To turn a value string into an actual value, it's better and faster to use Read Text Value String or Read Text Value File.
- Parsing file paths is better done using Loc From Unix Path and Loc From Windows Path.
- A Rascal Runtime is neither thread-safe nor thread-friendly.
staticTypeOf
is an abstract interpreter which can take as much time as running the program.
function createRascalRuntime
Workhorse to instantiate a working Rascal Runtime/.
RascalRuntime createRascalRuntime(PathConfig pcfg=pathConfig())
See Rascal Runtime on how to use a configured and stateful runtime to evaluate Rascal commands or the static type checker.
function eval
Evaluate a single command and return its return value.
deprecated: marked for future deletion Use Create Rascal Runtime for better efficiency/configurability.
Result[&T] eval(type[&T] typ, str command, int duration=-1, PathConfig pcfg=pathConfig())
throws Timeout, StaticError, ParseError
This creates a Rascal Runtime, uses it to evaluate one command, and then discards the runtime again.
function eval
Evaluate a list of command and return the value of the last command.
deprecated: marked for future deletion Use Create Rascal Runtime for better efficiency/configurability.
Result[&T] eval(type[&T] typ, list[str] commands, int duration=-1, PathConfig pcfg=pathConfig())
throws Timeout, StaticError, ParseError
This creates a Rascal Runtime, uses it to evaluate some commands, and then discards the runtime again.
function eval
Evaluate a list of command and return the value of the last command.
deprecated: marked for future deletion Use Create Rascal Runtime instead for better efficiency and configurability.
Result[value] eval(list[str] commands, int duration=-1, PathConfig pcfg=pathConfig())
throws Timeout, StaticError, ParseError
This creates a Rascal Runtime, uses it to evaluate some commands, and then discards the runtime again.
function eval
Evaluate a command and return the value, unless the duration
amount of milliseconds has passed first.
deprecated: marked for future deletion Use Create Rascal Runtime for better efficiency/configurability.
Result[&T] eval(type[&T] typ, str command, int duration) throws Timeout, StaticError, ParseError
function eval
Evaluate a list of commands and return the value of the last command, unless the duration
amount of milliseconds has passed first.
deprecated: marked for future deletion Use Create Rascal Runtime for better efficiency/configurability.
Result[&T] eval(type[&T] typ, list[str] commands, int duration) throws Timeout, StaticError, ParseError
Result[value] eval(list[str] commands, int duration)
function evalType
Give input string to the Rascal evaluator and return its type as string.
deprecated: marked for future deletion Use Create Rascal Runtime for better efficiency/configurability.
str evalType(str command, PathConfig pcfg=pathConfig(), int duration = -1) throws Timeout, StaticError, ParseError
function evalType
Give input strings to the Rascal evaluator and return the type of the last command as a string.
deprecated: marked for future deletion Use Create Rascal Runtime for better efficiency/configurability.
str evalType(list[str] commands, PathConfig pcfg=pathConfig(), int duration = -1) throws Timeout, StaticError, ParseError
function evalType
Return the static type of the given command unless duration
milliseconds pass before that.
deprecated: marked for future deletion Use Create Rascal Runtime for better efficiency/configurability.
str evalType(str command, int duration, PathConfig pcfg=pathConfig()) throws Timeout, StaticError, ParseError
function evalType
Give list of commands to the Rascal evaluator and return the type of the last one within duration ms.
deprecated: marked for future deletion Use Create Rascal Runtime for better efficiency/configurability.
str evalType(list[str] commands, int duration, PathConfig pcfg=pathConfig()) throws Timeout, StaticError, ParseError
Tests
test stateFulEvalCanReset
Tests and demonstrates how to work with an encapsulated stateful Rascal runtime.
test bool stateFulEvalCanReset() {
e = createRascalRuntime();
// import works
e.eval(#void, "import IO;");
// declaration
e.eval(#int, "int a = 42;");
// use of previous declaration
assert e.eval(#int, "2 * a;") == result(84);
// use of previous import without error
e.eval(#void, "println(a)");
// clear everything
e.reset();
try {
// use of undeclared variable
e.eval(#int, "a");
assert false;
}
catch StaticError(_, _):
assert true;
return true;
}
test evalTimeoutWorks
Tests and demonstrates using a Rascal runtime with a millisecond timeout feature.
test bool evalTimeoutWorks() {
e = createRascalRuntime();
e.setTimeout(10);
try {
e.eval(#int, "(0 | it + 1 | i \<- [0..1000000])");
assert false;
}
catch Timeout():
assert true;
return true;
}
test evalWithOwnPathConfig
test bool evalWithOwnPathConfig() {
e = createRascalRuntime(
pcfg=pathConfig(
srcs=[|memory://evalTests|]
)
);
writeFile(|memory://evalTests/MyTestModule.rsc|,
"module MyTestModule
'extend IO;
'public int a = 42;");
e.eval(#void, "import MyTestModule;");
e.eval(#void, "println(a)");
return e.eval(#int, "a") == result(42);
}
test testStaticTypeOf
test bool testStaticTypeOf() {
e = createRascalRuntime();
return e.staticTypeOf("1") == #int;
}