Add a viewer tool

This commit is contained in:
Olivier Goffart 2020-05-12 19:19:25 +02:00
parent f88d856990
commit 7d1394e349
4 changed files with 199 additions and 3 deletions

View file

@ -6,6 +6,7 @@ members = [
'sixtyfps_compiler/parser_test_macro', 'sixtyfps_compiler/parser_test_macro',
'api/sixtyfps-rs', 'api/sixtyfps-rs',
'api/sixtyfps-rs/sixtyfps-rs-macro', 'api/sixtyfps-rs/sixtyfps-rs-macro',
'tools/viewer',
'examples/graphicstest', 'examples/graphicstest',
'examples/rusttest', 'examples/rusttest',
'helper_crates/const-field-offset', 'helper_crates/const-field-offset',

View file

@ -66,12 +66,12 @@ pub fn const_field_offset(input: TokenStream) -> TokenStream {
// Build the output, possibly using quasi-quotation // Build the output, possibly using quasi-quotation
let expanded = quote! { let expanded = quote! {
struct #field_struct_name { pub struct #field_struct_name {
#(#fields : usize,)* #(pub #fields : usize,)*
} }
impl #struct_name { impl #struct_name {
/*pub ??? */ const fn field_offsets() -> #field_struct_name { pub const fn field_offsets() -> #field_struct_name {
let mut len = 0usize; let mut len = 0usize;
#field_struct_name { #field_struct_name {
#( #fields : { #( #fields : {

20
tools/viewer/Cargo.toml Normal file
View file

@ -0,0 +1,20 @@
[package]
name = "viewer"
version = "0.1.0"
authors = ["Olivier Goffart <ogoffart@sixtyfps.io>"]
edition = "2018"
[dependencies]
corelib = { path="../../sixtyfps_runtime/corelib" }
sixtyfps_compiler = { path = "../../sixtyfps_compiler", features = ["display-diagnostics"] }
# FIXME: make optional and configurable backends
gl = { path = "../../sixtyfps_runtime/rendering_backends/gl" }
structopt = "0.3.14"
codemap-diagnostic = "0.1.1"
codemap = "0.1"
[[bin]]
name = "viewer"
path = "main.rs"

175
tools/viewer/main.rs Normal file
View file

@ -0,0 +1,175 @@
use corelib::abi::datastructures::{ComponentImpl, ComponentType};
use sixtyfps_compiler::object_tree::Expression;
use std::collections::HashMap;
use structopt::StructOpt;
#[derive(StructOpt)]
struct Cli {
#[structopt(name = "path to .60 file", parse(from_os_str))]
path: std::path::PathBuf,
}
trait PropertyWriter {
unsafe fn write(ptr: *mut u8, value: &Expression);
}
impl PropertyWriter for f32 {
unsafe fn write(ptr: *mut u8, value: &Expression) {
let val: Self = match value {
Expression::NumberLiteral(v) => *v as _,
_ => todo!(),
};
std::ptr::write(ptr as *mut Self, val);
}
}
impl PropertyWriter for u32 {
unsafe fn write(ptr: *mut u8, value: &Expression) {
let val: Self = match value {
Expression::NumberLiteral(v) => *v as _,
_ => todo!(),
};
std::ptr::write(ptr as *mut Self, val);
}
}
impl PropertyWriter for *const i8 {
unsafe fn write(ptr: *mut u8, value: &Expression) {
let val: Self = match value {
Expression::StringLiteral(v) => {
// FIXME that's a leak
std::ffi::CString::new(v.as_str()).unwrap().into_raw() as _
}
_ => todo!(),
};
std::ptr::write(ptr as *mut Self, val);
}
}
unsafe fn construct<T: Default>(ptr: *mut corelib::abi::datastructures::ItemImpl) {
core::ptr::write(ptr as *mut T, T::default());
}
unsafe fn set_property<T: PropertyWriter>(ptr: *mut u8, e: &Expression) {
T::write(ptr, e);
}
unsafe extern "C" fn dummy_destroy(_: *const ComponentType, _: *mut ComponentImpl) {
panic!();
}
#[repr(C)]
struct MyComponentType {
ct: ComponentType,
it: Vec<corelib::abi::datastructures::ItemTreeNode>,
}
unsafe extern "C" fn item_tree(
c: *const ComponentType,
) -> *const corelib::abi::datastructures::ItemTreeNode {
(*(c as *const MyComponentType)).it.as_ptr()
}
struct RuntimeTypeInfo {
vtable: *const corelib::abi::datastructures::ItemVTable,
construct: unsafe fn(*mut corelib::abi::datastructures::ItemImpl),
properties: HashMap<&'static str, (usize, unsafe fn(*mut u8, &Expression))>,
size: usize,
}
fn main() -> std::io::Result<()> {
use sixtyfps_compiler::*;
let args = Cli::from_args();
let source = std::fs::read_to_string(&args.path)?;
let (syntax_node, mut diag) = parser::parse(&source);
let tr = typeregister::TypeRegister::builtin();
let tree = object_tree::Document::from_node(syntax_node, &mut diag, &tr);
if !diag.inner.is_empty() {
diag.print(args.path.to_string_lossy().into_owned(), source);
std::process::exit(-1);
}
use corelib::abi::primitives::{Image, Rectangle};
// FIXME: thus obviously is unsafe and not great
let mut rtti = HashMap::new();
rtti.insert(
"Rectangle",
RuntimeTypeInfo {
vtable: &corelib::abi::primitives::RectangleVTable as _,
construct: construct::<Rectangle>,
properties: [
("x", (Rectangle::field_offsets().x, set_property::<f32> as _)),
("y", (Rectangle::field_offsets().y, set_property::<f32> as _)),
("width", (Rectangle::field_offsets().width, set_property::<f32> as _)),
("height", (Rectangle::field_offsets().height, set_property::<f32> as _)),
("color", (Rectangle::field_offsets().color, set_property::<u32> as _)),
]
.iter()
.cloned()
.collect(),
size: std::mem::size_of::<Rectangle>(),
},
);
rtti.insert(
"Image",
RuntimeTypeInfo {
vtable: &corelib::abi::primitives::ImageVTable as _,
construct: construct::<Image>,
properties: [
("x", (Image::field_offsets().x, set_property::<f32> as _)),
("y", (Image::field_offsets().y, set_property::<f32> as _)),
("width", (Image::field_offsets().width, set_property::<f32> as _)),
("height", (Image::field_offsets().height, set_property::<f32> as _)),
("source", (Image::field_offsets().source, set_property::<*const i8> as _)),
]
.iter()
.cloned()
.collect(),
size: std::mem::size_of::<Image>(),
},
);
let l = lower::LoweredComponent::lower(&*tree.root_component);
let mut tree_array = vec![];
let mut current_offset = 0usize;
let mut items_types = vec![];
generator::build_array_helper(&l, |item, child_offset| {
let rt = &rtti[&*item.native_type.class_name];
tree_array.push(corelib::abi::datastructures::ItemTreeNode::Item {
offset: current_offset as isize,
vtable: rt.vtable,
children_index: child_offset,
chilren_count: item.children.len() as _,
});
items_types.push((current_offset, rt, item.init_properties.clone()));
current_offset += rt.size;
});
let t = ComponentType { create: None, destroy: dummy_destroy, item_tree };
let t = MyComponentType { ct: t, it: tree_array };
let mut my_impl = Vec::<u64>::new();
my_impl.resize(current_offset / 8 + 1, 0);
let mem = my_impl.as_mut_ptr() as *mut u8;
for (offset, rtti, properties) in items_types {
unsafe {
let item = mem.offset(offset as isize);
(rtti.construct)(item as _);
for (prop, expr) in properties {
let (o, set) = rtti.properties[&*prop];
set(item.offset(o as isize), &expr);
}
}
}
gl::sixtyfps_runtime_run_component_with_gl_renderer(
&t as *const MyComponentType as *const ComponentType,
std::ptr::NonNull::new(mem).unwrap().cast(),
);
Ok(())
}