v8toolkit  0.0.1
Utility library for embedding V8 Javascript engine in a c++ program
ast_action.cpp
Go to the documentation of this file.
1 #include "ast_action.h"
2 
3 static FrontendPluginRegistry::Add<PrintFunctionNamesAction>
4  X("v8toolkit-generate-bindings", "generate v8toolkit bindings");
5 
6 // This is called when all parsing is done
8 
9 }
10 
11 // takes a file number starting at 1 and incrementing 1 each time
12 // a list of WrappedClasses to print
13 // and whether or not this is the last file to be written
14 void write_classes(int file_count, vector<WrappedClass*> & classes, bool last_one) {
15 
16  cerr << fmt::format("writing classes, file_count: {}, classes.size: {}, last_one: {}", file_count, classes.size(), last_one) << endl;
17  // Open file
18  string class_wrapper_filename = fmt::format("v8toolkit_generated_class_wrapper_{}.cpp", file_count);
19  ofstream class_wrapper_file;
20 
21  class_wrapper_file.open(class_wrapper_filename, ios::out);
22  if (!class_wrapper_file) {
23  if (print_logging) cerr << "Couldn't open " << class_wrapper_filename << endl;
24  throw std::exception();
25  }
26 
27  // by putting in some "fake" includes, it will stop these from ever being put in since it will
28  // think they already are, even though they really aren't
29  set<string> already_included_this_file;
30  already_included_this_file.insert(never_include_for_any_file.begin(), never_include_for_any_file.end());
31 
32  class_wrapper_file << header_for_every_class_wrapper_file << "\n";
33 
34  // first the ones that go in every file regardless of its contents
35  for (auto & include : includes_for_every_class_wrapper_file) {
36  class_wrapper_file << fmt::format("#include {}\n", include);
37  already_included_this_file.insert(include);
38  }
39 
40 
41  std::set<WrappedClass *> extern_templates;
42  set<string> includes_for_this_file;
43 
44  for (WrappedClass * wrapped_class : classes) {
45 
46  // force methods to be parsed
47  wrapped_class->parse_all_methods();
48 
49  for (auto derived_type : wrapped_class->derived_types) {
50  extern_templates.insert(derived_type);
51  }
52 
53  for (auto used_class : wrapped_class->used_classes) {
54  if (used_class->should_be_wrapped()) {
55  extern_templates.insert(used_class);
56  }
57  }
58 
59 
60  if (print_logging) cerr << "Dumping " << wrapped_class->class_name << " to file " << class_wrapper_filename << endl;
61 
62  // printf("While dumping classes to file, %s has includes: ", wrapped_class->class_name.c_str());
63 
64  // Combine the includes needed for types in members/methods with the includes for the wrapped class's
65  // derived types
66  //std::cerr << fmt::format("aa1") << std::endl;
67  //std::cerr << fmt::format("aa2") << std::endl;
68 
69  auto base_type_includes = wrapped_class->get_base_type_includes();
70  includes_for_this_file.insert(base_type_includes.begin(), base_type_includes.end());
71 
72  auto derived_type_includes = wrapped_class->get_derived_type_includes();
73  includes_for_this_file.insert(derived_type_includes.begin(), derived_type_includes.end());
74 
75 
76  } // end loop through all classes for this file
77 
78 
79  for(auto & include_file : includes_for_this_file) {
80  if (include_file != "") {
81  // skip "internal looking" includes - look at 1 because 0 is < or "
82  if (include_file.find("__") == 1) {
83  continue;
84  }
85  //std::cerr << fmt::format("aa5") << std::endl;
86  class_wrapper_file << fmt::format("#include {}\n", include_file);
87  }
88  }
89 
90 
91 //std::cerr << fmt::format("aa7") << std::endl;
92  // remove any types that are wrapped in this file since it will be explicitly instantiated here
93  for (auto & wrapped_class : classes) {
94 //::cerr << fmt::format("aa8") << std::endl;
95  // DO NOT EXPLICITLY INSTANTIATE THE WRAPPED TYPE
96 // if (wrapped_class->is_template_specialization()) {
97 // class_wrapper_file << "template " << wrapped_class->class_name << ";" << endl;
98 // }
99  class_wrapper_file << fmt::format("template class v8toolkit::V8ClassWrapper<{}>;\n", wrapped_class->class_name);
100 
101  // the const type will be used by the 'third party' extension function, so it needs to be instantiated
102  if (!wrapped_class->wrapper_extension_methods.empty()) {
103  class_wrapper_file << fmt::format("template class v8toolkit::V8ClassWrapper<{} const>;\n", wrapped_class->class_name);
104  }
105 
106 
107  // if it's not a template specialization it shouldn't be in the extern_template set, but delete it anyhow
108  extern_templates.erase(wrapped_class);
109  //std::cerr << fmt::format("aa7.5") << std::endl;
110  }
111  //std::cerr << fmt::format("aa8") << std::endl;
112 
113  for (auto extern_template : extern_templates) {
114  //std::cerr << fmt::format("aa9 {}", extern_template->name_alias) << std::endl;
115  if (extern_template->is_template_specialization()) {
116  //std::cerr << fmt::format("aa10") << std::endl;
117  class_wrapper_file << "extern template " << extern_template->class_name << ";\n";
118  }
119  //std::cerr << fmt::format("aa11") << std::endl;
120  class_wrapper_file << fmt::format("extern template class v8toolkit::V8ClassWrapper<{}>;\n", extern_template->class_name);
121  }
122  //std::cerr << fmt::format("aa12") << std::endl;
123 
124 
125 
126  // Write function header
127  class_wrapper_file << fmt::format("void v8toolkit_initialize_class_wrappers_{}(v8toolkit::Isolate &); // may not exist -- that's ok\n", file_count+1);
128  //std::cerr << fmt::format("aa13") << std::endl;
129 
130  if (file_count == 1) {
131  class_wrapper_file << fmt::format("void v8toolkit_initialize_class_wrappers(v8toolkit::Isolate & isolate) {{\n");
132 
133  } else {
134  class_wrapper_file << fmt::format("void v8toolkit_initialize_class_wrappers_{}(v8toolkit::Isolate & isolate) {{\n",
135  file_count);
136  }
137 
138 
139  //std::cerr << fmt::format("aa14") << std::endl;
140  // Print function body
141  for (auto wrapped_class : classes) {
142  //std::cerr << fmt::format("aa15") << std::endl;
143  // each file is responsible for making explicit instantiatinos of its own types
144  class_wrapper_file << wrapped_class->get_bindings();
145  }
146  //std::cerr << fmt::format("aa16") << std::endl;
147 
148  // if there's going to be another file, call the function in it
149  if (!last_one) {
150  class_wrapper_file << fmt::format(" v8toolkit_initialize_class_wrappers_{}(isolate);\n", file_count + 1);
151  }
152 
153  // Close function and file
154  class_wrapper_file << "}\n";
155  class_wrapper_file.close();
156 
157 }
int print_logging
static FrontendPluginRegistry::Add< PrintFunctionNamesAction > X("v8toolkit-generate-bindings","generate v8toolkit bindings")
string header_for_every_class_wrapper_file
void write_classes(int file_count, vector< WrappedClass * > &classes, bool last_one)
Definition: ast_action.cpp:14
vector< string > includes_for_every_class_wrapper_file
vector< string > never_include_for_any_file