Skip to main content

phlow/
lib.rs

1use std::any::Any;
2
3pub use annotate;
4use annotate::{Function, Module};
5pub use phlow_derive::{RawView, environment, extensions, view};
6
7pub use crate::method::*;
8pub use crate::object::*;
9pub use crate::views::*;
10pub use ctor;
11
12pub mod cloning;
13mod method;
14mod object;
15pub mod printing;
16mod views;
17
18#[macro_export]
19macro_rules! export_link_macro {
20    ($crate_name:ident) => {
21        #[macro_export]
22        macro_rules! __phlow_generated_link_macro {
23            () => {
24                const _: () = {
25                    #[used]
26                    static __PHLOW_GENERATED_LINK: fn() = ::$crate_name::__ensure_linked;
27                };
28            };
29        }
30
31        pub use __phlow_generated_link_macro as link;
32    };
33}
34
35pub fn extension_modules_of_val<T: 'static>(_value: &T) -> Vec<Module> {
36    extension_modules_of_type::<T>()
37}
38
39pub fn extension_modules_of_type<T: 'static>() -> Vec<Module> {
40    annotate::global_environment().find_modules_such_that(&|module| {
41        module.has_attribute_such_that(|attribute| {
42            attribute.name() == "tag" && attribute.is_str("phlow-extensions")
43        }) && module.has_attribute_such_that(|attribute| {
44            attribute.name() == "phlow_type" && attribute.is_type::<T>()
45        })
46    })
47}
48
49pub fn extension_modules_of_any(value: &dyn Any) -> Vec<Module> {
50    let type_id = value.type_id();
51    annotate::global_environment().find_modules_such_that(&|module| {
52        module.has_attribute_such_that(|attribute| {
53            attribute.name() == "tag" && attribute.is_str("phlow-extensions")
54        }) && module.has_attribute_such_that(|attribute| {
55            attribute.name() == "phlow_type" && attribute.is_type_id(&type_id)
56        })
57    })
58}
59
60pub fn view_functions_of_val<T: 'static>(value: &T) -> Vec<DefiningMethod> {
61    view_functions_in_modules(&extension_modules_of_val(value))
62}
63
64pub fn view_defining_methods_for_type<T: 'static>() -> Vec<DefiningMethod> {
65    view_functions_in_modules(&extension_modules_of_type::<T>())
66}
67
68pub fn view_functions_of_any(value: &dyn Any) -> Vec<DefiningMethod> {
69    view_functions_in_modules(&extension_modules_of_any(value))
70}
71
72pub fn vtable_of_type<T: 'static>() -> PhlowVTable {
73    vtable_in_modules(&extension_modules_of_type::<T>())
74}
75
76pub fn vtable_of_val<T: 'static>(_value: &T) -> PhlowVTable {
77    vtable_in_modules(&extension_modules_of_type::<T>())
78}
79
80pub fn vtable_of_any(value: &dyn Any) -> PhlowVTable {
81    vtable_in_modules(&extension_modules_of_any(value))
82}
83
84fn vtable_in_modules(modules: &[Module]) -> PhlowVTable {
85    let to_string_fn = functions_in_utility_modules_tagged(modules, "phlow-printing").pop();
86    let type_name_fn = functions_in_utility_modules_tagged(modules, "phlow-type-name").pop();
87    let as_view_fn = functions_in_utility_modules_tagged(modules, "phlow-as-view").pop();
88    let defining_methods_fn =
89        functions_in_utility_modules_tagged(modules, "phlow-defining-methods").pop();
90
91    PhlowVTable {
92        type_name_fn,
93        to_string_fn,
94        as_view_fn,
95        defining_methods_fn,
96    }
97}
98
99fn view_functions_in_modules(modules: &[Module]) -> Vec<DefiningMethod> {
100    modules
101        .iter()
102        .flat_map(|module| {
103            module.find_functions_such_that(|function| {
104                function.has_attribute_such_that(|attribute| {
105                    attribute.name() == "tag" && attribute.is_str("phlow-view")
106                })
107            })
108        })
109        .map(|each| each.into())
110        .collect()
111}
112
113fn functions_in_utility_modules_tagged(modules: &[Module], tag: &str) -> Vec<Function> {
114    modules
115        .iter()
116        .flat_map(|module| {
117            module.find_functions_such_that(|function| {
118                function.has_attribute_such_that(|attribute| {
119                    attribute.name() == "tag" && attribute.is_str(tag)
120                })
121            })
122        })
123        .collect()
124}