Add HVM.print [sc-469] (#206)

This commit is contained in:
FranchuFranchu 2024-02-26 10:01:55 -03:00 committed by GitHub
parent e7056da312
commit c03b1d233b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 73 additions and 15 deletions

View File

@ -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

View File

@ -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

View File

@ -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();

View 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"))