mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-09-17 14:47:21 +03:00
Add HVM.print
[sc-469] (#206)
This commit is contained in:
parent
e7056da312
commit
c03b1d233b
@ -27,9 +27,34 @@ Reached Root
|
||||
|
||||
This will happen whenever there are free variables inside the logged term, or [scopeless lambdas](using-scopeless-lambdas.md) which bind variables that are used outside the logged term.
|
||||
|
||||
## `HVM.print`
|
||||
|
||||
This is very similar to `HVM.log`. However, it can only log strings. It prints these strings directly to stdout, without wrapping them in quotes or escaping them.
|
||||
|
||||
With `HVM.log`:
|
||||
```rs
|
||||
main = (HVM.log "Hi" "Hello world")
|
||||
|
||||
// Program output:
|
||||
"Hi"
|
||||
"Hello world"
|
||||
```
|
||||
However, with `HVM.print`:
|
||||
```rs
|
||||
main = (HVM.print "Hi" "Hello world")
|
||||
|
||||
// Program output:
|
||||
Hi
|
||||
"Hello world"
|
||||
```
|
||||
|
||||
This can be very useful, for example, to print strings with newlines in multiple lines.
|
||||
|
||||
When the first argument is not a string `HVM.print` returns the second argument and no side effects are produced (In other words, it fails silently).
|
||||
|
||||
## `HVM.black_box`
|
||||
|
||||
`HVM.black_box` is simply the identity function, but it does not get [pre-reduced](compiler-options#pre-reduce). This makes it possible to prevent some redexes from getting pre-reduced.
|
||||
`HVM.black_box` is simply the identity function, but it does not get [pre-reduced](compiler-options.md#pre-reduce). This makes it possible to prevent some redexes from getting pre-reduced.
|
||||
|
||||
Example without `HVM.black_box`
|
||||
```rs
|
||||
|
@ -118,7 +118,7 @@ main = (id also_id)
|
||||
|
||||
## Pre-reduce
|
||||
|
||||
Normalizes all functions except main, dereferencing definitions in active positions, and solving annihilations and commutations. It does not reduce [builtin definitions](builtin_defs), such as `HVM.log`.
|
||||
Normalizes all functions except main, dereferencing definitions in active positions, and solving annihilations and commutations. It does not reduce [builtin definitions](builtin-defs.md), such as `HVM.log`.
|
||||
|
||||
Example:
|
||||
```rs
|
||||
|
55
src/lib.rs
55
src/lib.rs
@ -37,27 +37,56 @@ pub const HVM1_ENTRY_POINT: &str = "Main";
|
||||
/// These are the names of builtin defs that are not in the hvm-lang book, but
|
||||
/// are present in the hvm-core book. They are implemented using Rust code by
|
||||
/// [`create_host`] and they can not be rewritten as hvm-lang functions.
|
||||
pub const CORE_BUILTINS: [&str; 2] = ["HVM.log", "HVM.black_box"];
|
||||
pub const CORE_BUILTINS: [&str; 3] = ["HVM.log", "HVM.black_box", "HVM.print"];
|
||||
|
||||
/// Creates a host with the hvm-core primitive definitions built-in.
|
||||
/// This needs the book as an Arc because the closure that logs
|
||||
/// data needs access to the book.
|
||||
pub fn create_host(hvml_book: Arc<Book>, labels: Arc<Labels>, compile_opts: CompileOpts) -> Arc<Mutex<Host>> {
|
||||
pub fn create_host(book: Arc<Book>, labels: Arc<Labels>, compile_opts: CompileOpts) -> Arc<Mutex<Host>> {
|
||||
let host = Arc::new(Mutex::new(Host::default()));
|
||||
let host_clone = host.clone();
|
||||
host.lock().unwrap().insert_def(
|
||||
"HVM.log",
|
||||
hvmc::host::DefRef::Owned(Box::new(LogDef::new(move |wire| {
|
||||
let host = host_clone.lock().unwrap();
|
||||
let tree = host.readback_tree(&wire);
|
||||
let net = hvmc::ast::Net { root: tree, rdex: vec![] };
|
||||
let net = hvmc_to_net(&net);
|
||||
let (mut term, mut readback_errors) = net_to_term(&net, &hvml_book, &labels, false);
|
||||
let resugar_errs = term.resugar_adts(&hvml_book, compile_opts.adt_encoding);
|
||||
term.resugar_builtins();
|
||||
hvmc::host::DefRef::Owned(Box::new(LogDef::new({
|
||||
let host = host.clone();
|
||||
let book = book.clone();
|
||||
let labels = labels.clone();
|
||||
move |wire| {
|
||||
let host = host.lock().unwrap();
|
||||
let tree = host.readback_tree(&wire);
|
||||
let net = hvmc::ast::Net { root: tree, rdex: vec![] };
|
||||
let net = hvmc_to_net(&net);
|
||||
let (mut term, mut readback_errors) = net_to_term(&net, &book, &labels, false);
|
||||
let resugar_errs = term.resugar_adts(&book, compile_opts.adt_encoding);
|
||||
term.resugar_builtins();
|
||||
|
||||
readback_errors.extend(resugar_errs);
|
||||
println!("{}{}", display_readback_errors(&readback_errors), term);
|
||||
readback_errors.extend(resugar_errs);
|
||||
println!("{}{}", display_readback_errors(&readback_errors), term);
|
||||
}
|
||||
}))),
|
||||
);
|
||||
host.lock().unwrap().insert_def(
|
||||
"HVM.print",
|
||||
hvmc::host::DefRef::Owned(Box::new(LogDef::new({
|
||||
let host = host.clone();
|
||||
let book = book.clone();
|
||||
let labels = labels.clone();
|
||||
move |wire| {
|
||||
let host = host.lock().unwrap();
|
||||
let tree = host.readback_tree(&wire);
|
||||
let net = hvmc::ast::Net { root: tree, rdex: vec![] };
|
||||
let net = hvmc_to_net(&net);
|
||||
let (mut term, mut readback_errors) = net_to_term(&net, &book, &labels, false);
|
||||
let resugar_errs = term.resugar_adts(&book, compile_opts.adt_encoding);
|
||||
term.resugar_builtins();
|
||||
|
||||
readback_errors.extend(resugar_errs);
|
||||
match term {
|
||||
Term::Str { val } => {
|
||||
println!("{}", val);
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}))),
|
||||
);
|
||||
let book = ast::Book::from_str("@HVM.black_box = (x x)").unwrap();
|
||||
|
4
tests/golden_tests/run_file/print.hvm
Normal file
4
tests/golden_tests/run_file/print.hvm
Normal file
@ -0,0 +1,4 @@
|
||||
concat (String.nil) str = str
|
||||
concat (String.cons c rest1) str2 = (String.cons c (concat rest1 str2))
|
||||
|
||||
main = (HVM.print (concat "hello " "world") (concat "goodbye " "world"))
|
Loading…
Reference in New Issue
Block a user