00001
00002
00003 #include "function_body.h"
00004 #include "function_body_i.h"
00005
00006
00007 #line 103 "function_body.cpp"
00008
00009
00017 static Ptree*
00018 process_initializers(Function_signature* fsig, Block_scope* scope, Ptree* tree);
00019
00020 #line 50 "function_body.cpp"
00021
00024 Function_body_queue::Function_body_queue()
00025 : first(0), last(0)
00026 { }
00027
00028 #line 56 "function_body.cpp"
00029
00035 void
00036 Function_body_queue::add_function(Function_signature* fsig,
00037 Block_scope* scope,
00038 Ptree* tree,
00039 Ptree* init)
00040 {
00041 assert(fsig);
00042 assert(scope);
00043 assert(tree);
00044 assert(!init || fsig->get_function()->get_function_kind() == Symbol_name::k_Constructor);
00045
00046 Function_body_node* p = new Function_body_node(fsig, scope, tree, init);
00047 if (first)
00048 last->next = p;
00049 else
00050 first = p;
00051 last = p;
00052 }
00053
00054 #line 80 "function_body.cpp"
00055
00056 Function_body_node*
00057 Function_body_queue::pop()
00058 {
00059 Function_body_node* rv = first;
00060 if (first) {
00061 first = first->next;
00062 if (!first)
00063 last = 0;
00064 }
00065 return rv;
00066 }
00067
00068 #line 92 "function_body.cpp"
00069
00071 void
00072 Function_body_queue::process()
00073 {
00074 while (Function_body_node* p = pop()) {
00075 process_function_body(p->fsig, p->scope, p->tree, p->init);
00076 delete p;
00077 }
00078 }
00079
00080 #line 102 "function_body.cpp"
00081
00082
00083
00091 static Ptree*
00092 process_initializers(Function_signature* fsig, Block_scope* scope, Ptree* tree)
00093 {
00094
00095 if (tree) {
00096 expect_ptree(tree->Car(), ':');
00097 tree = tree->Cdr();
00098 }
00099
00100
00101 Abstract_scope* class_scope = fsig->get_function()->get_declared_scope();
00102 Class_symbol* class_sym = downcast<Class_symbol*>(fsig->get_this_type().get_type_symbol());
00103
00104
00105
00106
00107 std::vector<std::pair<Symbol*, Ptree*> > inits;
00108 for (Ptree* p = tree; p; (p = p->Cdr()) && (p = p->Cdr())) {
00109 Ptree* ele = p->Car();
00110 expect_ptree(ele->Second(), '(');
00111 expect_ptree(ele->Nth(3), ')');
00112
00113
00114 Symbol_pair sp = Symbol_name(ele->First(), class_scope, false).lookup_for_use(false);
00115
00116 Symbol* the_sym = 0;
00117 if (Class_symbol* csym = dynamic_cast<Class_symbol*>(sp.tag))
00118 the_sym = csym;
00119 else if (Variable_symbol* vsym = dynamic_cast<Variable_symbol*>(sp.untag))
00120 the_sym = vsym;
00121 else if (Typedef_symbol* tdsym = dynamic_cast<Typedef_symbol*>(sp.untag)) {
00122 Type t = tdsym->get_type();
00123 if (t.is_class_type())
00124 the_sym = t.get_type_symbol();
00125 }
00126
00127 if (!the_sym)
00128 compile_error("don't know what to do with name `" + std::string(ele->First()->ToString()) + "` in an initializer");
00129
00130 inits.push_back(std::make_pair(the_sym, ele->Cdr()));
00131 }
00132
00133
00134 std::vector<Symbol*> want;
00135 for (Class_symbol::bases_t::const_iterator i = class_sym->vbc_begin(); i != class_sym->vbc_end(); ++i)
00136 want.push_back(*i);
00137 for (Class_symbol::bases_t::const_iterator i = class_sym->base_begin(); i != class_sym->base_end(); ++i)
00138 want.push_back(*i);
00139 for (Class_symbol::members_t::const_iterator i = class_sym->mem_begin(); i != class_sym->mem_end(); ++i)
00140 if ((*i)->is_member_variable())
00141 want.push_back(*i);
00142
00143
00144 Ptree* output_list = 0;
00145 unsigned last_used = 0;
00146 for (unsigned i = 0; i < want.size(); ++i) {
00147
00148 Ptree* the_init = 0;
00149 for (unsigned j = 0; j < inits.size(); ++j) {
00150 if (inits[j].first == want[i]) {
00151 if (the_init) {
00152 compile_warning("multiple initializers for `" + want[i]->get_name() + "'", the_init);
00153 } else {
00154 if (last_used > j)
00155 compile_warning("initializers will be re-ordered to match initialisation rules", the_init);
00156 the_init = inits[j].second;
00157 last_used = j;
00158 }
00159 inits[j].first = 0;
00160 }
00161 }
00162
00163
00164 Ptree *output_init, *output_name;
00165 if (Class_symbol* csym = dynamic_cast<Class_symbol*>(want[i])) {
00166 output_init = Init_handler(scope, the_init, false).process_initializer(csym->get_type());
00167 output_name = make_name(csym->get_name(), csym->get_type(), csym);
00168 } else if (Variable_symbol* vsym = dynamic_cast<Variable_symbol*>(want[i])) {
00169 output_init = Init_handler(scope, the_init, false).process_initializer(vsym->get_type());
00170 if (!output_init)
00171 compile_warning("member `" + vsym->get_name() + "' not initialized", tree);
00172 output_name = make_name(vsym);
00173 } else {
00174 assert(!"game over");
00175 }
00176
00177
00178 output_list = Ptree::Snoc(output_list,
00179 Ptree::List(output_name,
00180 make_static_leaf("="),
00181 output_init));
00182 }
00183
00184
00185 for (unsigned i = 0; i < inits.size(); ++i)
00186 if (inits[i].first)
00187 compile_error("unexpected initializer for `" + inits[i].first->get_name() + "'");
00188
00189 return output_list;
00190 }
00191
00192 #line 212 "function_body.cpp"
00193
00199 void
00200 process_function_body(Function_signature* fsig, Block_scope* scope,
00201 Ptree* tree, Ptree* init)
00202 {
00203 if (fsig->get_storage_specifier() == s_Member)
00204 scope->set_this_type(fsig->get_this_type());
00205 else
00206 scope->set_this_type(Type());
00207
00208
00209 if (fsig->get_function()->get_function_kind() == Symbol_name::k_Constructor)
00210 init = process_initializers(fsig, scope, init);
00211 else
00212 assert(!init);
00213
00214
00215 Annotator anno(&Source::instance(), scope);
00216 anno.visit_stmt_or_block(tree);
00217 fsig->set_body(anno.get_output(), init);
00218 }