View Javadoc
1   package net.sourceforge.jenesis4java.impl;
2   
3   /*
4    * #%L
5    * Jenesis 4 Java Code Generator
6    * %%
7    * Copyright (C) 2000 - 2015 jenesis4java
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * #L%
23   */
24  
25  /**
26   * Copyright (C) 2008, 2010 Richard van Nieuwenhoven - ritchie [at] gmx [dot] at
27   * Copyright (C) 2000, 2001 Paul Cody Johnston - pcj@inxar.org <br>
28   * This file is part of Jenesis4java. Jenesis4java is free software: you can
29   * redistribute it and/or modify it under the terms of the GNU Lesser General
30   * Public License as published by the Free Software Foundation, either version 3
31   * of the License, or (at your option) any later version.<br>
32   * Jenesis4java is distributed in the hope that it will be useful, but WITHOUT
33   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
35   * details.<br>
36   * You should have received a copy of the GNU Lesser General Public License
37   * along with Jenesis4java. If not, see <http://www.gnu.org/licenses/>.
38   */
39  import java.io.BufferedInputStream;
40  import java.io.FileInputStream;
41  import java.io.IOException;
42  import java.io.PrintWriter;
43  import java.io.StringWriter;
44  import java.util.*;
45  
46  import net.sourceforge.jenesis4java.*;
47  import net.sourceforge.jenesis4java.impl.util.BlockStyle;
48  import net.sourceforge.jenesis4java.impl.util.MemberComparator;
49  import net.sourceforge.jenesis4java.impl.util.VisitorUtils;
50  
51  /**
52   * Standard {@code VirtualMachine} implementation.
53   */
54  public class MVM extends net.sourceforge.jenesis4java.VirtualMachine {
55  
56      /**
57       * CODEABLE SUPERPARENT
58       */
59      abstract static class MCodeable implements Codeable {
60  
61          Comment comment;
62  
63          MVM vm;
64  
65          MCodeable(MVM vm) {
66              this.vm = vm;
67          }
68  
69          @Override
70          public <T> T cast(Class<T> clazz) {
71              return clazz.cast(this);
72          }
73  
74          @Override
75          public Comment getComment() {
76              return comment;
77          }
78  
79          @Override
80          public boolean isBlockWithAbruptCompletion() {
81              return false;
82          }
83  
84          private Set<Style> activeStyles = EnumSet.noneOf(Style.class);
85  
86          @Override
87          public MCodeable setComment(int type, String text) {
88              switch (type) {
89                  case Comment.SINGLE_LINE:
90                      comment = new MComment.MSingleLineComment(vm, text);
91                      break;
92                  case Comment.MULTI_LINE:
93                      comment = new MComment.MMultipleLineComment(vm, text);
94                      break;
95                  case Comment.BLOCK_WITHOUT_INTERMEDIARY_STARS:
96                      comment = new MComment.MMultipleLineComment(vm, text, true);
97                      break;
98                  case Comment.DOCUMENTATION:
99                      comment = new MComment.MDocumentationComment(vm, text);
100                     break;
101                 case Comment.TRAILING:
102                     comment = new MComment.MSingleLineComment(vm, text, true);
103                     break;
104                 default:
105                     String message = type + " is no valid comment type. " //
106                             + "Use a constant in Comment.";
107                     throw new IllegalArgumentException(message);
108             }
109             return this;
110         }
111 
112         @Override
113         public CodeWriter toCode(CodeWriter out) {
114             if (comment != null) {
115                 out.write(comment);
116             }
117             return out;
118         }
119 
120         @Override
121         public String toString() {
122             StringWriter sout = new StringWriter();
123             PrintWriter pout = new PrintWriter(sout);
124             CodeWriter cout = new MCodeWriter(pout);
125             toCode(cout);
126             return sout.toString();
127         }
128 
129         @Override
130         public void visit(ReplacingVisitor visitor) {
131             comment = VisitorUtils.visit(comment, this, visitor);
132         }
133 
134         @Override
135         public VirtualMachine vm() {
136             return vm;
137         }
138 
139         @Override
140         public Codeable applyStyle(Style style) {
141             activeStyles.add(style);
142             return this;
143         }
144 
145         @Override
146         public boolean isActive(Style style) {
147             return activeStyles.contains(style);
148         }
149     }
150 
151     PrimitiveType VOID;
152 
153     PrimitiveType NULL;
154 
155     PrimitiveType BOOLEAN;
156 
157     PrimitiveType BYTE;
158 
159     PrimitiveType SHORT;
160 
161     PrimitiveType INT;
162 
163     PrimitiveType CHAR;
164 
165     PrimitiveType LONG;
166 
167     PrimitiveType FLOAT;
168 
169     PrimitiveType DOUBLE;
170 
171     ClassType STRING;
172 
173     ClassType BIGDECIMAL_TYPE;
174 
175     ClassType BOOLEAN_TYPE;
176 
177     ClassType CALENDAR_TYPE;
178 
179     ClassType INTEGER_TYPE;
180 
181     ClassType LONG_TYPE;
182 
183     ClassType STRING_TYPE;
184 
185     Null _NULL;
186 
187     True TRUE;
188 
189     False FALSE;
190 
191     MStyle.MStyleMap styles;
192 
193     // Note: accesses to units list are synchronized to provide a minimum of
194     // thread safety
195     final ArrayList<CompilationUnit> units = new ArrayList<>();
196 
197     CompilationUnitEncoder encoder;
198 
199     public MVM(java.util.Properties styleprops) {
200         initTypes();
201         styles = new MStyle.MStyleMap(styleprops);
202         try {
203             encoder = (CompilationUnitEncoder) Class.forName(styleprops.getProperty("encoder", BasicCompilationUnitEncoder.class.getName())).newInstance();
204         } catch (Exception e) {
205             throw new RuntimeException("encoder class not found!", e);
206         }
207     }
208 
209     public MVM(String styleprops) throws IOException {
210         this(readProperties(styleprops));
211     }
212 
213     private static Properties readProperties(String properties) throws IOException {
214         Properties p;
215         try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(properties))) {
216             // fill the props
217             p = new Properties();
218             p.load(in);
219         }
220         return p;
221     }
222 
223     @Override
224     public synchronized VirtualMachine clear() {
225         units.clear();
226         return this;
227     }
228 
229     @Override
230     public MVM encode() {
231         for (CompilationUnit c : cloneUnits()) {
232             c.encode();
233         }
234         return this;
235     }
236 
237     @SuppressWarnings("unchecked")
238     private synchronized List<CompilationUnit> cloneUnits() {
239         return (List<CompilationUnit>) units.clone();
240     }
241 
242     @Override
243     public CompilationUnitEncoder getEncoder() {
244         return encoder;
245     }
246 
247     @Override
248     public FieldAccess newAccess(Class<?> qualifierClass, Object object) {
249         return newAccess(qualifierClass.getSimpleName(), object.toString());
250     }
251 
252     @Override
253     public FieldAccess newAccess(Expression qual, String name) {
254         return new MExpression.MFieldAccess(this, qual, name);
255     }
256 
257     @Override
258     public FieldAccess newAccess(String name) {
259         return new MExpression.MFieldAccess(this, (String) null, name);
260     }
261 
262     @Override
263     public FieldAccess newAccess(String qual, String name) {
264         return new MExpression.MFieldAccess(this, qual, name);
265     }
266 
267     @Override
268     public Annotation newAnnotation(Class<?> annotationClass) {
269         return newAnnotation(annotationClass.getSimpleName());
270     }
271 
272     @Override
273     public Annotation newAnnotation(String text) {
274         return new MAnnotation(this, text);
275     }
276 
277     @Override
278     public AnnotationAttribute newAnnotationAttribute(String key, Expression value, Expression... additionalValues) {
279         MAnnotation.MAnnotationAttribute attribute = new MAnnotation.MAnnotationAttribute(this);
280         attribute.setName(key);
281         attribute.addValue(value);
282         for (Expression val : additionalValues) {
283             attribute.addValue(val);
284         }
285         return attribute;
286     }
287 
288     @Override
289     public NewAnonymousClass newAnon(Type type, Comparator comparator) {
290         return new MExpression.MNewAnonymousClass(this, type, comparator);
291     }
292 
293     @Override
294     public NewAnonymousClass newAnon(Type type) {
295         return newAnon(type, new MemberComparator());
296     }
297 
298     @Override
299     public NewAnonymousClass newAnonymousClass(String className, Comparator comparator, String... genericTypes) {
300         return newAnon(newType(className + createTypeParameters(genericTypes)), comparator);
301     }
302 
303     @Override
304     public NewAnonymousClass newAnonymousClass(String className, String... genericTypes) {
305         return newAnon(newType(className + createTypeParameters(genericTypes)));
306     }
307 
308     @Override
309     public ArrayType newArray(int type, int name) {
310         return new MType.MArrayType(this, newType(type), name);
311     }
312 
313     @Override
314     public ArrayType newArray(String type, int dims) {
315         return new MType.MArrayType(this, newType(type), dims);
316     }
317 
318     @Override
319     public NewArray newArray(Type type) {
320         return new MExpression.MNewArray(this, type);
321     }
322 
323     public ArrayType newArray(Type type, int dims) {
324         return new MType.MArrayType(this, type, dims);
325     }
326 
327     @Override
328     public ArrayAccess newArrayAccess(Expression qual, String name) {
329         return new MExpression.MArrayAccess(this, qual, name);
330     }
331 
332     @Override
333     public ArrayAccess newArrayAccess(String name) {
334         return new MExpression.MArrayAccess(this, (String) null, name);
335     }
336 
337     @Override
338     public ArrayAccess newArrayAccess(String qual, String name) {
339         return new MExpression.MArrayAccess(this, qual, name);
340     }
341 
342     @Override
343     public ArrayInitializer newArrayInit(Expression[] expressions) {
344         return new MExpression.MArrayInitializer(this, expressions);
345     }
346 
347     @Override
348     public ArrayInitializer newArrayInit(Object o) {
349         return new MExpression.MArrayInitializer(this, o);
350     }
351 
352     @Override
353     public Assign newAssign(int type, Variable l, Expression r) {
354         return new MExpression.MAssign(this, type, l, r);
355     }
356 
357     @Override
358     public Assign newAssign(Variable l, Expression r) {
359         return new MExpression.MAssign(this, Assign.S, l, r);
360     }
361 
362     @Override
363     public Binary newBinary(int type, Expression l, Expression r) {
364         return new MExpression.MBinary(this, type, l, r);
365     }
366 
367     @Override
368     public Blank newBlank() {
369         return new MExpression.MBlank(this);
370     }
371 
372     @Override
373     public BooleanLiteral newBoolean(boolean value) {
374         return value ? newTrue() : newFalse();
375     }
376 
377     @Override
378     public Cast newBrackets(Expression expression) {
379         return newCast(null, expression);
380     }
381 
382     @Override
383     public ByteLiteral newByte(byte val) {
384         return new MLiteral.MByteLiteral(this, val);
385     }
386 
387     @Override
388     public CalendarClassType newCalendarType(String pattern) {
389         return new MType.MCalendarClassType(this, pattern);
390     }
391 
392     @Override
393     public Cast newCast(Type type, Expression val) {
394         return new MExpression.MCast(this, type, val);
395     }
396 
397     @Override
398     public CharLiteral newChar(char val) {
399         return new MLiteral.MCharLiteral(this, val);
400     }
401 
402     @Override
403     public NewClass newClass(Type type) {
404         return new MExpression.MNewClass(this, type);
405     }
406 
407     @Override
408     public ClassLiteral newClassLiteral(ClassType val) {
409         return new MLiteral.MClassLiteral(this, val);
410     }
411 
412     @Override
413     public ClassLiteral newClassLiteral(String val) {
414         return new MLiteral.MClassLiteral(this, newType(val));
415     }
416 
417     @Override
418     public synchronized CompilationUnit newCompilationUnit(String path) {
419         CompilationUnit x = new MDeclaration.MCompilationUnit(this, path);
420         units.add(x);
421         return x;
422     }
423 
424     @Override
425     public CompilationUnit newCompilationUnit(String sourceDirectory, String packageName) {
426         CompilationUnit unit = newCompilationUnit(sourceDirectory);
427         unit.setNamespace(packageName);
428         return unit;
429     }
430 
431     @Override
432     public DoubleLiteral newDouble(double val) {
433         return new MLiteral.MDoubleLiteral(this, val);
434     }
435 
436     @Override
437     public False newFalse() {
438         return FALSE;
439     }
440 
441     @Override
442     public FloatLiteral newFloat(float val) {
443         return new MLiteral.MFloatLiteral(this, val);
444     }
445 
446     @Override
447     public Freeform newFree(String code) {
448         return new MExpression.MFreeform(this, code);
449     }
450 
451     @Override
452     public IntLiteral newInt(int val) {
453         return new MLiteral.MIntLiteral(this, val);
454     }
455 
456     @Override
457     public Invoke newInvoke(Class<?> qualifyingClass, String name) {
458         return newInvoke(qualifyingClass.getSimpleName(), name);
459     }
460 
461     @Override
462     public Invoke newInvoke(Expression qual, String name) {
463         return new MExpression.MInvoke(this, qual, name);
464     }
465 
466     @Override
467     public Invoke newInvoke(String name) {
468         return newInvoke((String) null, name);
469     }
470 
471     @Override
472     public Invoke newInvoke(String qual, String name) {
473         return new MExpression.MInvoke(this, qual, name);
474     }
475 
476     @Override
477     public LongLiteral newLong(long val) {
478         return new MLiteral.MLongLiteral(this, val);
479     }
480 
481     @Override
482     public Null newNull() {
483         return _NULL;
484     }
485 
486     @Override
487     public OctalLiteral newOctal(char val) {
488         return new MLiteral.MOctalLiteral(this, val);
489     }
490 
491     @Override
492     public ScientificLiteral newScientific(int precision, int scale, int exponent) {
493         return new MLiteral.MScientificLiteral(this, precision, scale, exponent);
494     }
495 
496     @Override
497     public ShortLiteral newShort(short val) {
498         return new MLiteral.MShortLiteral(this, val);
499     }
500 
501     @Override
502     public ClassType newSimpleType(Class<?> type) {
503         return newType(type.getSimpleName());
504     }
505 
506     @Override
507     public StringLiteral newString(String val) {
508         return new MLiteral.MStringLiteral(this, val);
509     }
510 
511     @Override
512     public Ternary newTernary(int type, Expression one, Expression two, Expression three) {
513         return new MExpression.MTernary(this, type, one, two, three);
514     }
515 
516     @Override
517     public True newTrue() {
518         return TRUE;
519     }
520 
521     @Override
522     public ClassType newType(Class<?> clazz) {
523         return newType(clazz.getName());
524     }
525 
526     @Override
527     public PrimitiveType newType(int type) {
528         switch (type) {
529             case Type.VOID:
530                 return VOID;
531             case Type.NULL:
532                 return NULL;
533             case Type.BOOLEAN:
534                 return BOOLEAN;
535             case Type.BYTE:
536                 return BYTE;
537             case Type.SHORT:
538                 return SHORT;
539             case Type.INT:
540                 return INT;
541             case Type.LONG:
542                 return LONG;
543             case Type.FLOAT:
544                 return FLOAT;
545             case Type.DOUBLE:
546                 return DOUBLE;
547             case Type.CHAR:
548                 return CHAR;
549 
550             case Type.ARRAY:
551                 throw new IllegalArgumentException("Cannot create array Type with this method.");
552             case Type.CLASS:
553                 throw new IllegalArgumentException("Cannot create class Type with this method.");
554             default:
555                 String message = "Illegal type constant " + type + ". Use constants defined in Type.";
556                 throw new IllegalArgumentException(message);
557         }
558     }
559 
560     @Override
561     public ClassType newType(String name) {
562         return new MType.MClassType(this, name);
563     }
564 
565     @Override
566     public Unary newUnary(int type, Expression val) {
567         return new MExpression.MUnary(this, type, val);
568     }
569 
570     @Override
571     public UnicodeLiteral newUnicode(char val) {
572         return new MLiteral.MUnicodeLiteral(this, val);
573     }
574 
575     @Override
576     public Variable newVar(String name) {
577         return new MExpression.MVariable(this, name);
578     }
579 
580     @Override
581     public Variable newVar(Type type) {
582         return new MExpression.MTypeVariable(this, type);
583     }
584 
585     @Override
586     public Type type_boolean() {
587         return BOOLEAN;
588     }
589 
590     @Override
591     public Type type_byte() {
592         return BYTE;
593     }
594 
595     @Override
596     public Type type_char() {
597         return CHAR;
598     }
599 
600     @Override
601     public Type type_double() {
602         return DOUBLE;
603     }
604 
605     @Override
606     public Type type_float() {
607         return FLOAT;
608     }
609 
610     @Override
611     public Type type_int() {
612         return INT;
613     }
614 
615     @Override
616     public Type type_long() {
617         return LONG;
618     }
619 
620     @Override
621     public Type type_short() {
622         return SHORT;
623     }
624 
625     @Override
626     public Type type_void() {
627         return VOID;
628     }
629 
630     @Override
631     public ClassType typeBigDecimal() {
632         return BIGDECIMAL_TYPE;
633     }
634 
635     @Override
636     public ClassType typeBoolean() {
637         return BOOLEAN_TYPE;
638     }
639 
640     @Override
641     public ClassType typeCalendar() {
642         return CALENDAR_TYPE;
643     }
644 
645     @Override
646     public ClassType typeInteger() {
647         return INTEGER_TYPE;
648     }
649 
650     @Override
651     public ClassType typeLong() {
652         return LONG_TYPE;
653     }
654 
655     @Override
656     public ClassType typeString() {
657         return STRING_TYPE;
658     }
659 
660     @Override
661     public Super newSuper() {
662         return new MExpression.MSuper(this);
663     }
664 
665     @Override
666     public This newThis() {
667         return new MExpression.MThis(this);
668     }
669 
670     @Override
671     public This newThis(ClassType typeOfOuterClass) {
672         return new MExpression.MThis(this, typeOfOuterClass);
673     }
674 
675     private String createTypeParameters(String[] genericTypes) {
676         if (genericTypes == null || genericTypes.length == 0) {
677             return "";
678         }
679         StringBuilder builder = new StringBuilder("<");
680         boolean first = true;
681         for (String type : genericTypes) {
682             if (!first) {
683                 builder.append(", ");
684             } else {
685                 first = false;
686             }
687             builder.append(type);
688         }
689         return builder.append(">").toString();
690     }
691 
692     BlockStyle getStyle(String name) {
693         return styles.get(name);
694     }
695 
696     private void initTypes() {
697         VOID = new MType.MPrimitiveType(this, Type.VOID, "void");
698         NULL = new MType.MPrimitiveType(this, Type.NULL, "null");
699         BOOLEAN = new MType.MPrimitiveType(this, Type.BOOLEAN, "boolean");
700         BYTE = new MType.MPrimitiveType(this, Type.BYTE, "byte");
701         SHORT = new MType.MPrimitiveType(this, Type.SHORT, "short");
702         INT = new MType.MPrimitiveType(this, Type.INT, "int");
703         CHAR = new MType.MPrimitiveType(this, Type.CHAR, "char");
704         LONG = new MType.MPrimitiveType(this, Type.LONG, "long");
705         FLOAT = new MType.MPrimitiveType(this, Type.FLOAT, "float");
706         DOUBLE = new MType.MPrimitiveType(this, Type.DOUBLE, "double");
707         STRING = new MType.MClassType(this, "String");
708         _NULL = new MLiteral.MNull(this);
709         TRUE = new MLiteral.MTrue(this);
710         FALSE = new MLiteral.MFalse(this);
711 
712         BIGDECIMAL_TYPE = new MType.MClassType(this, java.math.BigDecimal.class.getName());
713         BOOLEAN_TYPE = new MType.MClassType(this, Boolean.class.getName());
714         CALENDAR_TYPE = new MType.MClassType(this, java.util.Calendar.class.getName());
715         INTEGER_TYPE = new MType.MClassType(this, Integer.class.getName());
716         LONG_TYPE = new MType.MClassType(this, Long.class.getName());
717         STRING_TYPE = new MType.MClassType(this, String.class.getName());
718     }
719 }