Modules | Files | Inheritance Tree | Inheritance Graph | Name Index | Config
File: Synopsis/Parser/C++/occ/mop.cc
    1| /*
    2|   Copyright (C) 1997-2000 Shigeru Chiba, University of Tsukuba.
    3| 
    4|   Permission to use, copy, distribute and modify this software and   
    5|   its documentation for any purpose is hereby granted without fee,        
    6|   provided that the above copyright notice appear in all copies and that 
    7|   both that copyright notice and this permission notice appear in 
    8|   supporting documentation.
    9| 
   10|   Shigeru Chiba makes no representations about the suitability of this 
   11|   software for any purpose.  It is provided "as is" without express or
   12|   implied warranty.
   13| */
   14| 
   15| #include <iostream>
   16| #include <cstring>
   17| #include "token.h"
   18| #include "mop.h"
   19| #include "env.h"
   20| #include "ptree.h"
   21| #include "walker.h"
   22| #include "classwalk.h"
   23| #include "typeinfo.h"
   24| #include "encoding.h"
   25| 
   26| ClassArray* Class::class_list = nil;
   27| int Class::num_of_cmd_options = 0;
   28| char* Class::cmd_options[];
   29| 
   30| char* Class::metaclass_for_c_functions = nil;
   31| Class* Class::for_c_functions = nil;
   32| 
   33| Ptree* Class::class_t = nil;
   34| Ptree* Class::empty_block_t = nil;
   35| Ptree* Class::public_t = nil;
   36| Ptree* Class::protected_t = nil;
   37| Ptree* Class::private_t = nil;
   38| Ptree* Class::virtual_t = nil;
   39| Ptree* Class::colon_t = nil;
   40| Ptree* Class::comma_t = nil;
   41| Ptree* Class::semicolon_t = nil;
   42| 
   43| static opcxx_ListOfMetaclassclassCreator = NULL;
   44| static opcxx_ListOfMetaclasstemplateCreator = NULL;
   45| static ClassCreateClass(Ptree* def, Ptree* marg);
   46| static ClassCreateTemplateClass(Ptree* def, Ptree* marg);
   47| 
   48| void Class::do_init_static()
   49| {
   50|     // Only do this once
   51|     static bool done_init = false;
   52|     if (done_initreturn;
   53|     done_init = true;
   54| 
   55|     class_t = new LeafReserved("class", 5);
   56|     empty_block_t = new PtreeClassBody(new Leaf("{", 1),
   57|                        nil,
   58|                                  new Leaf("}", 1));
   59|     public_t = new LeafPUBLIC("public", 6);
   60|     protected_t = new LeafPROTECTED("protected", 9);
   61|     private_t = new LeafPRIVATE("private", 7);
   62|     virtual_t = new LeafVIRTUAL("virtual", 7);
   63|     colon_t = new Leaf(":", 1);
   64|     comma_t = new Leaf(",", 1);
   65|     semicolon_t = new Leaf(";", 1);
   66| 
   67|     classCreator = new opcxx_ListOfMetaclass(
   68|             "Class", CreateClass, Class::Initialize, nil);
   69| 
   70|     templateCreator = new opcxx_ListOfMetaclass(
   71|             "TemplateClass", CreateTemplateClass,
   72|             TemplateClass::Initialize, nil);
   73| }
   74| 
   75| // class Class
   76| 
   77| void Class::Construct(Environment* e, Ptree* name)
   78| {
   79|     Ptreedef;
   80|     Encoding encode;
   81| 
   82|     encode.SimpleName(name);
   83|     def = Ptree::List(name, nil, empty_block_t);
   84|     def = new PtreeClassSpec(class_t, def, nil, encode.Get());
   85| 
   86|     full_definition = def;
   87|     definition = def;
   88|     class_environment = nil;
   89|     member_list = nil;
   90|     done_decl_translation = FALSE;
   91|     removed = FALSE;
   92|     changed_member_list = nil;
   93|     appended_member_list = nil;
   94|     appended_code = nil;
   95|     new_base_classes = def->Third();
   96|     new_class_specifier = nil;
   97| 
   98|     SetEnvironment(new Environment(e));
   99| }
  100| 
  101| void Class::InitializeInstance(Ptree* def, Ptree*)
  102| {
  103|     full_definition = def;
  104|     if(def->Car()->IsLeaf())
  105|         definition = def;
  106|     else
  107|         definition = def->Cdr();       // if coming with a user 
  108| 
  109|     class_environment = nil;
  110|     member_list = nil;
  111| 
  112|     if(class_list == nil)
  113|         class_list = new ClassArray;
  114| 
  115|     class_list->Append(this);
  116| 
  117|     done_decl_translation = FALSE;
  118|     removed = FALSE;
  119|     changed_member_list = nil;
  120|     appended_member_list = nil;
  121|     appended_code = nil;
  122|     new_base_classes = definition->Third();
  123|     new_class_specifier = nil;
  124|     new_class_name = nil;
  125| }
  126| 
  127| Class::~Class() {}
  128| 
  129| // introspection
  130| 
  131| charClass::MetaclassName()
  132| {
  133|     return "Class";
  134| }
  135| 
  136| PtreeClass::Comments()
  137| {
  138|     if (definition->IsA(ntClassSpec))
  139|         return ((PtreeClassSpec*)definition)->GetComments();
  140|     return nil;
  141| }
  142| 
  143| PtreeClass::Name()
  144| {
  145|     return definition->Second();
  146| }
  147| 
  148| PtreeClass::BaseClasses()
  149| {
  150|     return definition->Third();
  151| }
  152| 
  153| PtreeClass::Members()
  154| {
  155|     return definition->Nth(3)->Second();
  156| }
  157| 
  158| ClassClass::NthBaseClass(int n)
  159| {
  160|     Ptreebases = definition->Third();
  161|     while(bases != nil){
  162|         bases = bases->Cdr();         // sk
  163|         if(n-- == 0){
  164|             Ptreebase_class = bases->Car()->Last()->Car();
  165|             return class_environment->LookupClassMetaobject(base_class);
  166|         }
  167| 
  168|         bases = bases->Cdr();
  169|     }
  170| 
  171|     return nil;
  172| }
  173| 
  174| bool Class::IsSubclassOf(Ptree* name)
  175| {
  176|     Ptreebases = definition->Third();
  177|     while(bases != nil){
  178|         bases = bases->Cdr();         // skip : or ,
  179|         Ptreebase_class = bases->Car()->Last()->Car();
  180|         if(base_class->Eq(name))
  181|             return TRUE;
  182|         else{
  183|             Classmetaobject
  184|                class_environment->LookupClassMetaobject(base_class);
  185|             if(metaobject != nil && metaobject->IsSubclassOf(name))
  186|                return TRUE;
  187|         }
  188| 
  189|         bases = bases->Cdr();
  190|     }
  191| 
  192|     return FALSE;
  193| }
  194| 
  195| bool Class::IsImmediateSubclassOf(Ptree* name)
  196| {
  197|     Ptreebases = definition->Third();
  198|     while(bases != nil){
  199|         bases = bases->Cdr();         // skip : or ,
  200|         Ptreebase_class = bases->Car()->Last()->Car();
  201|         if(base_class->Eq(name))
  202|             return TRUE;
  203| 
  204|         bases = bases->Cdr();
  205|     }
  206| 
  207|     return FALSE;
  208| }
  209| 
  210| PtreeClass::NthBaseClassName(int n)
  211| {
  212|     Ptreebases = definition->Third();
  213|     while(bases != nil){
  214|         bases = bases->Cdr();         // sk
  215|         if(n-- == 0)
  216|             return bases->Car()->Last()->Car();
  217| 
  218|         bases = bases->Cdr();
  219|     }
  220| 
  221|     return nil;
  222| }
  223| 
  224| bool Class::NthMember(int nth, Member& mem)
  225| {
  226|     MemberListmlist = GetMemberList();
  227|     if(mlist == nil || nth >= mlist->Number())
  228|         return FALSE;
  229| 
  230|     mem.Set(thismlist->Ref(nth)->declaratornth);
  231|     return TRUE;
  232| }
  233| 
  234| bool Class::LookupMember(Ptree* name)
  235| {
  236|     Member m;
  237|     return LookupMember(namem);
  238| }
  239| 
  240| bool Class::LookupMember(Ptree* name, Member& mem, int index)
  241| {
  242|     MemberListmlist = GetMemberList();
  243|     if(mlist == nil)
  244|         return FALSE;
  245| 
  246|     int nth = mlist->Lookup(class_environmentnameindex);
  247|     if(nth < 0)
  248|         return FALSE;
  249| 
  250|     mem.Set(thismlist->Ref(nth)->declaratornth);
  251|     return TRUE;
  252| }
  253| 
  254| bool Class::LookupMember(char* name)
  255| {
  256|     Member m;
  257|     return LookupMember(namem);
  258| }
  259| 
  260| bool Class::LookupMember(char* name, Member& mem, int index)
  261| {
  262|     MemberListmlist = GetMemberList();
  263|     if(mlist == nil)
  264|         return FALSE;
  265| 
  266|     int nth = mlist->Lookup(class_environmentnameindex);
  267|     if(nth < 0)
  268|         return FALSE;
  269| 
  270|     mem.Set(thismlist->Ref(nth)->declaratornth);
  271|     return TRUE;
  272| }
  273| 
  274| MemberListClass::GetMemberList()
  275| {
  276|     if(member_list == nil){
  277|         member_list = new MemberList;
  278|         member_list->Make(this);
  279|     }
  280| 
  281|     return member_list;
  282| }
  283| 
  284| ClassArrayClass::AllClasses()
  285| {
  286|     return *class_list;
  287| }
  288| 
  289| int Class::Subclasses(ClassArray& subclasses)
  290| {
  291|     return Subclasses(Name(), subclasses);
  292| }
  293| 
  294| int Class::Subclasses(Ptree* name, ClassArray& subclasses)
  295| {
  296|     subclasses.Clear();
  297|     if(class_list == nil)
  298|         return 0;
  299| 
  300|     uint n = class_list->Number();
  301|     for(uint i = 0i < n; ++i){
  302|         Classc = class_list->Ref(i);
  303|         if(c->IsSubclassOf(name))
  304|             subclasses.Append(c);
  305|     }
  306| 
  307|     return subclasses.Number();
  308| }
  309| 
  310| int Class::ImmediateSubclasses(ClassArray& subclasses)
  311| {
  312|     return ImmediateSubclasses(Name(), subclasses);
  313| }
  314| 
  315| int Class::ImmediateSubclasses(Ptree* name, ClassArray& subclasses)
  316| {
  317|     subclasses.Clear();
  318|     if(class_list == nil)
  319|         return 0;
  320| 
  321|     uint n = class_list->Number();
  322|     for(uint i = 0i < n; ++i){
  323|         Classc = class_list->Ref(i);
  324|         if(c->IsImmediateSubclassOf(name))
  325|             subclasses.Append(c);
  326|     }
  327| 
  328|     return subclasses.Number();
  329| }
  330| 
  331| int Class::InstancesOf(char* name, ClassArray& classes)
  332| {
  333|     classes.Clear();
  334|     if(class_list == nil)
  335|         return 0;
  336| 
  337|     uint n = class_list->Number();
  338|     for(uint i = 0i < n; ++i){
  339|         Classc = class_list->Ref(i);
  340|         if(strcmp(namec->MetaclassName()) == 0)
  341|             classes.Append(c);
  342|     }
  343| 
  344|     return classes.Number();
  345| }
  346| 
  347| PtreeClass::NthMemberName(int nth)
  348| {
  349|     Member m;
  350| 
  351|     if(NthMember(nthm))
  352|         return m.Name();
  353|     else
  354|         return nil;
  355| }
  356| 
  357| int Class::IsMember(Ptree* name)
  358| {
  359|     Member mem;
  360|     if(LookupMember(namemem0))
  361|         return mem.Nth();
  362|     else
  363|         return -1;
  364| }
  365| 
  366| bool Class::LookupMemberType(Ptree* name, TypeInfo& mem_type)
  367| {
  368|     return class_environment->Lookup(namemem_type);
  369| }
  370| 
  371| 
  372| // translation of classes
  373| 
  374| void Class::TranslateClass(Environment* e)
  375| {
  376| }
  377| 
  378| /*
  379|   The class specifier is inserted between the class keyword and
  380|   the class name.  This is meaningless unless the compiler is MSVC++.
  381|   e.g.
  382|       class __declspec(dllexport) X { ... };
  383| */
  384| void Class::AddClassSpecifier(Ptree* spec)
  385| {
  386|     new_class_specifier = spec;
  387| }
  388| 
  389| void Class::ChangeName(Ptree* name)
  390| {
  391|     new_class_name = name;
  392| }
  393| 
  394| void Class::ChangeBaseClasses(Ptree* list)
  395| {
  396|     CheckValidity("ChangeBaseClasses()");
  397|     if(list->IsLeaf())
  398|         list = Ptree::List(list);
  399| 
  400|     new_base_classes = list;    // list should include ':'
  401| }
  402| 
  403| void Class::RemoveBaseClasses()
  404| {
  405|     CheckValidity("RemoveBaseClasses()");
  406|     new_base_classes = nil;
  407| }
  408| 
  409| void Class::AppendBaseClass(Class* c, int specifier, bool is_virtual)
  410| {
  411|     AppendBaseClass(c->Name(), specifieris_virtual);
  412| }
  413| 
  414| void Class::AppendBaseClass(char* name, int specifier, bool is_virtual)
  415| {
  416|     AppendBaseClass(new Leaf(name, strlen(name)), specifieris_virtual);
  417| }
  418| 
  419| void Class::AppendBaseClass(Ptree* name, int specifier, bool is_virtual)
  420| {
  421|     CheckValidity("AppendBaseClass()");
  422| 
  423|     Ptreelf;
  424|     switch(specifier){
  425|     case Public :
  426|         lf = public_t;
  427|         break;
  428|     case Protected :
  429|         lf = protected_t;
  430|         break;
  431|     case Private :
  432|         lf = private_t;
  433|         break;
  434|     default :
  435|         MopErrorMessage("Class::AppendBaseClass()""bad specifier");
  436|         lf = nil;
  437|         break;
  438|     }
  439| 
  440|     Ptreesuper = Ptree::List(lfname);
  441| 
  442|     if(is_virtual)
  443|         super = Ptree::Cons(virtual_tsuper);
  444| 
  445|     if(new_base_classes == nil)
  446|         new_base_classes = Ptree::List(colon_tsuper);
  447|     else
  448|         new_base_classes = Ptree::Append(new_base_classes,
  449|                                     Ptree::List(comma_tsuper));
  450| }
  451| 
  452| void Class::ChangeMember(Member& m)
  453| {
  454|     CheckValidity("ChangeMember()");
  455| 
  456|     if(changed_member_list == nil)
  457|         changed_member_list = new ChangedMemberList;
  458| 
  459|     changed_member_list->Append(&m, Undefined);
  460| }
  461| 
  462| void Class::AppendMember(Member& m, int access)
  463| {
  464|     CheckValidity("AppendMember()");
  465|     if(appended_member_list == nil)
  466|         appended_member_list = new ChangedMemberList;
  467| 
  468|     appended_member_list->Append(&maccess);
  469| }
  470| 
  471| void Class::AppendMember(Ptree* p)
  472| {
  473|     CheckValidity("AppendMember()");
  474|     appended_code = Ptree::Snoc(appended_codep);
  475| }
  476| 
  477| void Class::RemoveMember(Member& m)
  478| {
  479|     CheckValidity("RemoveMember()");
  480|     m.Remove();
  481|     ChangeMember(m);
  482| }
  483| 
  484| void Class::CheckValidity(char* name)
  485| {
  486|     if(done_decl_translation)
  487|         MopWarningMessage2(name" is available only in TranslateClass().");
  488| }
  489| 
  490| // TranslateMemberFunction() is invoked only if the function is
  491| // implemented out of the class declaration (not inlined.)
  492| 
  493| void Class::TranslateMemberFunction(Environment*, Member& m)
  494| {
  495| }
  496| 
  497| ChangedMemberList::CmemClass::GetChangedMember(Ptree* decl)
  498| {
  499|     if(changed_member_list == nil)
  500|         return nil;
  501|     else
  502|         return changed_member_list->Lookup(decl);
  503| }
  504| 
  505| // translation of expressions
  506| 
  507| /*
  508|   init is either "= <expression>" or "( <expression> )".
  509| */
  510| PtreeClass::TranslateInitializer(Environment* env, Ptree*,
  511|                       Ptree* init)
  512| {
  513|     if(init->Car()->Eq('('))
  514|         return TranslateArguments(envinit);
  515|     else{
  516|         Ptreeexp = init->Second();
  517|         Ptreeexp2 = TranslateExpression(envexp);
  518|         if(exp == exp2)
  519|             return init;
  520|         else
  521|             return Ptree::List(init->Car(), exp2);
  522|     }
  523| }
  524| 
  525| PtreeClass::TranslateNew(Environment* env, Ptree* header,
  526|                          Ptree* op, Ptree* placement, Ptree* tname,
  527|                       Ptree* arglist)
  528| {
  529|     Ptreeexp2;
  530| 
  531|     if(header != nil && !header->Eq("::"))
  532|         ErrorMessage(env"unsupported user keyword: "headerop);
  533| 
  534|     Ptreetname2 = TranslateNewType(envtname);
  535|     if(arglist == nil)
  536|         exp2 = Ptree::List(TranslateArguments(envplacement), tname2);
  537|     else
  538|         exp2 = Ptree::List(TranslateArguments(envplacement), tname2,
  539|                          TranslateArguments(envarglist));
  540| 
  541|     if(header == nil)
  542|         return new PtreeNewExpr(op, exp2);
  543|     else
  544|         return new PtreeNewExpr(header, Ptree::Cons(op, exp2));
  545| }
  546| 
  547| PtreeClass::TranslateDelete(Environment* env, Ptree* op, Ptree* obj)
  548| {
  549|     Ptreeobj2 = TranslateExpression(envobj);
  550|     return new PtreeDeleteExpr(op, Ptree::List(obj2));
  551| }
  552| 
  553| PtreeClass::TranslateAssign(Environment* env, Ptree* left, Ptree* op,
  554|                       Ptree* right)
  555| {
  556|     Ptreeleft2 = TranslateExpression(envleft);
  557|     Ptreeright2 = TranslateExpression(envright);
  558|     return new PtreeAssignExpr(left2, Ptree::List(op, right2));
  559| }
  560| 
  561| PtreeClass::TranslateBinary(Environment* env, Ptree* lexpr, Ptree* op,
  562|                       Ptree* rexpr)
  563| {
  564|     return new PtreeInfixExpr(TranslateExpression(env, lexpr),
  565|                       Ptree::List(op, TranslateExpression(env, rexpr)));
  566| }
  567| 
  568| PtreeClass::TranslateUnary(Environment* env, Ptree* op, Ptree* object)
  569| {
  570|     return new PtreeUnaryExpr(op, Ptree::List(TranslateExpression(env,
  571|                       object)));
  572| }
  573| 
  574| PtreeClass::TranslateSubscript(Environment* env, Ptree* object,
  575|                       Ptree* index)
  576| {
  577|     Ptreeobject2 = TranslateExpression(envobject);
  578|     Ptreeexp = index->Second();
  579|     Ptreeexp2 = TranslateExpression(envexp);
  580|     if(exp == exp2)
  581|         return new PtreeArrayExpr(object2, index);
  582|     else
  583|         return new PtreeArrayExpr(object2,
  584|                                Ptree::ShallowSubst(exp2, exp, index));
  585| }
  586| 
  587| PtreeClass::TranslatePostfix(Environment* env, Ptree* object,
  588|                       Ptree* op)
  589| {
  590|     return new PtreePostfixExpr(TranslateExpression(env, object),
  591|                       Ptree::List(op));
  592| }
  593| 
  594| /*
  595|    TranslateFunctionCall() is for the overloaded function call operator ().
  596| */
  597| PtreeClass::TranslateFunctionCall(Environment* env, Ptree* object,
  598|                       Ptree* arglist)
  599| {
  600|     return new PtreeFuncallExpr(TranslateExpression(env, object),
  601|                              TranslateArguments(env, arglist));
  602| }
  603| 
  604| PtreeClass::TranslateMemberCall(Environment* env, Ptree* object,
  605|                                Ptree* op, Ptree* member, Ptree* arglist)
  606| {
  607|     Ptreefunc;
  608| 
  609|     object = TranslateExpression(envobject);
  610|     func = Ptree::List(opmember);
  611|     if(op->Eq('.'))
  612|         func = new PtreeDotMemberExpr(object, func);
  613|     else
  614|         func = new PtreeArrowMemberExpr(object, func);
  615| 
  616|     arglist = TranslateArguments(envarglist);
  617|     return new PtreeFuncallExpr(func, arglist);
  618| }
  619| 
  620| PtreeClass::TranslateMemberCall(Environment* env,
  621|                                Ptree* member, Ptree* arglist)
  622| {
  623|     return new PtreeFuncallExpr(member, TranslateArguments(env, arglist));
  624| }
  625| 
  626| PtreeClass::TranslateMemberRead(Environment* env, Ptree* object,
  627|                              Ptree* op, Ptree* member)
  628| {
  629|     object = TranslateExpression(envobject);
  630|     Ptreerest = Ptree::List(opmember);
  631|     if(op->Eq('.'))
  632|         return new PtreeDotMemberExpr(object, rest);
  633|     else
  634|         return new PtreeArrowMemberExpr(object, rest);
  635| }
  636| 
  637| PtreeClass::TranslateMemberRead(Environment*, Ptree* member)
  638| {
  639|     return member;
  640| }
  641| 
  642| PtreeClass::TranslateMemberWrite(Environment* env, Ptree* object,
  643|                                 Ptree* op, Ptree* member, Ptree* assign_op,
  644|                       Ptree* expr)
  645| {
  646|     // Note: If this function is invoked, TranslateAssign() on the
  647|     // member does not work.  Suppose that the expression is p->m = 3.
  648|     // Although TranslateMemberWrite() is invoked on p's class,
  649|     // TranslateAssign() is not invoked on m's class.  This is a sort
  650|     // of bug, but I don't know how to fix.
  651| 
  652|     Ptreeleft;
  653|     object = TranslateExpression(envobject),
  654|     left = Ptree::List(opmember);
  655|     if(op->Eq('.'))
  656|         left = new PtreeDotMemberExpr(object, left);
  657|     else
  658|         left = new PtreeArrowMemberExpr(object, left);
  659| 
  660|     expr = TranslateExpression(envexpr);
  661|     return new PtreeAssignExpr(left, Ptree::List(assign_op, expr));
  662| }
  663| 
  664| PtreeClass::TranslateMemberWrite(Environment* env, Ptree* member,
  665|                                 Ptree* assign_op, Ptree* expr)
  666| {
  667|     return new PtreeAssignExpr(member,
  668|                              Ptree::List(assign_op,
  669|                                     TranslateExpression(env, expr)));
  670| }
  671| 
  672| PtreeClass::TranslateUnaryOnMember(Environment* env, Ptree* unary_op,
  673|                                   Ptree* object, Ptree* access_op,
  674|                              Ptree* member_name)
  675| {
  676|     Ptreeright;
  677|     object = TranslateExpression(envobject),
  678|     right = Ptree::List(access_opmember_name);
  679|     if(access_op->Eq('.'))
  680|         right = new PtreeDotMemberExpr(object, right);
  681|     else
  682|         right = new PtreeArrowMemberExpr(object, right);
  683| 
  684|     return new PtreeUnaryExpr(unary_op, Ptree::List(right));
  685| }
  686| 
  687| PtreeClass::TranslateUnaryOnMember(Environment*, Ptree* unary_op,
  688|                              Ptree* member_name)
  689| {
  690|     return new PtreeUnaryExpr(unary_op, Ptree::List(member_name));
  691| }
  692| 
  693| PtreeClass::TranslatePostfixOnMember(Environment* env,
  694|                                     Ptree* object, Ptree* access_op,
  695|                                     Ptree* member_name, Ptree* postfix_op)
  696| {
  697|     Ptreeleft;
  698|     object = TranslateExpression(envobject),
  699|     left = Ptree::List(access_opmember_name);
  700|     if(access_op->Eq('.'))
  701|         left = new PtreeDotMemberExpr(object, left);
  702|     else
  703|         left = new PtreeArrowMemberExpr(object, left);
  704| 
  705|     return new PtreePostfixExpr(left, Ptree::List(postfix_op));
  706| }
  707| 
  708| PtreeClass::TranslatePostfixOnMember(Environment*,
  709|                                     Ptree* member_name, Ptree* postfix_op)
  710| {
  711|     return new PtreePostfixExpr(member_name, Ptree::List(postfix_op));
  712| }
  713| 
  714| PtreeClass::TranslatePointer(Environment*, Ptree* var_name)
  715| {
  716|     return var_name;
  717| }
  718| 
  719| PtreeClass::TranslateUserStatement(Environment* env, Ptree*,
  720|                Ptree*,
  721|                              Ptree* keyword, Ptree*)
  722| {
  723|     ErrorMessage(env"unsupported user statement: "keywordkeyword);
  724|     return nil;
  725| }
  726| 
  727| PtreeClass::TranslateStaticUserStatement(Environment* env,
  728|                              Ptree* keyword, Ptree*)
  729| {
  730|     ErrorMessage(env"unsupported user statement: "keywordkeyword);
  731|     return nil;
  732| }
  733| 
  734| PtreeClass::StripClassQualifier(Ptree* qualified_name)
  735| {
  736|     if(qualified_name->IsLeaf())
  737|         return qualified_name;
  738|     else
  739|         return Ptree::First(Ptree::Last(qualified_name));
  740| }
  741| 
  742| 
  743| // utilities for translation
  744| 
  745| PtreeClass::TranslateExpression(Environment* env, Ptree* exp)
  746| {
  747|     if(exp == nil)
  748|         return exp;
  749|     else
  750|         return env->GetWalker()->Translate(exp);
  751| }
  752| 
  753| PtreeClass::TranslateExpression(Environment* env, Ptree* exp,
  754|                       TypeInfo& type)
  755| {
  756|     if(exp == nil){
  757|         type.Unknown();
  758|         return exp;
  759|     }
  760|     else{
  761|         env->GetWalker()->Typeof(exptype);
  762|         return env->GetWalker()->Translate(exp);
  763|     }
  764| }
  765| 
  766| PtreeClass::TranslateStatement(Environment* env, Ptree* exp)
  767| {
  768|     WarnObsoleteness("Class::TranslateStatement()",
  769|                    "Class::TranslateExpression()");
  770|     return TranslateExpression(envexp);
  771| }
  772| 
  773| PtreeClass::TranslateNewType(Environment* env, Ptree* type)
  774| {
  775|     return env->GetWalker()->TranslateNew3(type);
  776| }
  777| 
  778| PtreeClass::TranslateArguments(Environment* env, Ptree* arglist)
  779| {
  780|     return env->GetWalker()->TranslateArguments(arglist);
  781| }
  782| 
  783| PtreeClass::TranslateFunctionBody(Environment* env, Member& m, Ptree* body)
  784| {
  785|     Walker* w = env->GetWalker();
  786|     return w->RecordArgsAndTranslateFbody(thism.ArgumentList(), body);
  787| }
  788| 
  789| // others
  790| 
  791| void Class::SetEnvironment(Environment* e)
  792| {
  793|     class_environment = e;
  794|     e->SetMetaobject(this);
  795| }
  796| 
  797| // This metaobject cannot handle templates
  798| 
  799| bool Class::AcceptTemplate()
  800| {
  801|     return FALSE;       // Only the subclasses of TemplateClass can
  802|                       // return true.
  803| }
  804| 
  805| /*
  806|   At the beginning, Initialize() is once called on each metaclass.
  807|   The subclasses of Class may define their own Initialize().
  808|   Initialize() returns FALSE if the initialization fails.
  809| */
  810| bool Class::Initialize()
  811| {
  812|     return TRUE;
  813| }
  814| 
  815| void Class::FinalizeAll(std::ostream& out)
  816| {
  817|     if(class_list == nil)
  818|         return;
  819| 
  820|     int n = class_list->Number();
  821|     for(int i = 0i < n; ++i){
  822|         Classc = class_list->Ref(i);
  823|         if(c != nil){
  824|             Ptreep = c->FinalizeInstance();
  825|             if(p != nil){
  826|                p->Write(out);
  827|                out << '\n';
  828|         }
  829|         }
  830|     }
  831| }
  832| 
  833| PtreeClass::FinalizeInstance()
  834| {
  835|     return Finalize();
  836| }
  837| 
  838| /*
  839|   *Obsolete*
  840| 
  841|   Finalize() is called on each metaobject at the end.  The returned
  842|   code is appended to the resulting file.  Note that Initialize()
  843|   is called on each metaclass although Finalize() is on each metaobject.
  844| */
  845| PtreeClass::Finalize()
  846| {
  847|     return nil;
  848| }
  849| 
  850| PtreeClass::FinalizeClass()
  851| {
  852|     return nil;
  853| }
  854| 
  855| void Class::RegisterNewModifier(char* str)
  856| {
  857|     if(!Lex::RecordKeyword(str, UserKeyword))
  858|         MopErrorMessage("Class::RegisterNewModifier()",
  859|                       "the keyword is already used.");
  860| }
  861| 
  862| void Class::RegisterNewAccessSpecifier(char* str)
  863| {
  864|     if(!Lex::RecordKeyword(str, UserKeyword4))
  865|         MopErrorMessage("Class::RegisterNewAccessSpecifier()",
  866|                       "the keyword is already used.");
  867| }
  868| 
  869| void Class::RegisterNewMemberModifier(char* str)
  870| {
  871|     if(!Lex::RecordKeyword(str, UserKeyword5))
  872|         MopErrorMessage("Class::RegisterNewMemberModifier()",
  873|                       "the keyword is already used.");
  874| }
  875| 
  876| void Class::RegisterNewWhileStatement(char* str)
  877| {
  878|     if(!Lex::RecordKeyword(str, UserKeyword))
  879|         MopErrorMessage("Class::RegisterNewWhileStatement()",
  880|                       "the keyword is already used.");
  881| }
  882| 
  883| void Class::RegisterNewForStatement(char* str)
  884| {
  885|     if(!Lex::RecordKeyword(str, UserKeyword3))
  886|         MopErrorMessage("Class::RegisterNewForStatement()",
  887|                       "the keyword is already used.");
  888| }
  889| 
  890| void Class::RegisterNewClosureStatement(char* str)
  891| {
  892|     if(!Lex::RecordKeyword(str, UserKeyword2))
  893|         MopErrorMessage("Class::RegisterNewClosureStatement()",
  894|                       "the keyword is already used.");
  895| }
  896| 
  897| void Class::RegisterMetaclass(char* keyword, char* class_name)
  898| {
  899|     if(Lex::RecordKeyword(keyword, UserKeyword))
  900|         if(Environment::RecordClasskeyword(keywordclass_name))
  901|            return;
  902| 
  903|     MopErrorMessage("Class::RegisterMetaclass()",
  904|                    "the keyword is already used.");
  905| }
  906| 
  907| void Class::ChangeDefaultMetaclass(char* name)
  908| {
  909|     Walker::ChangeDefaultMetaclass(name);
  910| }
  911| 
  912| void Class::SetMetaclassForFunctions(char* name)
  913| {
  914|     metaclass_for_c_functions = name;
  915| }
  916| 
  917| void Class::InsertBeforeStatement(Environment* env, Ptree* p)
  918| {
  919|     Walker* w = env->GetWalker();
  920|     if(w->IsClassWalker())
  921|         ((ClassWalker*)w)->InsertBeforeStatement(p);
  922|     else
  923|         MopWarningMessage("Class::InsertBeforeStatement()",
  924|                       "cannot insert");
  925| }
  926| 
  927| void Class::AppendAfterStatement(Environment* env, Ptree* p)
  928| {
  929|     Walker* w = env->GetWalker();
  930|     if(w->IsClassWalker())
  931|         ((ClassWalker*)w)->AppendAfterStatement(p);
  932|     else
  933|         MopWarningMessage("Class::AppendAfterStatement()",
  934|                       "cannot append");
  935| }
  936| 
  937| void Class::InsertBeforeToplevel(Environment* env, Class* c)
  938| {
  939|     Walker* w = env->GetWalker();
  940|     if(w->IsClassWalker())
  941|         InsertBeforeToplevel(env, ((ClassWalker*)w)->ConstructClass(c));
  942|     else
  943|         MopWarningMessage("Class::InsertBeforeToplevel()",
  944|                       "cannot insert");
  945| }
  946| 
  947| void Class::InsertBeforeToplevel(Environment* env, Member& mem)
  948| {
  949|     Walker* w = env->GetWalker();
  950|     if(w->IsClassWalker()){
  951|         ChangedMemberList::Cmem cmem;
  952|         Member::Copy(&mem, &cmem);
  953|         InsertBeforeToplevel(env, ((ClassWalker*)w)->ConstructMember(&cmem));
  954|     }
  955|     else
  956|         MopWarningMessage("Class::InsertBeforeToplevel()",
  957|                       "cannot insert");
  958| }
  959| 
  960| void Class::InsertBeforeToplevel(Environment* env, Ptree* p)
  961| {
  962|     Walker* w = env->GetWalker();
  963|     if(w->IsClassWalker())
  964|         ((ClassWalker*)w)->InsertBeforeToplevel(p);
  965|     else
  966|         MopWarningMessage("Class::InsertBeforeToplevel()",
  967|                       "cannot insert");
  968| }
  969| 
  970| void Class::AppendAfterToplevel(Environment* env, Class* c)
  971| {
  972|     Walker* w = env->GetWalker();
  973|     if(w->IsClassWalker())
  974|         AppendAfterToplevel(env, ((ClassWalker*)w)->ConstructClass(c));
  975|     else
  976|         MopWarningMessage("Class::AppendAfterToplevel()",
  977|                       "cannot insert");
  978| }
  979| 
  980| void Class::AppendAfterToplevel(Environment* env, Member& mem)
  981| {
  982|     Walker* w = env->GetWalker();
  983|     if(w->IsClassWalker()){
  984|         ChangedMemberList::Cmem cmem;
  985|         Member::Copy(&mem, &cmem);
  986|         AppendAfterToplevel(env, ((ClassWalker*)w)->ConstructMember(&cmem));
  987|     }
  988|     else
  989|         MopWarningMessage("Class::AppendAfterToplevel()",
  990|                       "cannot insert");
  991| }
  992| 
  993| void Class::AppendAfterToplevel(Environment* env, Ptree* p)
  994| {
  995|     Walker* w = env->GetWalker();
  996|     if(w->IsClassWalker())
  997|         ((ClassWalker*)w)->AppendAfterToplevel(p);
  998|     else
  999|         MopWarningMessage("Class::AppendAfterToplevel()",
 1000|                       "cannot append");
 1001| }
 1002| 
 1003| bool Class::InsertDeclaration(Environment* env, Ptree* decl)
 1004| {
 1005|     return InsertDeclaration(envdecl, nil, nil);
 1006| }
 1007| 
 1008| bool Class::InsertDeclaration(Environment* env, Ptree* decl,
 1009|                             Ptree* key, void* client_data)
 1010| {
 1011|     Walker* w = env->GetWalker();
 1012|     if(w->IsClassWalker())
 1013|         return ((ClassWalker*)w)->InsertDeclaration(declthiskey,
 1014|                       client_data);
 1015|     else{
 1016|         MopWarningMessage("Class::InsertDeclaration()",
 1017|                       "cannot insert");
 1018|         return FALSE;
 1019|     }
 1020| }
 1021| 
 1022| voidClass::LookupClientData(Environment* env, Ptree* key)
 1023| {
 1024|     Walker* w = env->GetWalker();
 1025|     if(w->IsClassWalker())
 1026|         return ((ClassWalker*)w)->LookupClientData(thiskey);
 1027|     else{
 1028|         MopWarningMessage("Class::LookupClientData()",
 1029|                       "cannot lookup");
 1030|         return nil;
 1031|     }
 1032| }
 1033| 
 1034| void Class::ErrorMessage(Environment* env, char* msg,
 1035|                        Ptree* name, Ptree* where)
 1036| {
 1037|     env->GetWalker()->ErrorMessage(msgnamewhere);
 1038| }
 1039| 
 1040| void Class::WarningMessage(Environment* env, char* msg,
 1041|                          Ptree* name, Ptree* where)
 1042| {
 1043|     env->GetWalker()->WarningMessage(msgnamewhere);
 1044| }
 1045| 
 1046| void Class::ErrorMessage(char* msg, Ptree* name, Ptree* where)
 1047| {
 1048|     Walker::InaccurateErrorMessage(msgnamewhere);
 1049| }
 1050| 
 1051| void Class::WarningMessage(char* msg, Ptree* name, Ptree* where)
 1052| {
 1053|     Walker::InaccurateWarningMessage(msgnamewhere);
 1054| }
 1055| 
 1056| bool Class::RecordCmdLineOption(char* key, char* value)
 1057| {
 1058|     if(num_of_cmd_options < MaxOptions * 2){
 1059|         cmd_options[num_of_cmd_options++] = key;
 1060|         cmd_options[num_of_cmd_options++] = value;
 1061|         return TRUE;
 1062|     }
 1063|     else
 1064|         return FALSE;
 1065| }
 1066| 
 1067| bool Class::LookupCmdLineOption(char* key)
 1068| {
 1069|     charvalue;
 1070|     return LookupCmdLineOption(keyvalue);
 1071| }
 1072| 
 1073| bool Class::LookupCmdLineOption(char* key, char*& value)
 1074| {
 1075|     for(int i = 0i < num_of_cmd_optionsi += 2)
 1076|         if(strcmp(keycmd_options[i]) == 0){
 1077|             value = cmd_options[i + 1];
 1078|             return TRUE;
 1079|         }
 1080| 
 1081|     return FALSE;
 1082| }
 1083| 
 1084| void Class::WarnObsoleteness(char* func, char* alt)
 1085| {
 1086|     MopWarningMessage2(func" is obsolete.");
 1087|     MopMoreWarningMessage("use "alt);
 1088| }
 1089| 
 1090| 
 1091| // class TemplateClass
 1092| 
 1093| void TemplateClass::InitializeInstance(Ptree* def, Ptree* margs)
 1094| {
 1095|     Class::InitializeInstance(GetClassInTemplate(def), margs);
 1096|     template_definition = def;
 1097| }
 1098| 
 1099| /*
 1100|   This is needed because TemplateClass may be instantiated for a class.
 1101| */
 1102| PtreeTemplateClass::GetClassInTemplate(Ptree* def)
 1103| {
 1104|     Ptreedecl = def->Ptree::Nth(4);
 1105|     if(decl == nil)
 1106|         return def;
 1107| 
 1108|     Ptreecdef = Walker::GetClassTemplateSpec(decl);
 1109|     if(cdef == nil)
 1110|         return def;
 1111|     else
 1112|         return cdef;
 1113| }
 1114| 
 1115| bool TemplateClass::Initialize()
 1116| {
 1117|     return TRUE;
 1118| }
 1119| 
 1120| charTemplateClass::MetaclassName()
 1121| {
 1122|     return "TemplateClass";
 1123| }
 1124| 
 1125| PtreeTemplateClass::TemplateArguments()
 1126| {
 1127|     return template_definition->Third();
 1128| }
 1129| 
 1130| bool TemplateClass::AcceptTemplate()
 1131| {
 1132|     return TRUE;
 1133| }
 1134| 
 1135| /*
 1136|   Translate a template instantiation.
 1137| */
 1138| PtreeTemplateClass::TranslateInstantiation(Environment*, Ptree* spec)
 1139| {
 1140|     return spec;
 1141| }
 1142| 
 1143| // class ClassArray
 1144| 
 1145| ClassArray::ClassArray(int s)
 1146| {
 1147|     num = 0;
 1148|     if(s < 1)
 1149|         s = 1;
 1150| 
 1151|     size = s;
 1152|     array = new (GC) Class*[s];
 1153| }
 1154| 
 1155| void ClassArray::Append(Class* p)
 1156| {
 1157|     if(num >= size){
 1158|         size += 16;
 1159|         Class** a = new (GC) Class*[size];
 1160|         memmove(aarray, size_t(num * sizeof(Class*)));
 1161|         array = a;
 1162|     }
 1163| 
 1164|     array[num++] = p;
 1165| }
 1166| 
 1167| Class*& ClassArray::Ref(uint i)
 1168| {
 1169|     if(i < num)
 1170|         return array[i];
 1171|     else{
 1172|         MopErrorMessage("ClassArray""out of range");
 1173|         return array[0];
 1174|     }
 1175| }
 1176| 
 1177| 
 1178| //
 1179| // class opcxx_ListOfMetaclass  --- not documented cla
 1180| //
 1181| 
 1182| opcxx_ListOfMetaclass* opcxx_ListOfMetaclass::head = nil;
 1183| 
 1184| static ClassCreateClass(Ptree* def, Ptree* marg)
 1185| {
 1186|     Classmetaobject = new Class;
 1187|     metaobject->InitializeInstance(defmarg);
 1188|     return metaobject;
 1189| }
 1190| 
 1191| opcxx_ListOfMetaclassopcxx_init_Class()
 1192| {
 1193|     return new opcxx_ListOfMetaclass("Class", CreateClass, Class::Initialize,
 1194|                nil);
 1195| }
 1196| 
 1197| static ClassCreateTemplateClass(Ptree* def, Ptree* marg)
 1198| {
 1199|     Classmetaobject = new TemplateClass;
 1200|     metaobject->InitializeInstance(defmarg);
 1201|     return metaobject;
 1202| }
 1203| 
 1204| opcxx_ListOfMetaclassopcxx_init_TemplateClass()
 1205| {
 1206|     return new opcxx_ListOfMetaclass("TemplateClass", CreateTemplateClass,
 1207|                                   TemplateClass::Initialize, nil);
 1208| }
 1209| 
 1210| opcxx_ListOfMetaclass::opcxx_ListOfMetaclass(char* n,
 1211|                                     opcxx_MetaclassCreator c,
 1212|                              bool (*initialize)(),
 1213|                              Ptree* (*fin)())
 1214| {
 1215|     proc = c;
 1216|     name = n;
 1217|     if(AlreadyRecorded(n))
 1218|         next = nil;
 1219|     else{
 1220|         next = head;
 1221|         head = this;
 1222|         finalizer = fin;
 1223|         if(!initialize())
 1224|             MopErrorMessage("Initialize()",
 1225|                           "the initialization process failed.");
 1226|     }
 1227| }
 1228| 
 1229| Classopcxx_ListOfMetaclass::New(Ptree* name, Ptree* def, Ptree* marg)
 1230| {
 1231|     if(name != nil){
 1232|         opcxx_ListOfMetaclassp = head;
 1233|         while(p != nil){
 1234|             if(name->Eq(p->name))
 1235|                return (*p->proc)(defmarg);
 1236|         else
 1237|                p = p->next;
 1238|         }
 1239|     }
 1240| 
 1241|     return nil;        // the metaclass is not loaded.
 1242| }
 1243| 
 1244| Classopcxx_ListOfMetaclass::New(char* name, Ptree* def, Ptree* marg)
 1245| {
 1246|     if(name != nil){
 1247|         opcxx_ListOfMetaclassp = head;
 1248|         while(p != nil){
 1249|             if(strcmp(namep->name) == 0)
 1250|                return (*p->proc)(defmarg);
 1251|         else
 1252|                p = p->next;
 1253|         }
 1254|     }
 1255| 
 1256|     return nil;        // the metaclass is not loaded.
 1257| }
 1258| 
 1259| // FinalizeAll() calls all FinalizeClass()s.
 1260| 
 1261| void opcxx_ListOfMetaclass::FinalizeAll(std::ostream& out)
 1262| {
 1263|     for(opcxx_ListOfMetaclassp = headp != nil; p = p->next)
 1264|         if(p->finalizer != nil){
 1265|             Ptreecode = (*p->finalizer)();
 1266|             if(code != nil){
 1267|                code->Write(out);
 1268|                out << '\n';
 1269|         }
 1270|         }
 1271| }
 1272| 
 1273| bool opcxx_ListOfMetaclass::AlreadyRecorded(char* name)
 1274| {
 1275|     for(opcxx_ListOfMetaclassp = headp != nil; p = p->next)
 1276|         if(strcmp(namep->name) == 0)
 1277|            return TRUE;
 1278| 
 1279|     return FALSE;
 1280| }
 1281| 
 1282| bool opcxx_ListOfMetaclass::AlreadyRecorded(Ptree* name)
 1283| {
 1284|     for(opcxx_ListOfMetaclassp = headp != nil; p = p->next)
 1285|         if(name->Eq(p->name))
 1286|            return TRUE;
 1287| 
 1288|     return FALSE;
 1289| }
 1290| 
 1291| void opcxx_ListOfMetaclass::PrintAllMetaclasses()
 1292| {
 1293|     for(opcxx_ListOfMetaclassp = headp != nil; p = p->next)
 1294|         std::cout << p->name << '\n';
 1295| }