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_ListOfMetaclass* classCreator = NULL;
44| static opcxx_ListOfMetaclass* templateCreator = NULL;
45| static Class* CreateClass(Ptree* def, Ptree* marg);
46| static Class* CreateTemplateClass(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_init) return;
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| Ptree* def;
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| char* Class::MetaclassName()
132| {
133| return "Class";
134| }
135|
136| Ptree* Class::Comments()
137| {
138| if (definition->IsA(ntClassSpec))
139| return ((PtreeClassSpec*)definition)->GetComments();
140| return nil;
141| }
142|
143| Ptree* Class::Name()
144| {
145| return definition->Second();
146| }
147|
148| Ptree* Class::BaseClasses()
149| {
150| return definition->Third();
151| }
152|
153| Ptree* Class::Members()
154| {
155| return definition->Nth(3)->Second();
156| }
157|
158| Class* Class::NthBaseClass(int n)
159| {
160| Ptree* bases = definition->Third();
161| while(bases != nil){
162| bases = bases->Cdr(); // sk
163| if(n-- == 0){
164| Ptree* base_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| Ptree* bases = definition->Third();
177| while(bases != nil){
178| bases = bases->Cdr();
179| Ptree* base_class = bases->Car()->Last()->Car();
180| if(base_class->Eq(name))
181| return TRUE;
182| else{
183| Class* metaobject
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| Ptree* bases = definition->Third();
198| while(bases != nil){
199| bases = bases->Cdr();
200| Ptree* base_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| Ptree* Class::NthBaseClassName(int n)
211| {
212| Ptree* bases = 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| MemberList* mlist = GetMemberList();
227| if(mlist == nil || nth >= mlist->Number())
228| return FALSE;
229|
230| mem.Set(this, mlist->Ref(nth)->declarator, nth);
231| return TRUE;
232| }
233|
234| bool Class::LookupMember(Ptree* name)
235| {
236| Member m;
237| return LookupMember(name, m);
238| }
239|
240| bool Class::LookupMember(Ptree* name, Member& mem, int index)
241| {
242| MemberList* mlist = GetMemberList();
243| if(mlist == nil)
244| return FALSE;
245|
246| int nth = mlist->Lookup(class_environment, name, index);
247| if(nth < 0)
248| return FALSE;
249|
250| mem.Set(this, mlist->Ref(nth)->declarator, nth);
251| return TRUE;
252| }
253|
254| bool Class::LookupMember(char* name)
255| {
256| Member m;
257| return LookupMember(name, m);
258| }
259|
260| bool Class::LookupMember(char* name, Member& mem, int index)
261| {
262| MemberList* mlist = GetMemberList();
263| if(mlist == nil)
264| return FALSE;
265|
266| int nth = mlist->Lookup(class_environment, name, index);
267| if(nth < 0)
268| return FALSE;
269|
270| mem.Set(this, mlist->Ref(nth)->declarator, nth);
271| return TRUE;
272| }
273|
274| MemberList* Class::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| ClassArray& Class::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 = 0; i < n; ++i){
302| Class* c = 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 = 0; i < n; ++i){
323| Class* c = 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 = 0; i < n; ++i){
339| Class* c = class_list->Ref(i);
340| if(strcmp(name, c->MetaclassName()) == 0)
341| classes.Append(c);
342| }
343|
344| return classes.Number();
345| }
346|
347| Ptree* Class::NthMemberName(int nth)
348| {
349| Member m;
350|
351| if(NthMember(nth, m))
352| return m.Name();
353| else
354| return nil;
355| }
356|
357| int Class::IsMember(Ptree* name)
358| {
359| Member mem;
360| if(LookupMember(name, mem, 0))
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(name, mem_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;
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(), specifier, is_virtual);
412| }
413|
414| void Class::AppendBaseClass(char* name, int specifier, bool is_virtual)
415| {
416| AppendBaseClass(new Leaf(name, strlen(name)), specifier, is_virtual);
417| }
418|
419| void Class::AppendBaseClass(Ptree* name, int specifier, bool is_virtual)
420| {
421| CheckValidity("AppendBaseClass()");
422|
423| Ptree* lf;
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| Ptree* super = Ptree::List(lf, name);
441|
442| if(is_virtual)
443| super = Ptree::Cons(virtual_t, super);
444|
445| if(new_base_classes == nil)
446| new_base_classes = Ptree::List(colon_t, super);
447| else
448| new_base_classes = Ptree::Append(new_base_classes,
449| Ptree::List(comma_t, super));
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(&m, access);
469| }
470|
471| void Class::AppendMember(Ptree* p)
472| {
473| CheckValidity("AppendMember()");
474| appended_code = Ptree::Snoc(appended_code, p);
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::Cmem* Class::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| Ptree* Class::TranslateInitializer(Environment* env, Ptree*,
511| Ptree* init)
512| {
513| if(init->Car()->Eq('('))
514| return TranslateArguments(env, init);
515| else{
516| Ptree* exp = init->Second();
517| Ptree* exp2 = TranslateExpression(env, exp);
518| if(exp == exp2)
519| return init;
520| else
521| return Ptree::List(init->Car(), exp2);
522| }
523| }
524|
525| Ptree* Class::TranslateNew(Environment* env, Ptree* header,
526| Ptree* op, Ptree* placement, Ptree* tname,
527| Ptree* arglist)
528| {
529| Ptree* exp2;
530|
531| if(header != nil && !header->Eq("::"))
532| ErrorMessage(env, "unsupported user keyword: ", header, op);
533|
534| Ptree* tname2 = TranslateNewType(env, tname);
535| if(arglist == nil)
536| exp2 = Ptree::List(TranslateArguments(env, placement), tname2);
537| else
538| exp2 = Ptree::List(TranslateArguments(env, placement), tname2,
539| TranslateArguments(env, arglist));
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| Ptree* Class::TranslateDelete(Environment* env, Ptree* op, Ptree* obj)
548| {
549| Ptree* obj2 = TranslateExpression(env, obj);
550| return new PtreeDeleteExpr(op, Ptree::List(obj2));
551| }
552|
553| Ptree* Class::TranslateAssign(Environment* env, Ptree* left, Ptree* op,
554| Ptree* right)
555| {
556| Ptree* left2 = TranslateExpression(env, left);
557| Ptree* right2 = TranslateExpression(env, right);
558| return new PtreeAssignExpr(left2, Ptree::List(op, right2));
559| }
560|
561| Ptree* Class::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| Ptree* Class::TranslateUnary(Environment* env, Ptree* op, Ptree* object)
569| {
570| return new PtreeUnaryExpr(op, Ptree::List(TranslateExpression(env,
571| object)));
572| }
573|
574| Ptree* Class::TranslateSubscript(Environment* env, Ptree* object,
575| Ptree* index)
576| {
577| Ptree* object2 = TranslateExpression(env, object);
578| Ptree* exp = index->Second();
579| Ptree* exp2 = TranslateExpression(env, exp);
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| Ptree* Class::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| Ptree* Class::TranslateFunctionCall(Environment* env, Ptree* object,
598| Ptree* arglist)
599| {
600| return new PtreeFuncallExpr(TranslateExpression(env, object),
601| TranslateArguments(env, arglist));
602| }
603|
604| Ptree* Class::TranslateMemberCall(Environment* env, Ptree* object,
605| Ptree* op, Ptree* member, Ptree* arglist)
606| {
607| Ptree* func;
608|
609| object = TranslateExpression(env, object);
610| func = Ptree::List(op, member);
611| if(op->Eq('.'))
612| func = new PtreeDotMemberExpr(object, func);
613| else
614| func = new PtreeArrowMemberExpr(object, func);
615|
616| arglist = TranslateArguments(env, arglist);
617| return new PtreeFuncallExpr(func, arglist);
618| }
619|
620| Ptree* Class::TranslateMemberCall(Environment* env,
621| Ptree* member, Ptree* arglist)
622| {
623| return new PtreeFuncallExpr(member, TranslateArguments(env, arglist));
624| }
625|
626| Ptree* Class::TranslateMemberRead(Environment* env, Ptree* object,
627| Ptree* op, Ptree* member)
628| {
629| object = TranslateExpression(env, object);
630| Ptree* rest = Ptree::List(op, member);
631| if(op->Eq('.'))
632| return new PtreeDotMemberExpr(object, rest);
633| else
634| return new PtreeArrowMemberExpr(object, rest);
635| }
636|
637| Ptree* Class::TranslateMemberRead(Environment*, Ptree* member)
638| {
639| return member;
640| }
641|
642| Ptree* Class::TranslateMemberWrite(Environment* env, Ptree* object,
643| Ptree* op, Ptree* member, Ptree* assign_op,
644| Ptree* expr)
645| {
646|
647|
648|
649|
650|
651|
652| Ptree* left;
653| object = TranslateExpression(env, object),
654| left = Ptree::List(op, member);
655| if(op->Eq('.'))
656| left = new PtreeDotMemberExpr(object, left);
657| else
658| left = new PtreeArrowMemberExpr(object, left);
659|
660| expr = TranslateExpression(env, expr);
661| return new PtreeAssignExpr(left, Ptree::List(assign_op, expr));
662| }
663|
664| Ptree* Class::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| Ptree* Class::TranslateUnaryOnMember(Environment* env, Ptree* unary_op,
673| Ptree* object, Ptree* access_op,
674| Ptree* member_name)
675| {
676| Ptree* right;
677| object = TranslateExpression(env, object),
678| right = Ptree::List(access_op, member_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| Ptree* Class::TranslateUnaryOnMember(Environment*, Ptree* unary_op,
688| Ptree* member_name)
689| {
690| return new PtreeUnaryExpr(unary_op, Ptree::List(member_name));
691| }
692|
693| Ptree* Class::TranslatePostfixOnMember(Environment* env,
694| Ptree* object, Ptree* access_op,
695| Ptree* member_name, Ptree* postfix_op)
696| {
697| Ptree* left;
698| object = TranslateExpression(env, object),
699| left = Ptree::List(access_op, member_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| Ptree* Class::TranslatePostfixOnMember(Environment*,
709| Ptree* member_name, Ptree* postfix_op)
710| {
711| return new PtreePostfixExpr(member_name, Ptree::List(postfix_op));
712| }
713|
714| Ptree* Class::TranslatePointer(Environment*, Ptree* var_name)
715| {
716| return var_name;
717| }
718|
719| Ptree* Class::TranslateUserStatement(Environment* env, Ptree*,
720| Ptree*,
721| Ptree* keyword, Ptree*)
722| {
723| ErrorMessage(env, "unsupported user statement: ", keyword, keyword);
724| return nil;
725| }
726|
727| Ptree* Class::TranslateStaticUserStatement(Environment* env,
728| Ptree* keyword, Ptree*)
729| {
730| ErrorMessage(env, "unsupported user statement: ", keyword, keyword);
731| return nil;
732| }
733|
734| Ptree* Class::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| Ptree* Class::TranslateExpression(Environment* env, Ptree* exp)
746| {
747| if(exp == nil)
748| return exp;
749| else
750| return env->GetWalker()->Translate(exp);
751| }
752|
753| Ptree* Class::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(exp, type);
762| return env->GetWalker()->Translate(exp);
763| }
764| }
765|
766| Ptree* Class::TranslateStatement(Environment* env, Ptree* exp)
767| {
768| WarnObsoleteness("Class::TranslateStatement()",
769| "Class::TranslateExpression()");
770| return TranslateExpression(env, exp);
771| }
772|
773| Ptree* Class::TranslateNewType(Environment* env, Ptree* type)
774| {
775| return env->GetWalker()->TranslateNew3(type);
776| }
777|
778| Ptree* Class::TranslateArguments(Environment* env, Ptree* arglist)
779| {
780| return env->GetWalker()->TranslateArguments(arglist);
781| }
782|
783| Ptree* Class::TranslateFunctionBody(Environment* env, Member& m, Ptree* body)
784| {
785| Walker* w = env->GetWalker();
786| return w->RecordArgsAndTranslateFbody(this, m.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;
802|
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 = 0; i < n; ++i){
822| Class* c = class_list->Ref(i);
823| if(c != nil){
824| Ptree* p = c->FinalizeInstance();
825| if(p != nil){
826| p->Write(out);
827| out << '\n';
828| }
829| }
830| }
831| }
832|
833| Ptree* Class::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| Ptree* Class::Finalize()
846| {
847| return nil;
848| }
849|
850| Ptree* Class::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(keyword, class_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(env, decl, 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(decl, this, key,
1014| client_data);
1015| else{
1016| MopWarningMessage("Class::InsertDeclaration()",
1017| "cannot insert");
1018| return FALSE;
1019| }
1020| }
1021|
1022| void* Class::LookupClientData(Environment* env, Ptree* key)
1023| {
1024| Walker* w = env->GetWalker();
1025| if(w->IsClassWalker())
1026| return ((ClassWalker*)w)->LookupClientData(this, key);
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(msg, name, where);
1038| }
1039|
1040| void Class::WarningMessage(Environment* env, char* msg,
1041| Ptree* name, Ptree* where)
1042| {
1043| env->GetWalker()->WarningMessage(msg, name, where);
1044| }
1045|
1046| void Class::ErrorMessage(char* msg, Ptree* name, Ptree* where)
1047| {
1048| Walker::InaccurateErrorMessage(msg, name, where);
1049| }
1050|
1051| void Class::WarningMessage(char* msg, Ptree* name, Ptree* where)
1052| {
1053| Walker::InaccurateWarningMessage(msg, name, where);
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| char* value;
1070| return LookupCmdLineOption(key, value);
1071| }
1072|
1073| bool Class::LookupCmdLineOption(char* key, char*& value)
1074| {
1075| for(int i = 0; i < num_of_cmd_options; i += 2)
1076| if(strcmp(key, cmd_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| Ptree* TemplateClass::GetClassInTemplate(Ptree* def)
1103| {
1104| Ptree* decl = def->Ptree::Nth(4);
1105| if(decl == nil)
1106| return def;
1107|
1108| Ptree* cdef = 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| char* TemplateClass::MetaclassName()
1121| {
1122| return "TemplateClass";
1123| }
1124|
1125| Ptree* TemplateClass::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| Ptree* TemplateClass::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(a, array, 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 Class* CreateClass(Ptree* def, Ptree* marg)
1185| {
1186| Class* metaobject = new Class;
1187| metaobject->InitializeInstance(def, marg);
1188| return metaobject;
1189| }
1190|
1191| opcxx_ListOfMetaclass* opcxx_init_Class()
1192| {
1193| return new opcxx_ListOfMetaclass("Class", CreateClass, Class::Initialize,
1194| nil);
1195| }
1196|
1197| static Class* CreateTemplateClass(Ptree* def, Ptree* marg)
1198| {
1199| Class* metaobject = new TemplateClass;
1200| metaobject->InitializeInstance(def, marg);
1201| return metaobject;
1202| }
1203|
1204| opcxx_ListOfMetaclass* opcxx_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| Class* opcxx_ListOfMetaclass::New(Ptree* name, Ptree* def, Ptree* marg)
1230| {
1231| if(name != nil){
1232| opcxx_ListOfMetaclass* p = head;
1233| while(p != nil){
1234| if(name->Eq(p->name))
1235| return (*p->proc)(def, marg);
1236| else
1237| p = p->next;
1238| }
1239| }
1240|
1241| return nil;
1242| }
1243|
1244| Class* opcxx_ListOfMetaclass::New(char* name, Ptree* def, Ptree* marg)
1245| {
1246| if(name != nil){
1247| opcxx_ListOfMetaclass* p = head;
1248| while(p != nil){
1249| if(strcmp(name, p->name) == 0)
1250| return (*p->proc)(def, marg);
1251| else
1252| p = p->next;
1253| }
1254| }
1255|
1256| return nil;
1257| }
1258|
1259| // FinalizeAll() calls all FinalizeClass()s.
1260|
1261| void opcxx_ListOfMetaclass::FinalizeAll(std::ostream& out)
1262| {
1263| for(opcxx_ListOfMetaclass* p = head; p != nil; p = p->next)
1264| if(p->finalizer != nil){
1265| Ptree* code = (*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_ListOfMetaclass* p = head; p != nil; p = p->next)
1276| if(strcmp(name, p->name) == 0)
1277| return TRUE;
1278|
1279| return FALSE;
1280| }
1281|
1282| bool opcxx_ListOfMetaclass::AlreadyRecorded(Ptree* name)
1283| {
1284| for(opcxx_ListOfMetaclass* p = head; p != 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_ListOfMetaclass* p = head; p != nil; p = p->next)
1294| std::cout << p->name << '\n';
1295| }