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