use std::fmt::Write; use std::rc::Rc; use tvix_eval::observer::DisassemblingObserver; use web_sys::HtmlTextAreaElement; use yew::prelude::*; use yew::TargetCast; enum Msg { CodeChange(String), } struct Model { code: String, } fn tvixbolt_overview() -> Html { html! { <>
{"This page lets you explore the bytecode generated by the "} {"Tvix"} {" compiler for the Nix language. See the "} {"Tvix announcement"} {" for some background information on Tvix itself."}
{"Tvix is still "}{"extremely work-in-progress"}{" and you "} {"should expect to be able to cause bugs and errors in this tool."}
> } } fn footer_link(location: &'static str, name: &str) -> Html { html! { <> {name}{" | "} > } } fn footer() -> Html { html! { <>{"Enter some Nix code above to get started. Don't know Nix yet? "} {"Check out "} {"nix-1p"} {"!"}
}; } html! { <>{s}
>
}
}
}
impl Output {
fn display(self) -> Html {
html! {
<>
{maybe_show("Parse errors:", &self.parse_errors)}
{maybe_show("Warnings:", &self.warnings)}
{maybe_show("Compiler errors:", &self.compiler_errors)}
{maybe_show("Bytecode:", &String::from_utf8_lossy(&self.bytecode))}
{maybe_show("Runtime errors:", &self.runtime_errors)}
{maybe_show("Output:", &self.output)}
>
}
}
}
fn eval(code: &str) -> Output {
let mut out = Output::default();
if code.is_empty() {
return out;
}
let mut codemap = codemap::CodeMap::new();
let file = codemap.add_file("nixbolt".to_string(), code.into());
let parsed = rnix::ast::Root::parse(code);
let errors = parsed.errors();
if !errors.is_empty() {
for err in errors {
writeln!(&mut out.parse_errors, "parse error: {}", err).unwrap();
}
return out;
}
// If we've reached this point, there are no errors.
let root_expr = parsed
.tree()
.expr()
.expect("expression should exist if no errors occured");
let codemap = Rc::new(codemap);
let mut compilation_observer = DisassemblingObserver::new(codemap, &mut out.bytecode);
let result = tvix_eval::compile(
root_expr,
Some("/nixbolt".into()),
&file,
tvix_eval::global_builtins(),
&mut compilation_observer,
)
.unwrap();
for warning in result.warnings {
writeln!(
&mut out.warnings,
"warning: {:?} at `{}` [line {}]",
warning.kind,
file.source_slice(warning.span),
file.find_line(warning.span.low()) + 1
)
.unwrap();
}
if !result.errors.is_empty() {
for error in &result.errors {
writeln!(
&mut out.compiler_errors,
"error: {:?} at `{}` [line {}]",
error.kind,
file.source_slice(error.span),
file.find_line(error.span.low()) + 1
)
.unwrap();
}
return out;
}
let result = tvix_eval::run_lambda(result.lambda);
match result {
Ok(value) => writeln!(&mut out.output, "{}", value).unwrap(),
Err(err) => writeln!(&mut out.runtime_errors, "runtime error: {:?}", err).unwrap(),
};
out
}
fn main() {
yew::start_app::