From 8655440ae3f42543ad5d2a980cef389529867f4b Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sun, 4 Sep 2022 15:16:27 +0300 Subject: feat(corp/tvixbolt): check in initial tvixbolt version This is the code backing the small site currently deployed at https://tazj.in/blobs/nixbolt/index.html This relies on a newer version of Tvix than is available in depot and a bunch of other stuff that isn't public yet, so for now no build file is provided as this is heavily work-in-progress. Change-Id: I7a8e4dbf4e11d1c70175f929e65f40ff69acbbd9 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6315 Tested-by: BuildkiteCI Reviewed-by: tazjin --- corp/tvixbolt/src/main.rs | 187 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 corp/tvixbolt/src/main.rs (limited to 'corp/tvixbolt/src/main.rs') diff --git a/corp/tvixbolt/src/main.rs b/corp/tvixbolt/src/main.rs new file mode 100644 index 000000000000..9ed79aa0da82 --- /dev/null +++ b/corp/tvixbolt/src/main.rs @@ -0,0 +1,187 @@ +use std::{fmt::Write, rc::Rc}; +use web_sys::HtmlTextAreaElement; +use yew::prelude::*; +use yew::TargetCast; + +enum Msg { + CodeChange(String), +} + +struct Model { + code: String, +} + +impl Component for Model { + type Message = Msg; + type Properties = (); + + fn create(_ctx: &Context) -> Self { + Self { + code: String::new(), + } + } + + fn update(&mut self, _ctx: &Context, msg: Self::Message) -> bool { + match msg { + Msg::CodeChange(new_code) => { + self.code = new_code; + true + } + } + } + + fn view(&self, ctx: &Context) -> Html { + // This gives us a component's "`Scope`" which allows us to send messages, etc to the component. + let link = ctx.link(); + html! { +
+

{"tvixbolt"}

+
+
+ {"Input"} + +
+ + +
+ +
+ + +
+
+
+
+

{"Result:"}

+ {eval(&self.code).display()} +
+ } + } +} + +#[derive(Default)] +struct Output { + parse_errors: String, + warnings: String, + compiler_errors: String, + runtime_errors: String, + output: String, + bytecode: Vec, +} + +fn maybe_show(title: &str, s: &str) -> Html { + if s.is_empty() { + html! {} + } else { + html! { + <> +

{title}

+
{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 == "" { + 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 mut result = tvix_eval::compiler::compile( + root_expr, + Some("/nixbolt".into()), + &file, + tvix_eval::builtins::global_builtins(), + Rc::new(codemap), + ) + .unwrap(); + + let lambda = Rc::new(result.lambda); + + tvix_eval::disassembler::disassemble_lambda(&mut out.bytecode, lambda.clone()); + + out.bytecode.append(&mut result.output); + + 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::vm::run_lambda(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::(); +} -- cgit 1.4.1