diff --git a/sixtyfps_compiler/generator.rs b/sixtyfps_compiler/generator.rs new file mode 100644 index 000000000..8a7666439 --- /dev/null +++ b/sixtyfps_compiler/generator.rs @@ -0,0 +1,5 @@ +mod cpp; + +pub fn generate(component: &crate::lower::LoweredComponent) { + println!("{}", cpp::generate(component)); +} diff --git a/sixtyfps_compiler/generator/cpp.rs b/sixtyfps_compiler/generator/cpp.rs new file mode 100644 index 000000000..17bee7406 --- /dev/null +++ b/sixtyfps_compiler/generator/cpp.rs @@ -0,0 +1,134 @@ +mod cpp_ast { + + use std::fmt::{Display, Error, Formatter}; + + #[derive(Default, Debug)] + pub struct File { + pub includes: Vec, + pub declarations: Vec, + } + + impl Display for File { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + for i in &self.includes { + writeln!(f, "#include {}", i)?; + } + for d in &self.declarations { + write!(f, "\n{}", d)?; + } + Ok(()) + } + } + + #[derive(Debug, derive_more::Display)] + pub enum Declaration { + Struct(Struct), + Function(Function), + Var(Var), + } + + #[derive(Default, Debug)] + pub struct Struct { + pub name: String, + pub members: Vec, + } + + impl Display for Struct { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + writeln!(f, "struct {} {{", self.name)?; + for m in &self.members { + // FIXME! identation + write!(f, "{}", m)?; + } + writeln!(f, "}};") + } + } + + #[derive(Default, Debug)] + pub struct Function { + pub name: String, + /// (...) -> ... + pub signature: String, + pub is_constructor: bool, + pub statements: Vec, + } + + impl Display for Function { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + if !self.is_constructor { + write!(f, "auto ")?; + } + writeln!(f, "{} {} {{", self.name, self.signature)?; + for s in &self.statements { + writeln!(f, " {}", s)?; + } + writeln!(f, "}}") + } + } + + #[derive(Default, Debug)] + pub struct Var { + pub ty: String, + pub name: String, + pub init: Option, + } + + impl Display for Var { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + write!(f, "{} {}", self.ty, self.name)?; + if let Some(i) = &self.init { + write!(f, " = {}", i)?; + } + writeln!(f, ";") + } + } +} + +pub fn generate(component: &crate::lower::LoweredComponent) -> impl std::fmt::Display { + use cpp_ast::*; + let mut x = File::default(); + + x.includes.push("".into()); + + x.declarations.push(Declaration::Struct(Struct { + name: component.id.clone(), + members: vec![ + Declaration::Var(Var { + ty: component.root_item.native_type.class_name.clone(), + name: "root".to_owned(), + ..Default::default() + }), + Declaration::Function(Function { + name: component.id.clone(), + signature: "()".to_owned(), + is_constructor: true, + statements: component + .root_item + .init_properties + .iter() + .map(|(s, i)| format!("root.{} = \"{}\";", s, i)) + .collect(), + }), + ], + })); + + x.declarations.push(Declaration::Var(Var { + ty: "sixtyfps::ItemTreeNode".to_owned(), + name: format!("{}_children[]", component.id), + init: Some(format!( + "{{ sixtyfps::ItemTreeNode{{0, &{}, 0, 0}} }}", + component.root_item.native_type.vtable + )), + })); + + x.declarations.push(Declaration::Function(Function { + name: "main".into(), + signature: "() -> int".to_owned(), + is_constructor: false, + statements: vec![ + format!("{} component;", component.id), + format!("sixtyfps::run(&component, ComponentType{{ nullptr, nullptr, []{{return &{}_array }} }});", component.id), + ], + })); + x +} diff --git a/sixtyfps_compiler/lib.rs b/sixtyfps_compiler/lib.rs index 15507ed97..c8d3bb419 100644 --- a/sixtyfps_compiler/lib.rs +++ b/sixtyfps_compiler/lib.rs @@ -1,4 +1,6 @@ pub mod diagnostics; +pub mod generator; +pub mod lower; pub mod object_tree; pub mod parser; diff --git a/sixtyfps_compiler/lower.rs b/sixtyfps_compiler/lower.rs new file mode 100644 index 000000000..4e2328009 --- /dev/null +++ b/sixtyfps_compiler/lower.rs @@ -0,0 +1,54 @@ +//! This module contains the code that lower the tree to the datastructure that that the runtime understand +use std::collections::HashMap; +use std::rc::Rc; + +#[derive(Default, Debug)] +pub struct NativeItemType { + /*render_function: String, + geometry_function: String, + imput_function: String,*/ + /// The C symbol of the VTable + pub vtable: String, + + /// The class name + pub class_name: String, +} + +#[derive(Default, Debug)] +pub struct LoweredItem { + pub native_type: Rc, + pub init_properties: HashMap, + pub children: Vec, +} + +#[derive(Default, Debug)] +pub struct LoweredComponent { + pub id: String, + pub root_item: LoweredItem, +} + +impl LoweredComponent { + pub fn lower(component: &crate::object_tree::Component) -> Self { + LoweredComponent { + id: component.id.clone(), + root_item: LoweredComponent::lower_item(&*component.root_element), + } + } + + fn lower_item(element: &crate::object_tree::Element) -> LoweredItem { + // FIXME: lookup base instead of assuming + let native_type = Rc::new(NativeItemType { + vtable: format!("{}VTable", element.base), + class_name: element.base.clone(), + }); + LoweredItem { + native_type, + init_properties: element + .bindings + .iter() + .map(|(s, c)| (s.clone(), c.value.clone())) + .collect(), + children: vec![], + } + } +} diff --git a/sixtyfps_compiler/main.rs b/sixtyfps_compiler/main.rs index 240f22fca..f50504a21 100644 --- a/sixtyfps_compiler/main.rs +++ b/sixtyfps_compiler/main.rs @@ -2,6 +2,8 @@ use structopt::StructOpt; mod diagnostics; +mod generator; +mod lower; mod object_tree; mod parser; @@ -14,9 +16,10 @@ struct Cli { fn main() -> std::io::Result<()> { let args = Cli::from_args(); let source = std::fs::read_to_string(&args.path)?; - let (res, mut diag) = parser::parse(&source); - println!("{:#?}", res); - println!("{:#?}", object_tree::Document::from_node(res, &mut diag)); + let (syntax_node, mut diag) = parser::parse(&source); + //println!("{:#?}", syntax_node); + let tree = object_tree::Document::from_node(syntax_node, &mut diag); + //println!("{:#?}", tree); if !diag.inner.is_empty() { let mut codemap = codemap::CodeMap::new(); let file = codemap.add_file(args.path.to_string_lossy().into_owned(), source); @@ -45,6 +48,10 @@ fn main() -> std::io::Result<()> { Some(&codemap), ); emitter.emit(&diags); + std::process::exit(-1); } + + let l = lower::LoweredComponent::lower(&*tree.root_component); + generator::generate(&l); Ok(()) } diff --git a/sixtyfps_compiler/object_tree.rs b/sixtyfps_compiler/object_tree.rs index a5a7f04a8..996a78c38 100644 --- a/sixtyfps_compiler/object_tree.rs +++ b/sixtyfps_compiler/object_tree.rs @@ -6,7 +6,7 @@ use std::rc::Rc; #[derive(Default, Debug)] pub struct Document { // node: SyntaxNode, - root_component: Rc, + pub root_component: Rc, } impl Document { @@ -24,8 +24,8 @@ impl Document { #[derive(Default, Debug)] pub struct Component { // node: SyntaxNode, - id: String, - root_element: Rc, + pub id: String, + pub root_element: Rc, } impl Component { @@ -44,8 +44,8 @@ impl Component { #[derive(Default, Debug)] pub struct Element { // node: SyntaxNode, - base: String, - bindings: HashMap, + pub base: String, + pub bindings: HashMap, } impl Element { @@ -77,7 +77,7 @@ impl Element { #[derive(Default, Debug)] pub struct CodeStatement { // node: SyntaxNode, - value: String, + pub value: String, } impl CodeStatement { diff --git a/sixtyfps_runtime/corelib/datastructures.rs b/sixtyfps_runtime/corelib/datastructures.rs index b1d058ae3..f47b24d56 100644 --- a/sixtyfps_runtime/corelib/datastructures.rs +++ b/sixtyfps_runtime/corelib/datastructures.rs @@ -2,7 +2,7 @@ type ComponentImpl = (); #[repr(C)] -struct ComponentType { +pub struct ComponentType { /// Allocate an instance of this component create: fn(*const ComponentType) -> *mut ComponentImpl, @@ -25,15 +25,15 @@ type ItemImpl = (); // 64 | RenderNode | render node index #[repr(C)] -struct RenderNode { +pub struct RenderNode { /// Used and modified by the backend, should be initialized to 0 by the user code - cache_index: Cell, + cache_index: core::cell::Cell, /// Set to true by the user code, and reset to false by the backend - dirty_bit: Cell, + dirty_bit: core::cell::Cell, } #[repr(C)] -struct ItemTreeNode { +pub struct ItemTreeNode { /// byte offset where we can find the item (from the *ComponentImpl) offset: isize, /// virtual table of the item @@ -47,23 +47,23 @@ struct ItemTreeNode { } #[repr(C)] -struct ItemVTable { - +#[derive(Default)] +pub struct ItemVTable { // Rectangle: x/y/width/height ==> (path -> vertices/indicies(triangle)) - geometry: fn(*const ItemImpl) -> PrimitiveRectangle, // like kurbo::Rect + pub geometry: Option ()>, // like kurbo::Rect // offset in bytes fromthe *const ItemImpl - renderNodeIndexOffset: usize, + pub render_node_index_offset: Option, // fn(*const ItemImpl) -> usize, // ??? - rendering_info: Option RenderingInfo>, + pub rendering_info: Option RenderingInfo>, /// We would need max/min/preferred size, and all layout info - layouting_info: Option LayoutInfo>, + pub layouting_info: Option LayoutInfo>, /// input event - input_event: Option, + pub input_event: Option, } // given an ItemImpl & ItemVTable @@ -71,20 +71,22 @@ struct ItemVTable { // (2) change the width #[repr(C)] -struct LayoutInfo { +pub struct LayoutInfo { min_size: f32, //... width_offset: isize, } #[repr(C)] -enum RenderingInfo { +pub enum RenderingInfo { NoContents, - Path(Vec), + /*Path(Vec), Image(OpaqueImageHandle, AspectRatio), - Text(String) + Text(String)*/ } +type MouseEvent = (); +/* /* Button { visible: false; text: "foo"} @@ -177,7 +179,7 @@ pub static RECTANGLE_VTABLE: ItemVTable = ItemVTable { //#[derive(SixtyFpsItem)] struct QtButton { text: String, - is_pressed: bool, + is_pressed: bool, } @@ -210,4 +212,5 @@ main() { sixtyfps_runtime::run(&foo, ComponentType{ nullptr, nullptr, []{return array} }) } -"# \ No newline at end of file +"# +*/ diff --git a/sixtyfps_runtime/corelib/lib.rs b/sixtyfps_runtime/corelib/lib.rs index 6d5391c48..b35e28842 100644 --- a/sixtyfps_runtime/corelib/lib.rs +++ b/sixtyfps_runtime/corelib/lib.rs @@ -1,4 +1,6 @@ +pub mod datastructures; pub mod graphics; +pub mod primitives; #[cfg(test)] mod tests { diff --git a/sixtyfps_runtime/corelib/primitives.rs b/sixtyfps_runtime/corelib/primitives.rs new file mode 100644 index 000000000..843d12657 --- /dev/null +++ b/sixtyfps_runtime/corelib/primitives.rs @@ -0,0 +1,16 @@ +// FIXME: more properties +#[repr(C)] +pub struct Rectangle { + // FIXME! this is not suppĂ osed to be a String + color: &'static str, +} + +#[allow(non_upper_case_globals)] +// FIXME +pub static RectangleVTable: crate::datastructures::ItemVTable = crate::datastructures::ItemVTable { + geometry: None, + render_node_index_offset: None, + rendering_info: None, + layouting_info: None, + input_event: None, +};