1#include "AST.h"
2#include "Type.h"
3
4void
5WriteModifiers(FILE* to, int mod, int mask)
6{
7    int m = mod & mask;
8
9    if (m & OVERRIDE) {
10        fprintf(to, "@Override ");
11    }
12
13    if ((m & SCOPE_MASK) == PUBLIC) {
14        fprintf(to, "public ");
15    }
16    else if ((m & SCOPE_MASK) == PRIVATE) {
17        fprintf(to, "private ");
18    }
19    else if ((m & SCOPE_MASK) == PROTECTED) {
20        fprintf(to, "protected ");
21    }
22
23    if (m & STATIC) {
24        fprintf(to, "static ");
25    }
26
27    if (m & FINAL) {
28        fprintf(to, "final ");
29    }
30
31    if (m & ABSTRACT) {
32        fprintf(to, "abstract ");
33    }
34}
35
36void
37WriteArgumentList(FILE* to, const vector<Expression*>& arguments)
38{
39    size_t N = arguments.size();
40    for (size_t i=0; i<N; i++) {
41        arguments[i]->Write(to);
42        if (i != N-1) {
43            fprintf(to, ", ");
44        }
45    }
46}
47
48ClassElement::ClassElement()
49{
50}
51
52ClassElement::~ClassElement()
53{
54}
55
56Field::Field()
57    :ClassElement(),
58     modifiers(0),
59     variable(NULL)
60{
61}
62
63Field::Field(int m, Variable* v)
64    :ClassElement(),
65     modifiers(m),
66     variable(v)
67{
68}
69
70Field::~Field()
71{
72}
73
74void
75Field::GatherTypes(set<Type*>* types) const
76{
77    types->insert(this->variable->type);
78}
79
80void
81Field::Write(FILE* to)
82{
83    if (this->comment.length() != 0) {
84        fprintf(to, "%s\n", this->comment.c_str());
85    }
86    WriteModifiers(to, this->modifiers, SCOPE_MASK | STATIC | FINAL | OVERRIDE);
87    fprintf(to, "%s %s", this->variable->type->QualifiedName().c_str(),
88            this->variable->name.c_str());
89    if (this->value.length() != 0) {
90        fprintf(to, " = %s", this->value.c_str());
91    }
92    fprintf(to, ";\n");
93}
94
95Expression::~Expression()
96{
97}
98
99LiteralExpression::LiteralExpression(const string& v)
100    :value(v)
101{
102}
103
104LiteralExpression::~LiteralExpression()
105{
106}
107
108void
109LiteralExpression::Write(FILE* to)
110{
111    fprintf(to, "%s", this->value.c_str());
112}
113
114StringLiteralExpression::StringLiteralExpression(const string& v)
115    :value(v)
116{
117}
118
119StringLiteralExpression::~StringLiteralExpression()
120{
121}
122
123void
124StringLiteralExpression::Write(FILE* to)
125{
126    fprintf(to, "\"%s\"", this->value.c_str());
127}
128
129Variable::Variable()
130    :type(NULL),
131     name(),
132     dimension(0)
133{
134}
135
136Variable::Variable(Type* t, const string& n)
137    :type(t),
138     name(n),
139     dimension(0)
140{
141}
142
143Variable::Variable(Type* t, const string& n, int d)
144    :type(t),
145     name(n),
146     dimension(d)
147{
148}
149
150Variable::~Variable()
151{
152}
153
154void
155Variable::GatherTypes(set<Type*>* types) const
156{
157    types->insert(this->type);
158}
159
160void
161Variable::WriteDeclaration(FILE* to)
162{
163    string dim;
164    for (int i=0; i<this->dimension; i++) {
165        dim += "[]";
166    }
167    fprintf(to, "%s%s %s", this->type->QualifiedName().c_str(), dim.c_str(),
168            this->name.c_str());
169}
170
171void
172Variable::Write(FILE* to)
173{
174    fprintf(to, "%s", name.c_str());
175}
176
177FieldVariable::FieldVariable(Expression* o, const string& n)
178    :object(o),
179     clazz(NULL),
180     name(n)
181{
182}
183
184FieldVariable::FieldVariable(Type* c, const string& n)
185    :object(NULL),
186     clazz(c),
187     name(n)
188{
189}
190
191FieldVariable::~FieldVariable()
192{
193}
194
195void
196FieldVariable::Write(FILE* to)
197{
198    if (this->object != NULL) {
199        this->object->Write(to);
200    }
201    else if (this->clazz != NULL) {
202        fprintf(to, "%s", this->clazz->QualifiedName().c_str());
203    }
204    fprintf(to, ".%s", name.c_str());
205}
206
207
208Statement::~Statement()
209{
210}
211
212StatementBlock::StatementBlock()
213{
214}
215
216StatementBlock::~StatementBlock()
217{
218}
219
220void
221StatementBlock::Write(FILE* to)
222{
223    fprintf(to, "{\n");
224    int N = this->statements.size();
225    for (int i=0; i<N; i++) {
226        this->statements[i]->Write(to);
227    }
228    fprintf(to, "}\n");
229}
230
231void
232StatementBlock::Add(Statement* statement)
233{
234    this->statements.push_back(statement);
235}
236
237void
238StatementBlock::Add(Expression* expression)
239{
240    this->statements.push_back(new ExpressionStatement(expression));
241}
242
243ExpressionStatement::ExpressionStatement(Expression* e)
244    :expression(e)
245{
246}
247
248ExpressionStatement::~ExpressionStatement()
249{
250}
251
252void
253ExpressionStatement::Write(FILE* to)
254{
255    this->expression->Write(to);
256    fprintf(to, ";\n");
257}
258
259Assignment::Assignment(Variable* l, Expression* r)
260    :lvalue(l),
261     rvalue(r),
262     cast(NULL)
263{
264}
265
266Assignment::Assignment(Variable* l, Expression* r, Type* c)
267    :lvalue(l),
268     rvalue(r),
269     cast(c)
270{
271}
272
273Assignment::~Assignment()
274{
275}
276
277void
278Assignment::Write(FILE* to)
279{
280    this->lvalue->Write(to);
281    fprintf(to, " = ");
282    if (this->cast != NULL) {
283        fprintf(to, "(%s)", this->cast->QualifiedName().c_str());
284    }
285    this->rvalue->Write(to);
286}
287
288MethodCall::MethodCall(const string& n)
289    :obj(NULL),
290     clazz(NULL),
291     name(n)
292{
293}
294
295MethodCall::MethodCall(const string& n, int argc = 0, ...)
296    :obj(NULL),
297     clazz(NULL),
298     name(n)
299{
300  va_list args;
301  va_start(args, argc);
302  init(argc, args);
303  va_end(args);
304}
305
306MethodCall::MethodCall(Expression* o, const string& n)
307    :obj(o),
308     clazz(NULL),
309     name(n)
310{
311}
312
313MethodCall::MethodCall(Type* t, const string& n)
314    :obj(NULL),
315     clazz(t),
316     name(n)
317{
318}
319
320MethodCall::MethodCall(Expression* o, const string& n, int argc = 0, ...)
321    :obj(o),
322     clazz(NULL),
323     name(n)
324{
325  va_list args;
326  va_start(args, argc);
327  init(argc, args);
328  va_end(args);
329}
330
331MethodCall::MethodCall(Type* t, const string& n, int argc = 0, ...)
332    :obj(NULL),
333     clazz(t),
334     name(n)
335{
336  va_list args;
337  va_start(args, argc);
338  init(argc, args);
339  va_end(args);
340}
341
342MethodCall::~MethodCall()
343{
344}
345
346void
347MethodCall::init(int n, va_list args)
348{
349    for (int i=0; i<n; i++) {
350        Expression* expression = (Expression*)va_arg(args, void*);
351        this->arguments.push_back(expression);
352    }
353}
354
355void
356MethodCall::Write(FILE* to)
357{
358    if (this->obj != NULL) {
359        this->obj->Write(to);
360        fprintf(to, ".");
361    }
362    else if (this->clazz != NULL) {
363        fprintf(to, "%s.", this->clazz->QualifiedName().c_str());
364    }
365    fprintf(to, "%s(", this->name.c_str());
366    WriteArgumentList(to, this->arguments);
367    fprintf(to, ")");
368}
369
370Comparison::Comparison(Expression* l, const string& o, Expression* r)
371    :lvalue(l),
372     op(o),
373     rvalue(r)
374{
375}
376
377Comparison::~Comparison()
378{
379}
380
381void
382Comparison::Write(FILE* to)
383{
384    fprintf(to, "(");
385    this->lvalue->Write(to);
386    fprintf(to, "%s", this->op.c_str());
387    this->rvalue->Write(to);
388    fprintf(to, ")");
389}
390
391NewExpression::NewExpression(Type* t)
392    :type(t)
393{
394}
395
396NewExpression::NewExpression(Type* t, int argc = 0, ...)
397    :type(t)
398{
399  va_list args;
400  va_start(args, argc);
401  init(argc, args);
402  va_end(args);
403}
404
405NewExpression::~NewExpression()
406{
407}
408
409void
410NewExpression::init(int n, va_list args)
411{
412    for (int i=0; i<n; i++) {
413        Expression* expression = (Expression*)va_arg(args, void*);
414        this->arguments.push_back(expression);
415    }
416}
417
418void
419NewExpression::Write(FILE* to)
420{
421    fprintf(to, "new %s(", this->type->InstantiableName().c_str());
422    WriteArgumentList(to, this->arguments);
423    fprintf(to, ")");
424}
425
426NewArrayExpression::NewArrayExpression(Type* t, Expression* s)
427    :type(t),
428     size(s)
429{
430}
431
432NewArrayExpression::~NewArrayExpression()
433{
434}
435
436void
437NewArrayExpression::Write(FILE* to)
438{
439    fprintf(to, "new %s[", this->type->QualifiedName().c_str());
440    size->Write(to);
441    fprintf(to, "]");
442}
443
444Ternary::Ternary()
445    :condition(NULL),
446     ifpart(NULL),
447     elsepart(NULL)
448{
449}
450
451Ternary::Ternary(Expression* a, Expression* b, Expression* c)
452    :condition(a),
453     ifpart(b),
454     elsepart(c)
455{
456}
457
458Ternary::~Ternary()
459{
460}
461
462void
463Ternary::Write(FILE* to)
464{
465    fprintf(to, "((");
466    this->condition->Write(to);
467    fprintf(to, ")?(");
468    this->ifpart->Write(to);
469    fprintf(to, "):(");
470    this->elsepart->Write(to);
471    fprintf(to, "))");
472}
473
474Cast::Cast()
475    :type(NULL),
476     expression(NULL)
477{
478}
479
480Cast::Cast(Type* t, Expression* e)
481    :type(t),
482     expression(e)
483{
484}
485
486Cast::~Cast()
487{
488}
489
490void
491Cast::Write(FILE* to)
492{
493    fprintf(to, "((%s)", this->type->QualifiedName().c_str());
494    expression->Write(to);
495    fprintf(to, ")");
496}
497
498VariableDeclaration::VariableDeclaration(Variable* l, Expression* r, Type* c)
499    :lvalue(l),
500     cast(c),
501     rvalue(r)
502{
503}
504
505VariableDeclaration::VariableDeclaration(Variable* l)
506    :lvalue(l),
507     cast(NULL),
508     rvalue(NULL)
509{
510}
511
512VariableDeclaration::~VariableDeclaration()
513{
514}
515
516void
517VariableDeclaration::Write(FILE* to)
518{
519    this->lvalue->WriteDeclaration(to);
520    if (this->rvalue != NULL) {
521        fprintf(to, " = ");
522        if (this->cast != NULL) {
523            fprintf(to, "(%s)", this->cast->QualifiedName().c_str());
524        }
525        this->rvalue->Write(to);
526    }
527    fprintf(to, ";\n");
528}
529
530IfStatement::IfStatement()
531    :expression(NULL),
532     statements(new StatementBlock),
533     elseif(NULL)
534{
535}
536
537IfStatement::~IfStatement()
538{
539}
540
541void
542IfStatement::Write(FILE* to)
543{
544    if (this->expression != NULL) {
545        fprintf(to, "if (");
546        this->expression->Write(to);
547        fprintf(to, ") ");
548    }
549    this->statements->Write(to);
550    if (this->elseif != NULL) {
551        fprintf(to, "else ");
552        this->elseif->Write(to);
553    }
554}
555
556ReturnStatement::ReturnStatement(Expression* e)
557    :expression(e)
558{
559}
560
561ReturnStatement::~ReturnStatement()
562{
563}
564
565void
566ReturnStatement::Write(FILE* to)
567{
568    fprintf(to, "return ");
569    this->expression->Write(to);
570    fprintf(to, ";\n");
571}
572
573TryStatement::TryStatement()
574    :statements(new StatementBlock)
575{
576}
577
578TryStatement::~TryStatement()
579{
580}
581
582void
583TryStatement::Write(FILE* to)
584{
585    fprintf(to, "try ");
586    this->statements->Write(to);
587}
588
589CatchStatement::CatchStatement(Variable* e)
590    :statements(new StatementBlock),
591     exception(e)
592{
593}
594
595CatchStatement::~CatchStatement()
596{
597}
598
599void
600CatchStatement::Write(FILE* to)
601{
602    fprintf(to, "catch ");
603    if (this->exception != NULL) {
604        fprintf(to, "(");
605        this->exception->WriteDeclaration(to);
606        fprintf(to, ") ");
607    }
608    this->statements->Write(to);
609}
610
611FinallyStatement::FinallyStatement()
612    :statements(new StatementBlock)
613{
614}
615
616FinallyStatement::~FinallyStatement()
617{
618}
619
620void
621FinallyStatement::Write(FILE* to)
622{
623    fprintf(to, "finally ");
624    this->statements->Write(to);
625}
626
627Case::Case()
628    :statements(new StatementBlock)
629{
630}
631
632Case::Case(const string& c)
633    :statements(new StatementBlock)
634{
635    cases.push_back(c);
636}
637
638Case::~Case()
639{
640}
641
642void
643Case::Write(FILE* to)
644{
645    int N = this->cases.size();
646    if (N > 0) {
647        for (int i=0; i<N; i++) {
648            string s = this->cases[i];
649            if (s.length() != 0) {
650                fprintf(to, "case %s:\n", s.c_str());
651            } else {
652                fprintf(to, "default:\n");
653            }
654        }
655    } else {
656        fprintf(to, "default:\n");
657    }
658    statements->Write(to);
659}
660
661SwitchStatement::SwitchStatement(Expression* e)
662    :expression(e)
663{
664}
665
666SwitchStatement::~SwitchStatement()
667{
668}
669
670void
671SwitchStatement::Write(FILE* to)
672{
673    fprintf(to, "switch (");
674    this->expression->Write(to);
675    fprintf(to, ")\n{\n");
676    int N = this->cases.size();
677    for (int i=0; i<N; i++) {
678        this->cases[i]->Write(to);
679    }
680    fprintf(to, "}\n");
681}
682
683Break::Break()
684{
685}
686
687Break::~Break()
688{
689}
690
691void
692Break::Write(FILE* to)
693{
694    fprintf(to, "break;\n");
695}
696
697Method::Method()
698    :ClassElement(),
699     modifiers(0),
700     returnType(NULL), // (NULL means constructor)
701     returnTypeDimension(0),
702     statements(NULL)
703{
704}
705
706Method::~Method()
707{
708}
709
710void
711Method::GatherTypes(set<Type*>* types) const
712{
713    size_t N, i;
714
715    if (this->returnType) {
716        types->insert(this->returnType);
717    }
718
719    N = this->parameters.size();
720    for (i=0; i<N; i++) {
721        this->parameters[i]->GatherTypes(types);
722    }
723
724    N = this->exceptions.size();
725    for (i=0; i<N; i++) {
726        types->insert(this->exceptions[i]);
727    }
728}
729
730void
731Method::Write(FILE* to)
732{
733    size_t N, i;
734
735    if (this->comment.length() != 0) {
736        fprintf(to, "%s\n", this->comment.c_str());
737    }
738
739    WriteModifiers(to, this->modifiers, SCOPE_MASK | STATIC | ABSTRACT | FINAL | OVERRIDE);
740
741    if (this->returnType != NULL) {
742        string dim;
743        for (i=0; i<this->returnTypeDimension; i++) {
744            dim += "[]";
745        }
746        fprintf(to, "%s%s ", this->returnType->QualifiedName().c_str(),
747                dim.c_str());
748    }
749
750    fprintf(to, "%s(", this->name.c_str());
751
752    N = this->parameters.size();
753    for (i=0; i<N; i++) {
754        this->parameters[i]->WriteDeclaration(to);
755        if (i != N-1) {
756            fprintf(to, ", ");
757        }
758    }
759
760    fprintf(to, ")");
761
762    N = this->exceptions.size();
763    for (i=0; i<N; i++) {
764        if (i == 0) {
765            fprintf(to, " throws ");
766        } else {
767            fprintf(to, ", ");
768        }
769        fprintf(to, "%s", this->exceptions[i]->QualifiedName().c_str());
770    }
771
772    if (this->statements == NULL) {
773        fprintf(to, ";\n");
774    } else {
775        fprintf(to, "\n");
776        this->statements->Write(to);
777    }
778}
779
780Class::Class()
781    :modifiers(0),
782     what(CLASS),
783     type(NULL),
784     extends(NULL)
785{
786}
787
788Class::~Class()
789{
790}
791
792void
793Class::GatherTypes(set<Type*>* types) const
794{
795    int N, i;
796
797    types->insert(this->type);
798    if (this->extends != NULL) {
799        types->insert(this->extends);
800    }
801
802    N = this->interfaces.size();
803    for (i=0; i<N; i++) {
804        types->insert(this->interfaces[i]);
805    }
806
807    N = this->elements.size();
808    for (i=0; i<N; i++) {
809        this->elements[i]->GatherTypes(types);
810    }
811}
812
813void
814Class::Write(FILE* to)
815{
816    size_t N, i;
817
818    if (this->comment.length() != 0) {
819        fprintf(to, "%s\n", this->comment.c_str());
820    }
821
822    WriteModifiers(to, this->modifiers, ALL_MODIFIERS);
823
824    if (this->what == Class::CLASS) {
825        fprintf(to, "class ");
826    } else {
827        fprintf(to, "interface ");
828    }
829
830    string name = this->type->Name();
831    size_t pos = name.rfind('.');
832    if (pos != string::npos) {
833        name = name.c_str() + pos + 1;
834    }
835
836    fprintf(to, "%s", name.c_str());
837
838    if (this->extends != NULL) {
839        fprintf(to, " extends %s", this->extends->QualifiedName().c_str());
840    }
841
842    N = this->interfaces.size();
843    if (N != 0) {
844        if (this->what == Class::CLASS) {
845            fprintf(to, " implements");
846        } else {
847            fprintf(to, " extends");
848        }
849        for (i=0; i<N; i++) {
850            fprintf(to, " %s", this->interfaces[i]->QualifiedName().c_str());
851        }
852    }
853
854    fprintf(to, "\n");
855    fprintf(to, "{\n");
856
857    N = this->elements.size();
858    for (i=0; i<N; i++) {
859        this->elements[i]->Write(to);
860    }
861
862    fprintf(to, "}\n");
863
864}
865
866Document::Document()
867{
868}
869
870Document::~Document()
871{
872}
873
874static string
875escape_backslashes(const string& str)
876{
877    string result;
878    const size_t I=str.length();
879    for (size_t i=0; i<I; i++) {
880        char c = str[i];
881        if (c == '\\') {
882            result += "\\\\";
883        } else {
884            result += c;
885        }
886    }
887    return result;
888}
889
890void
891Document::Write(FILE* to)
892{
893    size_t N, i;
894
895    if (this->comment.length() != 0) {
896        fprintf(to, "%s\n", this->comment.c_str());
897    }
898    fprintf(to, "/*\n"
899                " * This file is auto-generated.  DO NOT MODIFY.\n"
900                " * Original file: %s\n"
901                " */\n", escape_backslashes(this->originalSrc).c_str());
902    if (this->package.length() != 0) {
903        fprintf(to, "package %s;\n", this->package.c_str());
904    }
905
906    N = this->classes.size();
907    for (i=0; i<N; i++) {
908        Class* c = this->classes[i];
909        c->Write(to);
910    }
911}
912
913