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}