Skip to content

Commit

Permalink
feat: Let the run_script functions execute IO actions
Browse files Browse the repository at this point in the history
BREAKING CHANGE

Uses of run_io_expr should be replaced with setting `run_io(true)` on the `Compiler` instance and calling `run_expr`.

```rust
Compiler::new().run_io_expr(...)
Compiler::new().run_io(true).run_expr(...)
```
  • Loading branch information
Marwes committed Nov 2, 2017
1 parent bd43b8a commit 8373f8f
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 78 deletions.
57 changes: 34 additions & 23 deletions src/compiler_pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,30 +360,30 @@ where
}
fn load_script(
self,
_compiler: &mut Compiler,
compiler: &mut Compiler,
vm: &'vm Thread,
filename: &str,
_expr_str: &str,
expr_str: &str,
_: (),
) -> BoxFutureValue<'vm, (), Error> {
use check::metadata;

let CompileValue {
mut expr,
typ,
function,
} = self;
let (metadata, _) = metadata::metadata(&*vm.get_env(), expr.borrow_mut());
let closure = try_future!(vm.global_env().new_global_thunk(function));
let run_io = compiler.run_io;
let filename = filename.to_string();
vm.call_thunk(closure)
.map_err(Error::from)
.and_then(move |(_, value)| {

self.run_expr(compiler, vm, &filename, expr_str, ())
.and_then(move |v| if run_io {
::compiler_pipeline::run_io(vm, v)
} else {
FutureValue::sync(Ok(v)).boxed()
})
.and_then(move |mut value| {
let (metadata, _) = metadata::metadata(&*vm.get_env(), value.expr.borrow_mut());
try_future!(vm.set_global(
closure.function.name.clone(),
typ,
value.id.clone(),
value.typ,
metadata,
value,
*value.value,
));
info!("Loaded module `{}` filename", filename);
FutureValue::sync(Ok(()))
Expand Down Expand Up @@ -514,28 +514,39 @@ where
pub fn run_io<'vm, E>(
vm: &'vm Thread,
v: ExecuteValue<'vm, E>,
) -> BoxFutureValue<'vm, (RootedValue<&'vm Thread>, ArcType), Error> {
) -> BoxFutureValue<'vm, ExecuteValue<'vm, E>, Error>
where
E: Send + 'vm,
{
use check::check_signature;
use vm::api::{VmType, IO};
use vm::api::generic::A;

let ExecuteValue {
typ: actual, value, ..
} = v;
if check_signature(&*vm.get_env(), &actual, &IO::<A>::make_forall_type(vm)) {
if check_signature(&*vm.get_env(), &v.typ, &IO::<A>::make_forall_type(vm)) {
let ExecuteValue {
id,
expr,
typ,
value,
} = v;
vm.execute_io(*value)
.map(move |(_, value)| {
// The type of the new value will be `a` instead of `IO a`
let actual = resolve::remove_aliases_cow(&*vm.get_env(), &actual);
let actual = resolve::remove_aliases_cow(&*vm.get_env(), &typ);
let actual = match **actual {
Type::App(_, ref arg) => arg[0].clone(),
_ => ice!("ICE: Expected IO type found: `{}`", actual),
};
(vm.root_value(value), actual)
ExecuteValue {
id,
expr,
value: vm.root_value(value),
typ: actual,
}
})
.map_err(Error::from)
.boxed()
} else {
FutureValue::sync(Ok((value, actual))).boxed()
FutureValue::sync(Ok(v)).boxed()
}
}
2 changes: 1 addition & 1 deletion src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ fn clear_frames(err: Error, frame_level: usize, mut stack: StackFrame) -> IO<Str

fn run_expr(WithVM { vm, value: expr }: WithVM<&str>) -> IO<String> {
let frame_level = vm.context().stack.get_frames().len();
let run_result = Compiler::new().run_io_expr::<OpaqueValue<&Thread, Hole>>(vm, "<top>", expr);
let run_result = Compiler::new().run_expr::<OpaqueValue<&Thread, Hole>>(vm, "<top>", expr);
let mut context = vm.context();
let stack = StackFrame::current(&mut context.stack);
match run_result {
Expand Down
71 changes: 21 additions & 50 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ pub struct Compiler {
symbols: Symbols,
implicit_prelude: bool,
emit_debug_info: bool,
run_io: bool,
}

impl Default for Compiler {
Expand All @@ -167,6 +168,7 @@ impl Compiler {
symbols: Symbols::new(),
implicit_prelude: true,
emit_debug_info: true,
run_io: false,
}
}

Expand All @@ -185,6 +187,13 @@ impl Compiler {
self
}

/// Sets whether `IO` expressions are evaluated.
/// (default: false)
pub fn run_io(mut self, run_io: bool) -> Compiler {
self.run_io = run_io;
self
}

pub fn mut_symbols(&mut self) -> &mut Symbols {
&mut self.symbols
}
Expand Down Expand Up @@ -430,60 +439,22 @@ impl Compiler {
where
T: Getable<'vm> + VmType + Send + 'vm,
{
let run_io = self.run_io;
let expected = T::make_type(vm);
expr_str
.run_expr(self, vm, name, expr_str, Some(&expected))
.and_then(move |v| {
let ExecuteValue {
typ: actual, value, ..
} = v;
unsafe {
FutureValue::sync(match T::from_value(vm, Variants::new(&value)) {
Some(value) => Ok((value, actual)),
None => Err(Error::from(VmError::WrongType(expected, actual))),
})
}
.and_then(move |v| if run_io {
compiler_pipeline::run_io(vm, v)
} else {
FutureValue::sync(Ok(v)).boxed()
})
.boxed()
}

/// Compiles and runs `expr_str`. If the expression is of type `IO a` the action is evaluated
/// and a value of type `a` is returned
pub fn run_io_expr<'vm, T>(
&mut self,
vm: &'vm Thread,
name: &str,
expr_str: &str,
) -> Result<(T, ArcType)>
where
T: Getable<'vm> + VmType + Send + 'vm,
T::Type: Sized,
{
self.run_io_expr_async(vm, name, expr_str).wait()
}

pub fn run_io_expr_async<'vm, T>(
&mut self,
vm: &'vm Thread,
name: &str,
expr_str: &str,
) -> BoxFutureValue<'vm, (T, ArcType), Error>
where
T: Getable<'vm> + VmType + Send + 'vm,
T::Type: Sized,
{
let expected = T::make_type(vm);
expr_str
.run_expr(self, vm, name, expr_str, Some(&expected))
.and_then(move |v| run_io(vm, v))
.and_then(move |(value, actual)| unsafe {
FutureValue::sync(match T::from_value(vm, Variants::new(&value)) {
Some(value) => Ok((value, actual)),
None => {
error!("Unable to extract value {:?}", value);
Err(Error::from(VmError::WrongType(expected, actual)))
}
})
.and_then(move |execute_value| unsafe {
FutureValue::sync(
match T::from_value(vm, Variants::new(&execute_value.value)) {
Some(value) => Ok((value, execute_value.typ)),
None => Err(Error::from(VmError::WrongType(expected, execute_value.typ))),
},
)
})
.boxed()
}
Expand Down
3 changes: 2 additions & 1 deletion tests/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ fn io_future() {
vm.define_global("test", primitive!(1 test)).unwrap();

let result = Compiler::new()
.run_io_expr::<IO<i32>>(&vm, "<top>", expr)
.run_io(true)
.run_expr::<IO<i32>>(&vm, "<top>", expr)
.unwrap_or_else(|err| panic!("{}", err));

assert_eq!(result.0, IO::Value(124));
Expand Down
6 changes: 4 additions & 2 deletions tests/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ fn read_file() {
wrap (array.index bytes 8)
"#;
let result = Compiler::new()
.run_io_expr_async::<IO<u8>>(&thread, "<top>", text)
.run_io(true)
.run_expr_async::<IO<u8>>(&thread, "<top>", text)
.sync_or_error();

match result {
Expand Down Expand Up @@ -66,7 +67,8 @@ fn run_expr_int() {
"#;
let mut vm = make_vm();
let (result, _) = Compiler::new()
.run_io_expr_async::<IO<String>>(&mut vm, "<top>", text)
.run_io(true)
.run_expr_async::<IO<String>>(&mut vm, "<top>", text)
.sync_or_error()
.unwrap();
match result {
Expand Down
3 changes: 2 additions & 1 deletion tests/support/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ macro_rules! test_expr {
let mut vm = $crate::support::make_vm();
let (value, _) = ::gluon::Compiler::new()
.implicit_prelude(false)
.run_io_expr(&mut vm, "<top>", $expr)
.run_io(true)
.run_expr(&mut vm, "<top>", $expr)
.unwrap_or_else(|err| panic!("{}", err));
match value {
IO::Value(value) => {
Expand Down

0 comments on commit 8373f8f

Please sign in to comment.