Use the new interpreter API in things that depends on it

This commit is contained in:
Olivier Goffart 2021-03-15 17:23:17 +01:00
parent 8372d3f6d8
commit 48333370a6
10 changed files with 165 additions and 161 deletions

View file

@ -18,8 +18,8 @@ name = "sixtyfps_node_native"
[dependencies]
once_cell = "1.5"
sixtyfps-compilerlib = { version = "=0.0.5", path="../../../sixtyfps_compiler", features = ["display-diagnostics"] }
sixtyfps-interpreter = { version = "=0.0.5", path="../../../sixtyfps_runtime/interpreter" }
sixtyfps-compilerlib = { version = "=0.0.5", path="../../../sixtyfps_compiler" }
sixtyfps-interpreter = { version = "=0.0.5", path="../../../sixtyfps_runtime/interpreter", features = ["display-diagnostics"] }
sixtyfps-corelib = { version = "=0.0.5", path="../../../sixtyfps_runtime/corelib" }
scoped-tls-hkt = "0.1"
neon = "0.7.0"

View file

@ -13,13 +13,11 @@ use rand::RngCore;
use sixtyfps_compilerlib::langtype::Type;
use sixtyfps_corelib::{ImageReference, SharedVector};
use std::rc::Rc;
mod js_model;
mod persistent_context;
struct WrappedComponentType(Option<Rc<sixtyfps_interpreter::ComponentDescription>>);
struct WrappedComponentRc(Option<sixtyfps_interpreter::ComponentRc>);
struct WrappedComponentType(Option<sixtyfps_interpreter::ComponentDefinition>);
struct WrappedComponentRc(Option<sixtyfps_interpreter::ComponentInstance>);
/// We need to do some gymnastic with closures to pass the ExecuteContext with the right lifetime
type GlobalContextCallback<'c> =
@ -64,21 +62,16 @@ fn load(mut cx: FunctionContext) -> JsResult<JsValue> {
}
None => vec![],
};
let mut compiler_config = sixtyfps_compilerlib::CompilerConfiguration::new(
sixtyfps_compilerlib::generator::OutputFormat::Interpreter,
);
compiler_config.include_paths = include_paths;
let source = std::fs::read_to_string(&path).or_else(|e| cx.throw_error(e.to_string()))?;
let (c, warnings) =
match spin_on::spin_on(sixtyfps_interpreter::load(source, path.into(), compiler_config)) {
(Ok(c), warnings) => (c, warnings),
(Err(()), errors) => {
errors.print();
return cx.throw_error("Compilation error");
}
};
let compiler_config =
sixtyfps_interpreter::CompilerConfiguration::new().with_include_paths(include_paths);
let (c, diags) = spin_on::spin_on(sixtyfps_interpreter::ComponentDefinition::from_path(
path,
compiler_config,
));
warnings.print();
sixtyfps_interpreter::print_diagnostics(&diags);
let c = if let Some(c) = c { c } else { return cx.throw_error("Compilation error") };
let mut obj = SixtyFpsComponentType::new::<_, JsValue, _>(&mut cx, std::iter::empty())?;
cx.borrow_mut(&mut obj, |mut obj| obj.0 = Some(c));
@ -119,7 +112,7 @@ fn make_callback_handler<'cx>(
fn create<'cx>(
cx: &mut CallContext<'cx, impl neon::object::This>,
component_type: Rc<sixtyfps_interpreter::ComponentDescription>,
component_type: sixtyfps_interpreter::ComponentDefinition,
) -> JsResult<'cx, JsValue> {
let component = component_type.clone().create();
let persistent_context = persistent_context::PersistentContext::new(cx);
@ -138,17 +131,16 @@ fn create<'cx>(
.clone();
if let Type::Callback { return_type, .. } = ty {
let fun = value.downcast_or_throw::<JsFunction, _>(cx)?;
component_type
.set_callback_handler(
component.borrow(),
component
.set_callback(
prop_name.as_str(),
make_callback_handler(cx, &persistent_context, fun, return_type),
)
.or_else(|_| cx.throw_error(format!("Cannot set callback")))?;
} else {
let value = to_eval_value(value, ty, cx, &persistent_context)?;
component_type
.set_property(component.borrow(), prop_name.as_str(), value)
component
.set_property(prop_name.as_str(), value)
.or_else(|_| cx.throw_error(format!("Cannot assign property")))?;
}
}
@ -300,7 +292,7 @@ declare_types! {
let this = cx.this();
let ct = cx.borrow(&this, |x| x.0.clone());
let ct = ct.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
Ok(cx.string(ct.id()).as_value(&mut cx))
Ok(cx.string(ct.name()).as_value(&mut cx))
}
method properties(mut cx) {
let this = cx.this();
@ -337,33 +329,31 @@ declare_types! {
Ok(WrappedComponentRc(None))
}
method run(mut cx) {
let mut this = cx.this();
let component = cx.borrow(&mut this, |x| x.0.clone());
let this = cx.this();
let component = cx.borrow(&this, |x| x.0.as_ref().map(|c| c.clone_strong()));
let component = component.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
run_scoped(&mut cx,this.downcast().unwrap(), || {
component.window().show();
sixtyfps_interpreter::run_event_loop();
component.window().hide();
component.run();
Ok(())
})?;
Ok(JsUndefined::new().as_value(&mut cx))
}
method show(mut cx) {
let mut this = cx.this();
let component = cx.borrow(&mut this, |x| x.0.clone());
let this = cx.this();
let component = cx.borrow(&this, |x| x.0.as_ref().map(|c| c.clone_strong()));
let component = component.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
run_scoped(&mut cx,this.downcast().unwrap(), || {
component.window().show();
component.show();
Ok(())
})?;
Ok(JsUndefined::new().as_value(&mut cx))
}
method hide(mut cx) {
let mut this = cx.this();
let component = cx.borrow(&mut this, |x| x.0.clone());
let this = cx.this();
let component = cx.borrow(&this, |x| x.0.as_ref().map(|c| c.clone_strong()));
let component = component.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
run_scoped(&mut cx,this.downcast().unwrap(), || {
component.window().hide();
component.hide();
Ok(())
})?;
Ok(JsUndefined::new().as_value(&mut cx))
@ -371,14 +361,10 @@ declare_types! {
method get_property(mut cx) {
let prop_name = cx.argument::<JsString>(0)?.value();
let this = cx.this();
let lock = cx.lock();
let x = this.borrow(&lock).0.clone();
let component = x.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
generativity::make_guard!(guard);
let component = component.unerase(guard);
let component = cx.borrow(&this, |x| x.0.as_ref().map(|c| c.clone_strong()));
let component = component.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
let value = run_scoped(&mut cx,this.downcast().unwrap(), || {
component.description()
.get_property(component.borrow(), prop_name.as_str())
component.get_property(prop_name.as_str())
.map_err(|_| format!("Cannot read property"))
})?;
to_js_value(value, &mut cx)
@ -386,12 +372,9 @@ declare_types! {
method set_property(mut cx) {
let prop_name = cx.argument::<JsString>(0)?.value();
let this = cx.this();
let lock = cx.lock();
let x = this.borrow(&lock).0.clone();
let component = x.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
generativity::make_guard!(guard);
let component = component.unerase(guard);
let ty = component.description().properties()
let component = cx.borrow(&this, |x| x.0.as_ref().map(|c| c.clone_strong()));
let component = component.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
let ty = component.definition().properties()
.get(&prop_name)
.ok_or(())
.or_else(|()| {
@ -403,8 +386,7 @@ declare_types! {
persistent_context::PersistentContext::from_object(&mut cx, this.downcast().unwrap())?;
let value = to_eval_value(cx.argument::<JsValue>(1)?, ty, &mut cx, &persistent_context)?;
component.description()
.set_property(component.borrow(), prop_name.as_str(), value)
component.set_property(prop_name.as_str(), value)
.or_else(|_| cx.throw_error(format!("Cannot assign property")))?;
Ok(JsUndefined::new().as_value(&mut cx))
@ -413,12 +395,9 @@ declare_types! {
let callback_name = cx.argument::<JsString>(0)?.value();
let arguments = cx.argument::<JsArray>(1)?.to_vec(&mut cx)?;
let this = cx.this();
let lock = cx.lock();
let x = this.borrow(&lock).0.clone();
let component = x.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
generativity::make_guard!(guard);
let component = component.unerase(guard);
let ty = component.description().properties().get(&callback_name)
let component = cx.borrow(&this, |x| x.0.as_ref().map(|c| c.clone_strong()));
let component = component.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
let ty = component.definition().properties().get(&callback_name)
.ok_or(())
.or_else(|()| {
cx.throw_error(format!("Callback {} not found in the component", callback_name))
@ -443,9 +422,8 @@ declare_types! {
};
let res = run_scoped(&mut cx,this.downcast().unwrap(), || {
component.description()
.invoke_callback(component.borrow(), callback_name.as_str(), args.as_slice())
.map_err(|()| "Cannot emit callback".to_string())
component.invoke_callback(callback_name.as_str(), args.as_slice())
.map_err(|_| "Cannot emit callback".to_string())
})?;
to_js_value(res, &mut cx)
}
@ -456,21 +434,17 @@ declare_types! {
let this = cx.this();
let persistent_context =
persistent_context::PersistentContext::from_object(&mut cx, this.downcast().unwrap())?;
let lock = cx.lock();
let x = this.borrow(&lock).0.clone();
let component = x.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
generativity::make_guard!(guard);
let component = component.unerase(guard);
let component = cx.borrow(&this, |x| x.0.as_ref().map(|c| c.clone_strong()));
let component = component.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
let ty = component.description().properties().get(&callback_name)
let ty = component.definition().properties().get(&callback_name)
.ok_or(())
.or_else(|()| {
cx.throw_error(format!("Callback {} not found in the component", callback_name))
})?
.clone();
if let Type::Callback {return_type, ..} = ty {
component.description().set_callback_handler(
component.borrow(),
component.set_callback(
callback_name.as_str(),
make_callback_handler(&mut cx, &persistent_context, handler, return_type)
).or_else(|_| cx.throw_error(format!("Cannot set callback")))?;
@ -485,12 +459,10 @@ declare_types! {
let x = cx.argument::<JsNumber>(0)?.value() as f32;
let y = cx.argument::<JsNumber>(1)?.value() as f32;
let this = cx.this();
let lock = cx.lock();
let comp = this.borrow(&lock).0.clone();
let component = comp.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
let win = component.window();
let component = cx.borrow(&this, |x| x.0.as_ref().map(|c| c.clone_strong()));
let component = component.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
run_scoped(&mut cx,this.downcast().unwrap(), || {
sixtyfps_corelib::tests::sixtyfps_send_mouse_click(&vtable::VRc::into_dyn(component), x, y, &win);
sixtyfps_interpreter::testing::send_mouse_click(&component, x, y);
Ok(())
})?;
Ok(JsUndefined::new().as_value(&mut cx))
@ -499,11 +471,10 @@ declare_types! {
method send_keyboard_string_sequence(mut cx) {
let sequence = cx.argument::<JsString>(0)?.value();
let this = cx.this();
let lock = cx.lock();
let comp = this.borrow(&lock).0.clone();
let component = comp.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
let component = cx.borrow(&this, |x| x.0.as_ref().map(|c| c.clone_strong()));
let component = component.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
run_scoped(&mut cx,this.downcast().unwrap(), || {
sixtyfps_corelib::tests::send_keyboard_string_sequence(&sequence.into(), Default::default(), &component.window());
sixtyfps_interpreter::testing::send_keyboard_string_sequence(&component, sequence.into());
Ok(())
})?;
Ok(JsUndefined::new().as_value(&mut cx))

View file

@ -11,6 +11,9 @@ homepage = "https://sixtyfps.io"
[lib]
path = "lib.rs"
[features]
display-diagnostics = ["sixtyfps-compilerlib/display-diagnostics"]
[dependencies]
sixtyfps-corelib = { version = "=0.0.5", path = "../corelib", features = ["rtti"] }
sixtyfps-rendering-backend-default = { version = "=0.0.5", path = "../../sixtyfps_runtime/rendering_backends/default", features = ["sixtyfps-rendering-backend-gl"] }

View file

@ -8,8 +8,6 @@
Please contact info@sixtyfps.io for more information.
LICENSE END */
#![warn(missing_docs)]
use core::convert::TryInto;
use sixtyfps_corelib::{Brush, ImageReference, PathData, SharedString, SharedVector};
use std::collections::HashMap;
@ -361,7 +359,12 @@ impl ComponentDefinition {
Err(d) => return (None, vec![d]),
};
let (c, diag) = crate::load(source, path.into(), config.config).await;
// We create here a 'static guard. That's alright because we make sure
// in this module that we only use erased component
let guard = unsafe { generativity::Guard::new(generativity::Id::new()) };
let (c, diag) =
crate::dynamic_component::load(source, path.into(), config.config, guard).await;
(c.ok().map(|inner| Self { inner }), diag.into_iter().collect())
}
/// Compile some .60 code into a ComponentDefinition
@ -373,7 +376,17 @@ impl ComponentDefinition {
source_code: &str,
config: CompilerConfiguration,
) -> (Option<Self>, Vec<Diagnostic>) {
let (c, diag) = crate::load(source_code.into(), Default::default(), config.config).await;
// We create here a 'static guard. That's alright because we make sure
// in this module that we only use erased component
let guard = unsafe { generativity::Guard::new(generativity::Id::new()) };
let (c, diag) = crate::dynamic_component::load(
source_code.into(),
Default::default(),
config.config,
guard,
)
.await;
(c.ok().map(|inner| Self { inner }), diag.into_iter().collect())
}
@ -408,6 +421,16 @@ impl ComponentDefinition {
}
}
/// Print the diagnostics to stderr
#[cfg(feature = "display-diagnostics")]
pub fn print_diagnostics(diagnostics: &[Diagnostic]) {
let mut build_diagnostics = sixtyfps_compilerlib::diagnostics::BuildDiagnostics::default();
for d in diagnostics {
build_diagnostics.push_compiler_error(d.clone())
}
build_diagnostics.print();
}
/// This represent an instance of a dynamic component
pub struct ComponentInstance {
inner: vtable::VRc<
@ -417,6 +440,14 @@ pub struct ComponentInstance {
}
impl ComponentInstance {
/// Return the definition for this instance
pub fn definition(&self) -> ComponentDefinition {
// We create here a 'static guard. That's alright because we make sure
// in this module that we only use erased component
let guard = unsafe { generativity::Guard::new(generativity::Id::new()) };
ComponentDefinition { inner: self.inner.unerase(guard).description() }
}
/// Return the value for a public property of this component
pub fn get_property(&self, name: &str) -> Result<Value, GetPropertyError> {
generativity::make_guard!(guard);
@ -426,7 +457,7 @@ impl ComponentInstance {
.map_err(|()| GetPropertyError::NoSuchProperty)
}
/// Return the value for a public property of this component
/// Set the value for a public property of this component
pub fn set_property(&self, name: &str, value: Value) -> Result<(), SetPropertyError> {
generativity::make_guard!(guard);
let comp = self.inner.unerase(guard);
@ -477,7 +508,7 @@ impl ComponentInstance {
/// and [`Self::hide`].
pub fn run(&self) {
self.show();
crate::run_event_loop();
sixtyfps_rendering_backend_default::backend().run_event_loop();
self.hide();
}
@ -594,3 +625,27 @@ impl CompilerConfiguration {
todo!();
}
}
/// A few helper function usefull for tests
pub mod testing {
/// Wrapper around [`sixtyfps_corelib::tests::sixtyfps_send_mouse_click`]
pub fn send_mouse_click(comp: &super::ComponentInstance, x: f32, y: f32) {
sixtyfps_corelib::tests::sixtyfps_send_mouse_click(
&vtable::VRc::into_dyn(comp.inner.clone()),
x,
y,
&comp.inner.window(),
);
}
/// Wrapper around [`sixtyfps_corelib::tests::send_keyboard_string_sequence`]
pub fn send_keyboard_string_sequence(
comp: &super::ComponentInstance,
string: sixtyfps_corelib::SharedString,
) {
sixtyfps_corelib::tests::send_keyboard_string_sequence(
&string,
Default::default(),
&comp.inner.window(),
);
}
}

View file

@ -371,6 +371,7 @@ impl<'id> ComponentDescription<'id> {
///
/// Returns an error if the component is not an instance corresponding to this ComponentDescription,
/// or if the property with this name does not exist in this component
#[allow(unused)]
pub fn set_binding(
&self,
component: ComponentRef,
@ -612,10 +613,19 @@ fn rtti_for_flickable() -> (&'static str, Rc<ItemRTTI>) {
pub async fn load<'id>(
source: String,
path: std::path::PathBuf,
compiler_config: CompilerConfiguration,
mut compiler_config: CompilerConfiguration,
guard: generativity::Guard<'id>,
) -> (Result<Rc<ComponentDescription<'id>>, ()>, sixtyfps_compilerlib::diagnostics::BuildDiagnostics)
{
if compiler_config.style.is_none() && std::env::var("SIXTYFPS_STYLE").is_err() {
// Defaults to native if it exists:
compiler_config.style = Some(if sixtyfps_rendering_backend_default::HAS_NATIVE_STYLE {
"native".to_owned()
} else {
"ugly".to_owned()
});
}
let mut diag = BuildDiagnostics::default();
let syntax_node = parser::parse(source, Some(path.as_path()), &mut diag);
if diag.has_error() {

View file

@ -14,61 +14,31 @@ LICENSE END */
This crate should not be used directly by application using SixtyFPS.
You should use the `sixtyfps` crate instead
*/
#![warn(missing_docs)]
#![doc(html_logo_url = "https://sixtyfps.io/resources/logo.drawio.svg")]
mod api;
mod dynamic_component;
mod dynamic_type;
mod eval;
mod global_component;
mod value_model;
/// FIXME: re-export everything from abi, but and everything else should be private
pub mod api;
pub use api::Value;
pub use sixtyfps_compilerlib::CompilerConfiguration;
use sixtyfps_corelib::component::ComponentVTable;
use std::rc::Rc;
pub fn new_compiler_configuration() -> CompilerConfiguration {
sixtyfps_compilerlib::CompilerConfiguration::new(
sixtyfps_compilerlib::generator::OutputFormat::Interpreter,
)
}
pub type ComponentDescription = dynamic_component::ComponentDescription<'static>;
pub type ComponentBox = dynamic_component::ComponentBox<'static>;
pub type ComponentRc = vtable::VRc<ComponentVTable, dynamic_component::ErasedComponentBox>;
pub async fn load(
source: String,
path: std::path::PathBuf,
mut compiler_config: CompilerConfiguration,
) -> (Result<Rc<ComponentDescription>, ()>, sixtyfps_compilerlib::diagnostics::BuildDiagnostics) {
if compiler_config.style.is_none() && std::env::var("SIXTYFPS_STYLE").is_err() {
// Defaults to native if it exists:
compiler_config.style = Some(if sixtyfps_rendering_backend_default::HAS_NATIVE_STYLE {
"native".to_owned()
} else {
"ugly".to_owned()
});
}
dynamic_component::load(source, path, compiler_config, unsafe {
generativity::Guard::new(generativity::Id::new())
})
.await
}
pub fn run_event_loop() {
sixtyfps_rendering_backend_default::backend().run_event_loop();
}
#[doc(inline)]
pub use api::*;
/// This function can be used to register a custom TrueType font with SixtyFPS,
/// for use with the `font-family` property. The provided path must refer to a valid TrueType
/// font.
pub fn register_font_from_path<P: AsRef<std::path::Path>>(
path: P,
) -> Result<(), Box<dyn std::error::Error>> {
sixtyfps_rendering_backend_default::backend().register_font_from_path(path.as_ref())
}
/// This function can be used to register a custom TrueType font with SixtyFPS,
/// for use with the `font-family` property. The provided slice must be a valid TrueType
/// font.
pub fn register_font_from_memory(data: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
sixtyfps_rendering_backend_default::backend().register_font_from_memory(data)
}

View file

@ -16,6 +16,7 @@ sixtyfps-compilerlib = { path = "../../../sixtyfps_compiler", features = ["displ
test_driver_lib = { path = "../driverlib" }
lazy_static = "1.4.0"
spin_on = "0.1"
itertools = "0.10"
[build-dependencies]
test_driver_lib = { path = "../driverlib" }

View file

@ -7,30 +7,28 @@
This file is also available under commercial licensing terms.
Please contact info@sixtyfps.io for more information.
LICENSE END */
use itertools::Itertools;
use std::error::Error;
pub fn test(testcase: &test_driver_lib::TestCase) -> Result<(), Box<dyn Error>> {
let source = std::fs::read_to_string(&testcase.absolute_path)?;
let include_paths = test_driver_lib::extract_include_paths(&source)
.map(std::path::PathBuf::from)
.collect::<Vec<_>>();
let mut config = sixtyfps_compilerlib::CompilerConfiguration::new(
sixtyfps_compilerlib::generator::OutputFormat::Interpreter,
);
config.include_paths = include_paths;
let mut config =
sixtyfps_interpreter::CompilerConfiguration::new().with_include_paths(include_paths);
let (component, _warnings) = match spin_on::spin_on(sixtyfps_interpreter::load(
source,
testcase.absolute_path.clone(),
config,
)) {
(Ok(c), diagnostics) => (c, diagnostics),
(Err(()), errors) => {
let vec = errors.to_string_vec();
errors.print();
return Err(vec.join("\n").into());
// FIXME: use from_source instead of from_path
let (component, diags) = spin_on::spin_on(
sixtyfps_interpreter::ComponentDefinition::from_path(&testcase.absolute_path, config),
);
let component = match component {
None => {
sixtyfps_interpreter::print_diagnostics(&diags);
return Err(diags.into_iter().map(|d| d.to_string()).join("\n").into());
}
Some(c) => c,
};
component.create();

View file

@ -10,8 +10,7 @@ homepage = "https://sixtyfps.io"
[dependencies]
sixtyfps-corelib = { version = "=0.0.5", path="../../sixtyfps_runtime/corelib" }
sixtyfps-interpreter = { version = "=0.0.5", path = "../../sixtyfps_runtime/interpreter" }
sixtyfps-compilerlib = { version = "=0.0.5", path = "../../sixtyfps_compiler", features = ["display-diagnostics"] }
sixtyfps-interpreter = { version = "=0.0.5", path = "../../sixtyfps_runtime/interpreter", features = ["display-diagnostics"] }
vtable = { version = "0.1", path="../../helper_crates/vtable" }
structopt = "0.3.14"
codemap-diagnostic = "0.1.1"

View file

@ -28,7 +28,6 @@ struct Cli {
fn main() -> std::io::Result<()> {
let args = Cli::from_args();
let source = std::fs::read_to_string(&args.path)?;
args.load_font.map(|fonts| {
fonts.iter().for_each(|font_path| {
@ -38,26 +37,24 @@ fn main() -> std::io::Result<()> {
});
});
let mut compiler_config = sixtyfps_compilerlib::CompilerConfiguration::new(
sixtyfps_compilerlib::generator::OutputFormat::Interpreter,
);
compiler_config.include_paths = args.include_paths;
compiler_config.style = if args.style.is_empty() { None } else { Some(args.style) };
let mut compiler_config =
sixtyfps_interpreter::CompilerConfiguration::new().with_include_paths(args.include_paths);
if !args.style.is_empty() {
compiler_config = compiler_config.with_style(args.style);
}
let c = match spin_on::spin_on(sixtyfps_interpreter::load(source, args.path, compiler_config)) {
(Ok(c), warnings) => {
warnings.print();
c
}
(Err(()), errors) => {
errors.print();
std::process::exit(-1);
}
let (c, diags) = spin_on::spin_on(sixtyfps_interpreter::ComponentDefinition::from_path(
args.path,
compiler_config,
));
sixtyfps_interpreter::print_diagnostics(&diags);
let c = match c {
Some(c) => c,
None => std::process::exit(-1),
};
let component = c.create();
component.window().show();
sixtyfps_interpreter::run_event_loop();
component.window().hide();
component.run();
Ok(())
}