001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2005-2007 Robert Grimm
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * version 2 as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
017: * USA.
018: */
019: package xtc.type;
020:
021: import java.util.IdentityHashMap;
022: import java.util.Iterator;
023: import java.util.Map;
024:
025: import xtc.tree.Attribute;
026: import xtc.tree.Printer;
027: import xtc.tree.Visitor;
028:
029: /**
030: * A visitor to print types.
031: *
032: * @author Robert Grimm
033: * @version $Revision: 1.63 $
034: */
035: public class TypePrinter extends Visitor {
036:
037: /** The printer utility. */
038: protected final Printer printer;
039:
040: /** The set of visited, complex types. */
041: protected final Map<Object, Object> visited;
042:
043: /** The flag for instantiated types. */
044: protected boolean isInstantiated;
045:
046: /**
047: * Create a new type printer. Note that this constructor {@link
048: * xtc.tree.Utility#register registers} the new type printer with
049: * the specified printer.
050: *
051: * @param printer The printer utility.
052: */
053: public TypePrinter(Printer printer) {
054: this .printer = printer;
055: this .visited = new IdentityHashMap<Object, Object>();
056: isInstantiated = false;
057: printer.register(this );
058: }
059:
060: /** Reset this type printer. */
061: public void reset() {
062: visited.clear();
063: }
064:
065: // =========================================================================
066:
067: /**
068: * Print the specified type's annotations.
069: *
070: * @param t The type.
071: * @return <code>true</code> if anything was printed.
072: */
073: public boolean printAnnotations(Type t) {
074: boolean printed = false;
075:
076: if (t.hasLocation(false)) {
077: printer.p("line(").p(t.getLocation(false).line).p(") ");
078: printed = true;
079: }
080: if (t.hasLanguage(false)) {
081: printer.p("language(").p(t.getLanguage(false).toString())
082: .p(") ");
083: printed = true;
084: }
085: if (t.hasScope(false)) {
086: printer.p("scope(").p(t.getScope(false)).p(") ");
087: printed = true;
088: }
089: if (t.hasConstant(false)) {
090: printer.p("value(").p(
091: t.getConstant(false).getValue().toString()).p(") ");
092: printed = true;
093: }
094: if (t.hasShape(false)) {
095: printer.p("shape(").p(t.getShape().toString()).p(") ");
096: printed = true;
097: }
098: if (t.hasAttributes()) {
099: for (Attribute att : t.attributes()) {
100: printer.p(att).p(' ');
101: printed = true;
102: }
103: }
104:
105: return printed;
106: }
107:
108: // =========================================================================
109:
110: /** Print the specified boolean type. */
111: public void visit(BooleanT t) {
112: printAnnotations(t);
113: printer.p("boolean");
114: }
115:
116: /** Print the specified error type. */
117: public void visit(ErrorT t) {
118: printAnnotations(t);
119: printer.p("** error **");
120: }
121:
122: /** Print the specified internal type. */
123: public void visit(InternalT t) {
124: printAnnotations(t);
125: printer.p(t.getName());
126: }
127:
128: /** Print the specified label type. */
129: public void visit(LabelT t) {
130: printAnnotations(t);
131: printer.p("label(").p(t.getName()).p(')');
132: }
133:
134: /** Print the specified number type. */
135: public void visit(NumberT t) {
136: printAnnotations(t);
137: printer.p(t.toString());
138: }
139:
140: /** Print the specified package type. */
141: public void visit(PackageT t) {
142: printAnnotations(t);
143: printer.p("package(").p(t.getName()).p(')');
144: }
145:
146: /** Print the specified type parameter. */
147: public void visit(Parameter t) {
148: printAnnotations(t);
149: printer.p('<').p(t.getName()).p('>');
150: }
151:
152: /** Print the specified unit type. */
153: public void visit(UnitT t) {
154: printAnnotations(t);
155: printer.p(t.getName());
156: }
157:
158: /** Print the specified void type. */
159: public void visit(VoidT t) {
160: printAnnotations(t);
161: printer.p("void");
162: }
163:
164: // =========================================================================
165:
166: /** Print the specified array type. */
167: public void visit(ArrayT t) {
168: printAnnotations(t);
169: printer.p("array(").p(t.getType());
170: if (t.isVarLength()) {
171: printer.p(", *");
172: } else if (t.hasLength()) {
173: printer.p(", ").p(t.getLength());
174: }
175: printer.p(')');
176: }
177:
178: /**
179: * Print the interfaces, fields, and methods of the specified class
180: * or interface type.
181: *
182: * @param t The class or interface type.
183: */
184: public void printBody(ClassOrInterfaceT t) {
185: if (!t.getInterfaces().isEmpty()) {
186: for (Iterator<Type> iter = t.getInterfaces().iterator(); iter
187: .hasNext();) {
188: Type type = iter.next();
189: if (type.isAlias()
190: && (null == type.toAlias().getType())) {
191: printer.p(type);
192: } else {
193: printer.p(((InterfaceT) type.resolve()).getQName());
194: }
195: if (iter.hasNext()) {
196: printer.p(", ");
197: }
198: }
199: }
200:
201: if (visited.containsKey(t))
202: return;
203: visited.put(t, Boolean.TRUE);
204:
205: if (t.getFields().isEmpty() && t.getMethods().isEmpty()) {
206: printer.p(" {}");
207: } else {
208: printer.pln(" {").incr();
209: for (Type field : t.getFields()) {
210: printer.indent().p(field).pln(';');
211: }
212: for (Type method : t.getMethods()) {
213: printer.indent().p(method).pln(';');
214: }
215: printer.decr().indent().p('}');
216: }
217: }
218:
219: /** Print the specified class type. */
220: public void visit(ClassT t) {
221: printer.p("class ").p(t.getQName());
222: if (null != t.getParent()) {
223: Type type = t.getParent();
224: printer.p(" extends ");
225: if (type.isAlias() && (null == type.toAlias().getType())) {
226: printer.p(type);
227: } else {
228: printer.p(((ClassT) type.resolve()).getQName());
229: }
230: }
231: if (!t.getInterfaces().isEmpty()) {
232: printer.p(" implements ");
233: }
234: printBody(t);
235: }
236:
237: /** Print the specified interface type. */
238: public void visit(InterfaceT t) {
239: printer.p("interface ").p(t.getQName());
240: if (!t.getInterfaces().isEmpty()) {
241: printer.p(" extends ");
242: }
243: printBody(t);
244: }
245:
246: /**
247: * Print the specified function or method type's signature.
248: *
249: * @param t The function or method type.
250: */
251: public void printSignature(FunctionOrMethodT t) {
252: printer.p('(');
253: for (Iterator<Type> iter = t.getParameters().iterator(); iter
254: .hasNext();) {
255: printer.p(iter.next());
256: if (iter.hasNext() || t.isVarArgs()) {
257: printer.p(", ");
258: }
259: }
260: if (t.isVarArgs()) {
261: printer.p("...");
262: }
263: printer.p(") -> ");
264: if (t.getResult().resolve().isFunction()) {
265: printer.p('(').p(t.getResult()).p(')');
266: } else {
267: printer.p(t.getResult());
268: }
269: if ((null != t.getExceptions())
270: && (!t.getExceptions().isEmpty())) {
271: printer.p(" throws ");
272: for (Iterator<Type> iter = t.getExceptions().iterator(); iter
273: .hasNext();) {
274: printer.p(iter.next());
275: if (iter.hasNext())
276: printer.p(", ");
277: }
278: }
279: }
280:
281: /** Print the specified function type. */
282: public void visit(FunctionT t) {
283: printAnnotations(t);
284: printSignature(t);
285: }
286:
287: /** Print the specified method type. */
288: public void visit(MethodT t) {
289: printAnnotations(t);
290: printer.p(t.getName()).p(' ');
291: printSignature(t);
292: }
293:
294: /** Print the specified pointer type. */
295: public void visit(PointerT t) {
296: printAnnotations(t);
297: printer.p("pointer(").p(t.getType()).p(')');
298: }
299:
300: /**
301: * Print the specified tagged type.
302: *
303: * @param kind The kind.
304: * @param tag The tagged type.
305: */
306: public void printTagged(String kind, Tagged tag) {
307: printer.p(kind).p(' ').p(tag.getName());
308: if ((null != tag.getMembers()) && (!visited.containsKey(tag))) {
309: visited.put(tag, Boolean.TRUE);
310:
311: if (tag.getMembers().isEmpty()) {
312: printer.p(" {}");
313: } else {
314: printer.pln(" {").incr();
315: for (Iterator<?> iter = tag.getMembers().iterator(); iter
316: .hasNext();) {
317: printer.indent().p((Type) iter.next());
318: if ("enum".equals(kind)) {
319: if (iter.hasNext()) {
320: printer.pln(',');
321: } else {
322: printer.pln();
323: }
324: } else {
325: printer.pln(';');
326: }
327: }
328: printer.decr().indent().p('}');
329: }
330: }
331: }
332:
333: /** Print the specified struct type. */
334: public void visit(StructT t) {
335: printAnnotations(t);
336: printTagged("struct", t);
337: }
338:
339: /** Print the specified union type. */
340: public void visit(UnionT t) {
341: printAnnotations(t);
342: printTagged("union", t);
343: }
344:
345: /** Print the specified tuple type. */
346: public void visit(TupleT t) {
347: printAnnotations(t);
348: if (null == t.getName()) {
349: printer.p("<anon>");
350: } else {
351: printer.p(t.getName());
352: }
353: printer.p('(');
354: if (null == t.getTypes()) {
355: printer.p("...");
356: } else {
357: for (Iterator<Type> iter = t.getTypes().iterator(); iter
358: .hasNext();) {
359: printer.p(iter.next());
360: if (iter.hasNext())
361: printer.p(", ");
362: }
363: }
364: printer.p(')');
365: }
366:
367: /** Print the specified variant typee. */
368: public void visit(VariantT t) {
369: printAnnotations(t);
370: if (t.isPolymorphic())
371: printer.p("polymorphic-");
372: printer.p("variant ");
373: if (null == t.getName()) {
374: printer.p("<anonymous>");
375: } else {
376: printer.p(t.getName());
377: }
378:
379: if (visited.containsKey(t))
380: return;
381: visited.put(t, Boolean.TRUE);
382:
383: if (null == t.getTuples()) {
384: printer.p(" { ... }");
385: } else {
386: printer.pln(" {").incr();
387: for (Type var : t.getTuples()) {
388: printer.indent().p(var).pln(';');
389: }
390: printer.decr().indent().p('}');
391: }
392: }
393:
394: // =========================================================================
395:
396: /** Print the specified type alias. */
397: public void visit(AliasT t) {
398: printAnnotations(t);
399: printer.p("alias(").p(t.getName());
400: if (null != t.getType()) {
401: printer.p(", ").p(t.getType());
402: }
403: printer.p(')');
404: }
405:
406: /** Print the specified annotated type. */
407: public void visit(AnnotatedT t) {
408: printAnnotations(t);
409: printer.p(t.getType());
410: }
411:
412: /** Print the specified enumerator. */
413: public void visit(EnumeratorT t) {
414: printAnnotations(t); // Prints value.
415: printer.p("enumerator(").p(t.getType()).p(' ').p(t.getName())
416: .p(')');
417: }
418:
419: /** Print the specified enum type. */
420: public void visit(EnumT t) {
421: printAnnotations(t);
422: printTagged("enum", t);
423: }
424:
425: /** Print the specified instantiated type. */
426: public void visit(InstantiatedT t) {
427: printAnnotations(t);
428:
429: // Get the wrapped parameterized type.
430: Iterator<Parameter> params = t.toParameterized()
431: .getParameters().iterator();
432: Iterator<Type> args = t.getArguments().iterator();
433:
434: printer.p('<');
435: while (params.hasNext()) {
436: printer.p(params.next()).p(" = ").p(args.next());
437: if (params.hasNext())
438: printer.p(", ");
439: }
440: printer.p('>');
441:
442: isInstantiated = true;
443: printer.p(t.getType());
444: }
445:
446: /** Print the specified parameterized type. */
447: public void visit(ParameterizedT t) {
448: printAnnotations(t);
449: if (isInstantiated) {
450: isInstantiated = false;
451: } else {
452: printer.p('<');
453: for (Iterator<Parameter> iter = t.getParameters()
454: .iterator(); iter.hasNext();) {
455: printer.p(iter.next());
456: if (iter.hasNext())
457: printer.p(", ");
458: }
459: printer.p("> ");
460: }
461: printer.p(t.getType());
462: }
463:
464: /** Print the specified variable type. */
465: public void visit(VariableT t) {
466: printAnnotations(t);
467: switch (t.getKind()) {
468: case GLOBAL:
469: printer.p("global");
470: break;
471: case LOCAL:
472: printer.p("local");
473: break;
474: case PARAMETER:
475: printer.p("param");
476: break;
477: case FIELD:
478: printer.p("field");
479: break;
480: case BITFIELD:
481: printer.p("bitfield");
482: break;
483: }
484: printer.p('(').p(t.getType()).p(", ");
485: if (t.hasName()) {
486: printer.p(t.getName());
487: } else {
488: printer.p("<anon>");
489: }
490: if (t.hasWidth()) {
491: printer.p(", ").p(t.getWidth());
492: }
493: printer.p(')');
494: }
495:
496: }
|