Skip to content

Commit

Permalink
Merge pull request #248 from HigherOrderCO/lazy-io
Browse files Browse the repository at this point in the history
fix IO on lazy mode
  • Loading branch information
tjjfvi authored Apr 2, 2024
2 parents d5ee329 + b86d9ac commit f4c551e
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 90 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 15 additions & 34 deletions src/builtins/exit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::sync::{Arc, Mutex};
use hvmc::{
host::Host,
run::{Def, LabSet, Mode, Net, Port, Tag, Wire},
stdlib::{ArcDef, AsArcDef, HostedDef},
stdlib::HostedDef,
};

use crate::builtins::util::AsDefFunction;
Expand All @@ -26,40 +26,21 @@ pub(crate) fn add_exit_def(host: Arc<Mutex<Host>>) {
// Purposefully deadlock "output" to prevent further reduction
drop(output);

net.link_wire_port(input, ArcDef::new_arc_port(LabSet::ALL, ExitDefGetStatus));
}
}
if M::LAZY {
net.normal_from(input.clone());
exit(net, input.load_target());
} else {
net.link_wire_port(input, Port::new_ref(&*Def::new(LabSet::ALL, (exit, exit))));
}

/// Def that scans for a number, and exits the program with that number as the exit code
///
/// ```txt
/// ExitDefGetStatus ~ {lab a b} // also works on match and op
/// ---
/// ExitDefGetStatus ~ a & ExitDefGetStatus ~ b
///
/// ExitDefGetStatus ~ #num
/// ---
/// process::exit(num)
///
/// ExitDefGetStatus ~ other
/// ---
/// process::exit(-1)
/// ```
struct ExitDefGetStatus;
impl AsArcDef for ExitDefGetStatus {
fn call<M: Mode>(slf: Arc<Def<Self>>, net: &mut Net<M>, port: Port) {
match port.tag() {
Tag::Red | Tag::Var | Tag::Num => {
std::process::exit(port.num().try_into().unwrap_or(-1));
}
Tag::Ref => {
std::process::exit(-1);
}
_ => {
// Commute
let node = port.consume_node();
net.link_wire_port(node.p1, ArcDef::to_port(slf.clone()));
net.link_wire_port(node.p2, ArcDef::to_port(slf));
fn exit<M: Mode>(_: &mut Net<M>, port: Port) {
match port.tag() {
Tag::Num => {
std::process::exit(port.num().try_into().unwrap_or(-1));
}
_ => {
std::process::exit(-1);
}
}
}
}
Expand Down
98 changes: 44 additions & 54 deletions src/builtins/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,9 @@ pub(crate) fn add_fs_defs(
}
impl AsDefFunction for Fs0 {
fn call<M: hvmc::run::Mode>(&self, net: &mut hvmc::run::Net<M>, input: Wire, output: Wire) {
let (wire, port) = net.create_wire();
let slf = self.clone();
let readback_node = hvmc::stdlib::readback(slf.readback_data.host.clone(), port, move |net, tree| {
hvmc::stdlib::readback(net, slf.readback_data.host.clone(), Trg::wire(input), move |net, tree| {
dispatch_dyn_net!(net => {
net.link_wire_port(wire, Port::ERA);
let (term, _errs) = readback_hvmc(&ast::Net { root: tree,redexes: vec![]} , &slf.readback_data.book, &slf.readback_data.labels, false, slf.readback_data.adt_encoding);
let filename = if let Term::Str { ref val } = term {
Some(val.to_string())
Expand All @@ -60,7 +58,6 @@ pub(crate) fn add_fs_defs(
net.link_wire_port(output, ArcDef::new_arc_port(LabSet::ALL, FunctionLike(Fs1 { readback_data: slf.readback_data, save: slf.save, filename })));
})
});
net.link_wire_port(input, readback_node);
}
}

Expand All @@ -73,61 +70,54 @@ pub(crate) fn add_fs_defs(
impl AsDefFunction for Fs1 {
fn call<M: hvmc::run::Mode>(&self, net: &mut hvmc::run::Net<M>, input: Wire, output: Wire) {
if self.save {
let (wire, port) = net.create_wire();
let slf = self.clone();
let mut labels = (*self.readback_data.labels).clone();
let host = self.readback_data.host.clone();
let readback_node = hvmc::stdlib::readback(
self.readback_data.host.clone(),
port,
move |net, tree| {
dispatch_dyn_net!(net => {
let (term, _errs) = readback_hvmc(&ast::Net { root: tree,redexes: vec![]} , &slf.readback_data.book, &slf.readback_data.labels, false, slf.readback_data.adt_encoding);
let contents = if let Term::Str { ref val } = term {
Some(val.to_string())
} else {
None
};
// Save file
let result = match (slf.filename, contents) {
(None, _) => {
Term::encode_err(Term::encode_str(FILENAME_NOT_VALID_MSG))
},
(_, None) => {
Term::encode_err(Term::encode_str(CONTENTS_NOT_VALID_MSG))
hvmc::stdlib::readback(net, self.readback_data.host.clone(), Trg::wire(input), move |net, tree| {
dispatch_dyn_net!(net => {
let (term, _errs) = readback_hvmc(&ast::Net { root: tree,redexes: vec![]} , &slf.readback_data.book, &slf.readback_data.labels, false, slf.readback_data.adt_encoding);
let contents = if let Term::Str { ref val } = term {
Some(val.to_string())
} else {
None
};
// Save file
let result = match (slf.filename, contents) {
(None, _) => {
Term::encode_err(Term::encode_str(FILENAME_NOT_VALID_MSG))
},
(_, None) => {
Term::encode_err(Term::encode_str(CONTENTS_NOT_VALID_MSG))
},
(Some(filename), Some(contents)) => {
match std::fs::write(filename, contents) {
Ok(_) => Term::encode_ok(Term::Era),
Err(e) => Term::encode_err(Term::encode_str(&format!("{FS_ERROR_MSG}{e}"))),
}
},
};
let result = term_to_compat_net(&result, &mut labels);
match net_to_hvmc(&result) {
Ok(result) => {
// Return λx (x result)
let app = net.create_node(hvmc::run::Tag::Ctr, 0);
let lam = net.create_node(hvmc::run::Tag::Ctr, 0);
host.lock().unwrap().encode_net(net, Trg::port(app.p1), &result);
net.link_port_port(app.p0, lam.p1);
net.link_port_port(app.p2, lam.p2);

net.link_wire_port(output, lam.p0);
},
(Some(filename), Some(contents)) => {
match std::fs::write(filename, contents) {
Ok(_) => Term::encode_ok(Term::Era),
Err(e) => Term::encode_err(Term::encode_str(&format!("{FS_ERROR_MSG}{e}"))),
}
Err(_) => {
// If this happens, we can't even report an error to
// the hvm program, so simply print an error, and plug in an ERA
// The other option would be panicking.
eprintln!("{VICIOUS_CIRCLE_MSG}");
net.link_wire_port(output, Port::ERA);
},
};
let result = term_to_compat_net(&result, &mut labels);
match net_to_hvmc(&result) {
Ok(result) => {
// Return λx (x result)
let app = net.create_node(hvmc::run::Tag::Ctr, 0);
let lam = net.create_node(hvmc::run::Tag::Ctr, 0);
host.lock().unwrap().encode_net(net, Trg::port(app.p1), &result);
net.link_wire_port(wire, Port::ERA);
net.link_port_port(app.p0, lam.p1);
net.link_port_port(app.p2, lam.p2);

net.link_wire_port(output, lam.p0);
},
Err(_) => {
// If this happens, we can't even report an error to
// the hvm program, so simply print an error, and plug in an ERA
// The other option would be panicking.
eprintln!("{VICIOUS_CIRCLE_MSG}");
net.link_wire_port(output, Port::ERA);
},
}
})
},
);
net.link_wire_port(input, readback_node);
}
})
});
} else {
let app = net.create_node(hvmc::run::Tag::Ctr, 0);
let result = self
Expand Down

0 comments on commit f4c551e

Please sign in to comment.