Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

annotator.cc

Go to the documentation of this file.
00001 // AUTOMATICALLY GENERATED -- DO NOT EDIT!         -*- c++ -*-
00002 
00003 #include "annotator.h"
00004 #include "annotator_i.h"
00005 
00006 
00007 #line 762 "annotator.cpp"
00008 /******************************* Goto & Co. ******************************/
00009 
00010 static PtreeExprStatement*
00011 make_null_statement();
00012 
00013 #line 50 "annotator.cpp"
00014 
00015 /******************************* Annotator *******************************/
00016 
00017 
00018 Annotator::Annotator(Source* s, Abstract_scope* scope)
00019     : Paranoid_visitor<Annotator_RT>(s),
00020       Ptree_visitor<Annotator_RT>(s), current_scope(scope),
00021       current_block(0), output(0)
00022 {
00023     assert(!dynamic_cast<Block_scope*>(scope));
00024 }
00025 
00026 #line 61 "annotator.cpp"
00027 
00028 
00029 Annotator::Annotator(Source* s, Block_scope* scope)
00030     : Paranoid_visitor<Annotator_RT>(s),
00031       Ptree_visitor<Annotator_RT>(s), current_scope(scope),
00032       current_block(scope), output(0)
00033 { }
00034 
00035 #line 87 "annotator.cpp"
00036 
00037 void
00038 Simple_declaration_reader::parse_specifiers(Ptree* tree)
00039 {
00040     ::parse_specifiers(tree, &storage, &func);
00041 }
00042 
00043 #line 93 "annotator.cpp"
00044 
00045 void
00046 Simple_declaration_reader::declare_variable(Type type, Ptree* name,
00047                                             Ptree* initializer, Ptree* bitsize)
00048 {
00049     if (type.get_kind() == Type::k_Function) {
00050         Function_specifier_set this_fs_set = func;
00051         Storage_class_specifier this_ss = storage;
00052 
00053         Symbol_name sym_name(name, get_scope(), true);
00054 
00055         if (sym_name.is_template())
00056             compile_error("FIXME: template functions not yet supported");
00057         if (!name)
00058             compile_error("unnamed functions are not allowed");
00059         if (bitsize)
00060             compile_error("functions can't have bitsizes");
00061         if (initializer) {
00062             if (initializer->Car()->Eq('=') && initializer->Second()->Eq('0')) {
00063                 this_fs_set |= f_Abstract;
00064                 initializer = 0;
00065             } else if (initializer->Car()->Eq(':')) {
00066                 if (sym_name.get_kind() != Symbol_name::k_Constructor)
00067                     compile_error("member initializer list only valid for constructors");
00068             } else {
00069                 compile_error("can't initialize a function");
00070             }
00071         }
00072 
00073         switch(sym_name.get_kind()) {
00074          case Symbol_name::k_Alloc:
00075             if (dynamic_cast<Class_scope*>(get_scope())) {
00076                 if (this_ss != s_None && this_ss != s_Static)
00077                     compile_error("no storage class allowed for allocation function");
00078                 this_ss = s_Static;
00079             } else {
00080                 if (this_ss != s_Extern && this_ss != s_None)
00081                     compile_error("no storage class allowed for allocation function");
00082                 if (get_scope()->get_parent())
00083                     compile_error("allocation functions only allowed at global scope");
00084                 this_ss = s_Extern;
00085             }
00086             /* FALLTHROUGH */
00087          case Symbol_name::k_Operator:
00088          case Symbol_name::k_Normal:
00089             if (type.get_return_type() == ctor_type)
00090                 compile_error("need a return type for `" + sym_name.get_name() + "'");
00091             break;
00092          case Symbol_name::k_Constructor:
00093             if (type.get_return_type() != ctor_type)
00094                 compile_error("constructors can't have return types");
00095             break;
00096          case Symbol_name::k_Destructor:
00097             if (type.get_return_type() != ctor_type)
00098                 compile_error("destructors can't have return types");
00099             break;
00100          case Symbol_name::k_Conversion:
00101             /* these don't have a declaration type. Make a faked type,
00102                so that "operator T()" is turned into "T __cvt(T*)",
00103                and "operator T&()" to "T __cvt(T&)". The dummy
00104                argument is for name mangling and overloading. It must
00105                be a pointer or reference so that add_parameter doesn't
00106                try to be smart. */
00107             {
00108                 if (type.get_num_function_args() != 0 || type.get_return_type() != ctor_type)
00109                     compile_error("invalid type `" + type.get_human_readable_type() + "' for conversion operator");
00110                 Function_type_maker m;
00111                 if (sym_name.get_type().get_kind() != Type::k_Reference)
00112                     m.add_parameter(sym_name.get_type().make_pointer_type());
00113                 else
00114                     m.add_parameter(sym_name.get_type());
00115                 Type tmp = m.make_function_type(sym_name.get_type());
00116                 tmp.copy_qualifiers(type);
00117                 type = tmp;
00118             }
00119             break;
00120         }
00121 
00122         Function_signature* fsig = get_scope()->add_function_decl(this_ss, this_fs_set, type, sym_name);
00123         if (func_defn) {
00124             Block_scope* block = new Block_scope(fsig);
00125             Arg_vec* args = get_args();
00126             for (unsigned i = 0; i < args->size(); ++i)
00127                 block->add_variable(s_Parameter, (*args)[i].first, (*args)[i].second, 0, 0);
00128             get_scope()->add_function_implementation(fsig, block, func_defn, initializer);
00129         }
00130         func_defn = 0;
00131     } else {
00132         if (func)
00133             compile_error("function specifiers make no sense for variables");
00134         if (type.is_void())
00135             compile_error("can't define variables of type `void'");
00136         Variable_symbol* vsym =
00137             get_scope()->add_variable(storage, type, name, initializer, bitsize);
00138         if (vsym && annotator)
00139             annotator->add_output(make_declaration(vsym));
00140     }
00141 }
00142 
00143 #line 191 "annotator.cpp"
00144 
00150 Annotator_RT
00151 Annotator::visit_name_declaration(Ptree* storagespec, Ptree* typespec, Ptree* decllist)
00152 {
00153     if (storagespec && (storagespec->Eq("friend") || storagespec->Car()->Eq("friend"))) {
00154         // FIXME? I think we can ignore friends because we don't do protection
00155         return 0;
00156     }
00157 
00158     // HACK around OpenC++ limitations:
00159     HACK_EXPLICIT(typespec, storagespec);
00160 
00161     Type type = parse_type(typespec, current_scope, 0, false);
00162 
00163     Simple_declaration_reader sdr(current_scope, get_source(), this);
00164     sdr.parse_specifiers(storagespec);
00165     sdr.parse_declarator_list(type, decllist);
00166     process_pending();
00167     return 0;
00168 }
00169 
00170 #line 216 "annotator.cpp"
00171 
00172 Annotator_RT
00173 Annotator::visit_function(Ptree* storagespec, Ptree* typespec,
00174                           PtreeDeclarator* decl, PtreeBlock* block)
00175 {
00176     HACK_EXPLICIT(typespec, storagespec);
00177     Type type = parse_type(typespec, current_scope, 0, false);
00178 
00179     Declaration_reader::Arg_vec args;
00180     Simple_declaration_reader sdr(current_scope, get_source(), &args, block);
00181     sdr.parse_specifiers(storagespec);
00182     sdr.parse_declarator(type, decl);
00183     process_pending();
00184     return 0;
00185 }
00186 
00187 #line 231 "annotator.cpp"
00188 
00189 Annotator_RT
00190 Annotator::visit_templatedecl(PtreeTemplateDecl* p)
00191 {
00192     expect_ptree(p->Car(), "template");
00193     expect_ptree(p->Second(), '<');
00194     expect_ptree(p->Nth(3), '>');
00195 
00196     ::visit_template(p->Third(), p->Nth(4), current_scope);
00197     process_pending();
00198     return 0;
00199 }
00200 
00201 #line 243 "annotator.cpp"
00202 
00203 /************************* Linkage specification *************************/
00204 
00205 Annotator_RT
00206 Annotator::visit_linkagespec(PtreeLinkageSpec* p)
00207 {
00208     expect_ptree(p->First(), "extern");
00209     return visit(p->Third());
00210 }
00211 
00212 #line 252 "annotator.cpp"
00213 
00214 Annotator_RT
00215 Annotator::visit_brace(PtreeBrace* p)
00216 {
00217     assert(!is_code());
00218     expect_ptree(p->First(), '{');
00219     expect_ptree(p->Third(), '}');
00220 
00221     for (Ptree* content = p->Second(); content; content = content->Cdr())
00222         visit_and_catch(content->Car());
00223 
00224     return 0;
00225 }
00226 
00227 #line 279 "annotator.cpp"
00228 
00229 void
00230 Typedef_name_reader::declare_variable(Type type, Ptree* name, Ptree*, Ptree*)
00231 {
00232     if (name && type == int_type && !name_out)
00233         name_out = name;
00234 }
00235 
00236 #line 292 "annotator.cpp"
00237 
00238 void
00239 Typedef_declaration_reader::declare_variable(Type type, Ptree* name,
00240                                              Ptree* initializer, Ptree* bitsize)
00241 {
00242     if (!name)
00243         compile_error("typedef without a name makes no sense");
00244     if (initializer || bitsize)
00245         compile_error("typedef can't have initializer or bitsize");
00246     if (!name->IsLeaf()) {
00247         compile_error("complicated name not allowed in typedef");
00248     } else {
00249         std::string my_name = name->ToString();
00250         Symbol_pair p = get_scope()->lookup_here(my_name, true);
00251 
00252         /* if there is already a thing named identically, our typedef
00253            must refer there. */
00254         if (p.tag)
00255             if (type.get_kind() != Type::k_Userdef || p.tag != type.get_type_symbol())
00256                 compile_error("typedef `" + my_name + "' conflicts with other type of the same name");
00257 
00258         /* redefinition? allowed according to 7.1.3p2 */
00259         if (Typedef_symbol* sym = dynamic_cast<Typedef_symbol*>(p.untag)) {
00260             if (sym->get_type() != type)
00261                 compile_error("`" + my_name + "' redefined to different type");
00262             return;
00263         }
00264 
00265         /* add it */
00266         Typedef_symbol* tdsym = new Typedef_symbol(type);
00267         get_scope()->add_symbol(my_name, tdsym);
00268 
00269         /* a typedef-name that names a class is a class-name, 7.1.3p4.
00270            this occupies the tag slot of the symbol table entry, so
00271            noone can put a class there. */
00272         if (type.get_kind() == Type::k_Userdef) {
00273             Type_symbol* sym = type.get_type_symbol();
00274             if (!p.tag)
00275                 Symbol_table::get_instance().set_peer(tdsym, sym);
00276         }
00277     }
00278 }
00279 
00280 #line 334 "annotator.cpp"
00281 
00282 Annotator_RT
00283 Annotator::visit_typedef(PtreeTypedef* p)
00284 {
00285     /* [typedef type-specifier-list declarator-list ;] */
00286     Ptree* typespec = p->Second();
00287     Ptree* decllist = p->Third();
00288 
00289     /* figure out the name for anonymous class definitions */
00290     Typedef_name_reader nr(current_scope);
00291     nr.parse_declarator_list(int_type, decllist);
00292 
00293     /* parse actual typedef */
00294     Type type = parse_type(typespec, current_scope, nr.get_name(), false);
00295     Typedef_declaration_reader tdr(current_scope);
00296     tdr.parse_declarator_list(type, decllist);
00297     process_pending();
00298     return 0;
00299 }
00300 
00301 #line 353 "annotator.cpp"
00302 
00304 Annotator_RT
00305 Annotator::visit_type_declaration(Ptree* storagespec, Ptree* typespec)
00306 {
00307     if (storagespec && (storagespec->Eq("friend") || storagespec->Car()->Eq("friend"))) {
00308         // FIXME? I think we can ignore friends because we don't do protection
00309         return 0;
00310     }
00311 
00312     if (storagespec)
00313         bogus_ptree_error("type declarations may not have storage specifiers", storagespec);
00314 
00315     if (!typespec)
00316         compile_warning("stray `;' in program", storagespec);
00317     else
00318         parse_type(typespec, current_scope, 0, true);
00319 
00320     process_pending();
00321     return 0;
00322 }
00323 
00324 #line 374 "annotator.cpp"
00325 
00329 Annotator_RT
00330 Annotator::visit_accessspec(PtreeAccessSpec* p)
00331 {
00332     /* ignore */
00333     return 0;
00334 }
00335 
00336 #line 384 "annotator.cpp"
00337 
00338 Annotator_RT
00339 Annotator::visit_namespacespec(PtreeNamespaceSpec* p)
00340 {
00341     /* [namespace name [{ [content] }] */
00342     Ptree* nametree = p->Second();
00343     Ptree* brace = p->Third();
00344     expect_ptree(brace->First(), '{');
00345     Ptree* content = brace->Second();
00346 
00347     /* first, make a namespace node */
00348     std::string name = nametree ? nametree->ToString() : Symbol_name::get_unnamed_namespace_name();
00349     Symbol_pair pair = current_scope->lookup_here(name, true);
00350     Namespace_symbol* sym;
00351     Namespace_scope* current_ns = downcast<Namespace_scope*>(current_scope);
00352 
00353     if (pair && pair.untag->get_kind() == Symbol::k_Namespace) {
00354         /* we already know this namespace */
00355         sym = downcast<Namespace_symbol*>(pair.untag);
00356     } else if (pair.untag) {
00357         compile_error("can't define namespace `" + name + "' because we already have something named alike");
00358         return 0;
00359     } else {
00360         sym = new Namespace_symbol();
00361         current_scope->add_symbol(name, sym);
00362     }
00363 
00364     if (content) {
00365         Annotator x(get_source(), new Namespace_scope(current_ns, sym));
00366         x.visit(content);
00367         add_output_list(x.get_output());
00368     }
00369     return 0;
00370 }
00371 
00372 #line 418 "annotator.cpp"
00373 
00374 Annotator_RT
00375 Annotator::visit_nonleaf(NonLeaf* p)
00376 {
00377     for (Ptree* i = p; i != 0; i = i->Cdr())
00378         visit_and_catch(i->Car());
00379     return 0;
00380 }
00381 
00382 #line 426 "annotator.cpp"
00383 
00384 Annotator_RT
00385 Annotator::visit_using(PtreeUsing* p)
00386 {
00387     // [using namespace LEAF ;]
00388     // [using namespace [q-name] ;]
00389     // [using nil [qname] ;]
00390     if (p->Second()) {
00391         /* "using namespace" is allowed at namespace or block scope */
00392         bogus_ptree_error("FIXME: `using' doesn't work yet", p);
00393         // ISO 14882 p.115ff
00394     } else {
00395         bogus_ptree_error("FIXME: `using non-namespace' doesn't work yet", p);
00396     }
00397     return 0;
00398 }
00399 
00400 #line 442 "annotator.cpp"
00401 
00402 /********************************** Code *********************************/
00403 
00404 void
00405 Annotator::visit_stmt_or_block(Ptree* p)
00406 {
00407     if (dynamic_cast<PtreeBlock*>(p)) {
00408         for (Ptree* q = p->Second(); q; q = q->Cdr())
00409             visit_and_catch(q->Car());
00410     } else {
00411         visit(p);
00412     }
00413 }
00414 
00415 #line 455 "annotator.cpp"
00416 
00418 Annotator_RT
00419 Annotator::visit_block(PtreeBlock* p)
00420 {
00421     assert(is_code());
00422     expect_ptree(p->First(), '{');
00423     expect_ptree(p->Third(), '}');
00424 
00425     Annotator anno(get_source(), new Block_scope(current_block, false));
00426     for (Ptree* q = p->Second(); q; q = q->Cdr())
00427         anno.visit_and_catch(q->Car());
00428 
00429     add_output(anno.get_output_as_block());
00430     return 0;
00431 }
00432 
00433 #line 471 "annotator.cpp"
00434 
00435 Annotator_RT
00436 Annotator::visit_do(PtreeDoStatement* p)
00437 {
00438     /* [do stmt while ( expr ) ;] */
00439     assert(is_code());
00440     expect_ptree(p->First(), "do");
00441     expect_ptree(p->Third(), "while");
00442     expect_ptree(p->Nth(3), '(');
00443     expect_ptree(p->Nth(5), ')');
00444     expect_ptree(p->Nth(6), ';');
00445 
00446     Expr_result result = Expr_annotator(current_scope, get_source()).visit(p->Nth(4));
00447     Implicit_conversion* ics = generate_implicit_conversion(result,
00448                                                             bool_type,
00449                                                             0,
00450                                                             true /* user-defined */,
00451                                                             true /* copy init */,
00452                                                             false /* not IOA */);
00453     if (!ics)
00454         compile_error("`do while' condition not convertible to `bool'");
00455 
00456     Annotator anno(get_source(), new Block_scope(current_block, false));
00457     anno.visit_stmt_or_block(p->Second());
00458     add_output(new PtreeDoStatement(p->First(),
00459                                     Ptree::List(anno.get_output_as_block(),
00460                                                 p->Nth(2),
00461                                                 p->Nth(3),
00462                                                 ics->make_tree(result).get_tree(),
00463                                                 p->Nth(5),
00464                                                 p->Nth(6))));
00465     return 0;
00466 }
00467 
00468 #line 504 "annotator.cpp"
00469 
00470 Annotator_RT
00471 Annotator::visit_while(PtreeWhileStatement* p)
00472 {
00473     // FIXME: OpenC++ doesn't recognize the
00474     //     while ( declaration ) stmt
00475     // form. I think it should be translated into
00476     //     while (1) { declaration; if (!var) break; stmt }
00477     // where the stmt scope inherits from the while scope. This
00478     // frees the surrounding code from having to handle while specially.
00479 
00480     /* [while ( expr ) stmt] */
00481     assert(is_code());
00482     expect_ptree(p->First(), "while");
00483     expect_ptree(p->Second(), '(');
00484     expect_ptree(p->Nth(3), ')');
00485 
00486     Expr_result result = Expr_annotator(current_scope, get_source()).visit(p->Third());
00487     Implicit_conversion* ics = generate_implicit_conversion(result,
00488                                                             bool_type,
00489                                                             0,
00490                                                             true /* user-defined */,
00491                                                             true /* copy init */,
00492                                                             false /* not IOA */);
00493     if (!ics)
00494         compile_error("`while' condition not convertible to `bool'");
00495 
00496     Annotator anno(get_source(), new Block_scope(current_block, false));
00497     anno.visit_stmt_or_block(p->Nth(4));
00498 
00499     add_output(new PtreeWhileStatement(p->First(),
00500                                        Ptree::List(p->Second(),
00501                                                    ics->make_tree(result).get_tree(),
00502                                                    p->Nth(3),
00503                                                    anno.get_output_as_block())));
00504     return 0;
00505 }
00506 
00507 #line 541 "annotator.cpp"
00508 
00509 Annotator_RT
00510 Annotator::visit_if(PtreeIfStatement* p)
00511 {
00512     // FIXME: OpenC++ doesn't handle
00513     //   if (declaration) stmt
00514     // I think it should be translated into
00515     //   { declaration; if (var) stmt }
00516     // where the inner block inherits from the outer one.
00517 
00518     /* [if ( expr ) stmt]
00519        [if ( expr ) stmt else stmt] */
00520     assert(is_code());
00521     expect_ptree(p->First(), "if");
00522     expect_ptree(p->Second(), '(');
00523     expect_ptree(p->Nth(3), ')');
00524 
00525     Expr_result cond = Expr_annotator(current_block, get_source()).visit(p->Third());
00526     Implicit_conversion* ics = generate_implicit_conversion(cond,
00527                                                             bool_type,
00528                                                             0,
00529                                                             true /* user-defined */,
00530                                                             true /* copy init */,
00531                                                             false /* not IOA */);
00532     if (!ics)
00533         compile_error("`if' condition not convertible to `bool'");
00534 
00535     Annotator then_anno(get_source(), new Block_scope(current_block, false));
00536     then_anno.visit_stmt_or_block(p->Nth(4));
00537 
00538     Ptree* rv = new PtreeIfStatement(p->First(),
00539                                      Ptree::List(p->Second(),
00540                                                  ics->make_tree(cond).get_tree(),
00541                                                  p->Nth(3),
00542                                                  then_anno.get_output_as_block()));
00543     if (p->Length() > 5) {
00544         expect_ptree(p->Nth(5), "else");
00545         Annotator else_anno(get_source(), new Block_scope(current_block, false));
00546         else_anno.visit_stmt_or_block(p->Nth(6));
00547         Ptree::Snoc(rv, p->Nth(5));
00548         Ptree::Snoc(rv, else_anno.get_output_as_block());
00549     }
00550     add_output(rv);
00551     return 0;
00552 }
00553 
00554 #line 586 "annotator.cpp"
00555 
00557 Annotator_RT
00558 Annotator::visit_exprstatement(PtreeExprStatement* p)
00559 {
00560     assert(is_code());
00561     expect_ptree(p->Second(), ';');
00562 
00563     if (p->First()) {
00564         /* first might be null, empty statement */
00565         Expr_result res = Expr_annotator(current_scope, get_source()).visit(p->First());
00566         if (!res.is_value())
00567             compile_error("invalid expression statement");
00568 
00569         add_output(new PtreeExprStatement(res.get_tree(), p->Cdr()));
00570     }
00571     return 0;
00572 }
00573 
00574 #line 604 "annotator.cpp"
00575 
00576 Annotator_RT
00577 Annotator::visit_for(PtreeForStatement* p)
00578 {
00579     /* [for ( statement expr-or-null ; expr-or-null ) stmt] */
00580     /* translate this into
00581          { statement for ( ; e ; e ) stmt } */
00582     expect_ptree(p->First(), "for");
00583     expect_ptree(p->Second(), '(');
00584     expect_ptree(p->Nth(4), ';');
00585     expect_ptree(p->Nth(6), ')');
00586 
00587     Block_scope* outer_scope = new Block_scope(current_block, false);
00588     Block_scope* inner_scope = new Block_scope(outer_scope, true);
00589 
00590     /* visit first part of the statement */
00591     Annotator anno(get_source(), outer_scope);
00592     anno.visit(p->Third());
00593 
00594     Ptree* out = new PtreeForStatement(p->First(),
00595                                        Ptree::List(p->Second(),
00596                                                    make_null_statement()));
00597     /* visit second part */
00598     if (p->Nth(3)) {
00599         Expr_result result = Expr_annotator(outer_scope, get_source()).visit(p->Nth(3));
00600         if (!result.is_value())
00601             compile_error("invalid second parameter to `for'");
00602         Implicit_conversion* ics = generate_implicit_conversion(result,
00603                                                                 bool_type,
00604                                                                 0,
00605                                                                 true,
00606                                                                 true,
00607                                                                 false);
00608         if (!ics)
00609             compile_error("`for' expects `bool'");
00610         Ptree::Snoc(out, ics->make_tree(result).get_tree());
00611     } else {
00612         Ptree::Snoc(out, 0);
00613     }
00614     Ptree::Snoc(out, p->Nth(4));
00615 
00616     /* visit third part */
00617     if (p->Nth(5)) {
00618         Expr_result result = Expr_annotator(outer_scope, get_source()).visit(p->Nth(5));
00619         if (!result.is_value())
00620             compile_error("invalid third parameter to `for'");
00621         Ptree::Snoc(out, result.get_tree());
00622     } else {
00623         Ptree::Snoc(out, 0);
00624     }
00625     Ptree::Snoc(out, p->Nth(6));
00626 
00627     /* visit statement */
00628     Annotator ianno(get_source(), inner_scope);
00629     ianno.visit_stmt_or_block(p->Nth(7));
00630     Ptree::Snoc(out, ianno.get_output_as_block());
00631     anno.add_output(out);
00632     add_output(anno.get_output_as_block());
00633     return 0;
00634 }
00635 
00636 #line 664 "annotator.cpp"
00637 
00638 Annotator_RT
00639 Annotator::visit_return(PtreeReturnStatement* p)
00640 {
00641     assert(is_code());
00642     Type rt = current_block->get_function()->get_return_type();
00643     expect_ptree(p->First(), "return");
00644     if (p->Length() == 2) {
00645         /* "return;" */
00646         expect_ptree(p->Second(), ';');
00647         if (rt.is_void() || rt.is_same_unqualified_type(ctor_type))
00648             /* accept */;
00649         else
00650             compile_error("return without parameter in function returning non-void");
00651         add_output(p);
00652         return 0;
00653     } else {
00654         /* "return EXPR;" */
00655         expect_ptree(p->Third(), ';');
00656         Expr_result res = Expr_annotator(current_scope, get_source()).visit(p->Second());
00657         if (rt.is_void() || rt.is_same_unqualified_type(ctor_type)) {
00658             /* return type void <-> expression must have type void */
00659             if (!res.is_value() || !res.get_type().is_void())
00660                 compile_error("invalid type for `return'");
00661             add_output(new PtreeExprStatement(res.get_tree(), Ptree::List(make_static_leaf(";"))));
00662             add_output(new PtreeReturnStatement(p->First(),
00663                                                 Ptree::List(p->Third())));
00664         } else {
00665             /* non-void <-> convert type accordingly */
00666             Implicit_conversion* ics =
00667                 generate_implicit_conversion(res, rt, 0, true /* with user-defined */,
00668                                              true /* is copy-init */, false /* not IOA */);
00669             if (!ics)
00670                 compile_error("unable to convert `" + res.get_type().get_human_readable_type()
00671                               + "' into `" + rt.get_human_readable_type() + "'");
00672             add_output(new PtreeReturnStatement(p->First(),
00673                                                 Ptree::List(ics->make_tree(res).get_tree(),
00674                                                             p->Third())));
00675         }
00676         return 0;
00677     }
00678 }
00679 
00680 #line 706 "annotator.cpp"
00681 
00682 /********************************* Switch ********************************/
00683 
00684 Annotator_RT
00685 Annotator::visit_switch(PtreeSwitchStatement* p)
00686 {
00687     expect_ptree(p->First(), "switch");
00688     expect_ptree(p->Second(), '(');
00689     expect_ptree(p->Nth(3), ')');
00690 
00691     Expr_result res = Expr_annotator(current_scope, get_source()).visit(p->Third());
00692     if (!res.is_value())
00693         compile_error("invalid `switch' expression");
00694     if (res.get_type().is_class_type()) {
00695         /* 6.4.2p2: class type with one conversion function to integral
00696            or enumeration type */
00697         Conversion_op_map com;
00698         enumerate_conversion_ops(res, &com);
00699         Conversion_op_map::iterator found = com.end(), i;
00700         Type found_type;
00701         for (i = com.begin(); i != com.end(); ++i) {
00702             Type t = i->first->get_return_type().sans_reference().get_unqualified_type();
00703             if (t.is_int() || t.is_enum_type()) {
00704                 if (found != com.end() || i->second != 1)
00705                     compile_error("conversion to scalar is ambiguous for `" + res.get_type().get_human_readable_type() + "' in `switch'");
00706                 found = i;
00707                 found_type = t;
00708             }
00709         }
00710         if (found == com.end())
00711             compile_error("no conversion to scalar for `switch'");
00712 
00713         Implicit_conversion* ics =
00714             generate_implicit_conversion(res, found_type, 0, true /* userdef */,
00715                                          true /* copy-init */, false /* IOA */);
00716         if (!ics)
00717             compile_error("can't convert `" + res.get_type().get_human_readable_type()
00718                           + "' into `" + found_type.get_human_readable_type() + "' for `switch'");
00719 
00720         res = ics->make_tree(res);
00721     }
00722 
00723     if (!res.get_type().is_int() && !res.get_type().is_enum_type())
00724         compile_error("argument to `switch' is not scalar");
00725 
00726     Annotator anno(get_source(), new Block_scope(current_block, false));
00727     anno.visit_stmt_or_block(p->Nth(4));
00728 
00729     add_output(new PtreeSwitchStatement(p->First(),
00730                                         Ptree::List(p->Second(),
00731                                                     res.get_tree(),
00732                                                     p->Nth(3),
00733                                                     anno.get_output_as_block())));
00734     return 0;
00735 }
00736 
00737 #line 761 "annotator.cpp"
00738 
00739 /******************************* Goto & Co. ******************************/
00740 
00741 static PtreeExprStatement*
00742 make_null_statement()
00743 {
00744     return new PtreeExprStatement(0, Ptree::List(make_static_leaf(";")));
00745 }
00746 
00747 #line 769 "annotator.cpp"
00748 
00749 Annotator_RT
00750 Annotator::visit_label(PtreeLabelStatement* lbl)
00751 {
00752     /* [name : stmt]
00753        translate these into [label-form : ExprStatement@[null ;]] */
00754 
00755     expect_ptree(lbl->Second(), ':');
00756     add_output(new PtreeLabelStatement(lbl->First(),
00757                                        Ptree::List(lbl->Second(),
00758                                                    make_null_statement())));
00759     visit(lbl->Third());
00760     return 0;
00761 }
00762 
00763 #line 783 "annotator.cpp"
00764 
00765 Annotator_RT
00766 Annotator::visit_default(PtreeDefaultStatement* lbl)
00767 {
00768     expect_ptree(lbl->First(), "default");
00769     expect_ptree(lbl->Second(), ':');
00770     add_output(new PtreeDefaultStatement(lbl->First(),
00771                                          Ptree::List(lbl->Second(),
00772                                                      make_null_statement())));
00773     visit(lbl->Third());
00774     return 0;
00775 }
00776 
00777 #line 795 "annotator.cpp"
00778 
00779 Annotator_RT
00780 Annotator::visit_case(PtreeCaseStatement* c)
00781 {
00782     expect_ptree(c->First(), "case");
00783     expect_ptree(c->Third(), ':');
00784 
00785     Expr_result res = Expr_annotator(current_scope, get_source()).visit(c->Second());
00786     if (!res.is_value() || !(res.get_type().is_int() || res.get_type().is_enum_type()))
00787         compile_error("invalid `case' label type");
00788     // FIXME: maybe cast this to the enum selector's type
00789     add_output(new PtreeLabelStatement(c->First(),
00790                                        Ptree::List(res.get_tree(),
00791                                                    c->Third(),
00792                                                    make_null_statement())));
00793     visit(c->Nth(3));
00794     return 0;
00795 }
00796 
00797 #line 813 "annotator.cpp"
00798 
00799 Annotator_RT
00800 Annotator::visit_goto(PtreeGotoStatement* g)
00801 {
00802     expect_ptree(g->First(), "goto");
00803     expect_ptree(g->Third(), ';');
00804     add_output(g);
00805     return 0;
00806 }
00807 
00808 #line 822 "annotator.cpp"
00809 
00810 Annotator_RT
00811 Annotator::visit_continue(PtreeContinueStatement* c)
00812 {
00813     expect_ptree(c->First(), "continue");
00814     expect_ptree(c->Second(), ';');
00815     add_output(c);
00816     return 0;
00817 }
00818 
00819 #line 831 "annotator.cpp"
00820 
00821 Annotator_RT
00822 Annotator::visit_break(PtreeBreakStatement* b)
00823 {
00824     expect_ptree(b->First(), "break");
00825     expect_ptree(b->Second(), ';');
00826     add_output(b);
00827     return 0;
00828 }
00829 
00830 #line 840 "annotator.cpp"
00831 
00832 /***************************** Administrivia *****************************/
00833 
00837 void
00838 Annotator::process_pending()
00839 {
00840     current_scope->process_pending();
00841 }
00842 
00843 #line 851 "annotator.cpp"
00844 
00846 void
00847 Annotator::add_output(Ptree* node)
00848 {
00849     assert(node);
00850     output = Ptree::Snoc(output, node);
00851 }
00852 
00853 #line 859 "annotator.cpp"
00854 
00856 void
00857 Annotator::add_output_list(Ptree* nodes)
00858 {
00859     if (nodes) {
00860         assert(!nodes->IsLeaf());
00861         output = Ptree::Append(output, nodes);
00862     }
00863 }
00864 
00865 #line 876 "annotator.cpp"
00866 
00868 PtreeBlock*
00869 Annotator::get_output_as_block() const
00870 {
00871     return new PtreeBlock(make_static_leaf("{"),
00872                           Ptree::List(get_output(),
00873                                       make_static_leaf("}")));
00874 }

Generated on Mon Feb 10 17:32:43 2003 for VFiasco Semantics Compiler by doxygen1.2.15