001: package gnu.expr;
002:
003: import gnu.bytecode.*;
004:
005: /** A Literal contains compile-time information about a constant. */
006:
007: public class Literal {
008: Literal next;
009:
010: public Field field;
011:
012: Object value;
013:
014: /* If field is non-null, it is the number of the Field.
015: * I.e. if the index is 10, the value of the Literal is the value of
016: * the static Field named Lit10. */
017: int index;
018:
019: public Type type;
020:
021: public int flags;
022:
023: /** Set at the beginning of the call to writeObject. */
024: static final int WRITING = 1;
025:
026: /** Set at the end of the call to writeObject. */
027: static final int WRITTEN = 2;
028:
029: static final int CYCLIC = 4;
030:
031: /** In pass 2, object has been at least allocated. */
032: static final int EMITTED = 8;
033:
034: /** Values produced by calling writeObject on value. */
035: Object[] argValues;
036: /** Types produced by calling writeObject on value. */
037: Type[] argTypes;
038:
039: public static final Literal nullLiteral = new Literal(null,
040: Type.nullType);
041:
042: public final Object getValue() {
043: return value;
044: }
045:
046: void assign(Compilation comp) {
047: assign((String) null, comp);
048: }
049:
050: /** Assign a static Field to hold the value of this Literal.
051: * This supports the same value being used multiple times or cyclically. */
052: void assign(String name, Compilation comp) {
053: int flags = comp.immediate ? Access.STATIC | Access.PUBLIC
054: : Access.STATIC | Access.FINAL;
055: if (name == null) {
056: index = comp.literalsCount++;
057: name = "Lit" + index;
058: } else
059: flags |= Access.PUBLIC;
060: assign(comp.curClass.addField(name, type, flags), comp);
061: }
062:
063: void assign(Field field, Compilation comp) {
064: next = comp.topLambda.literalsChain;
065: comp.topLambda.literalsChain = this ;
066: this .field = field;
067: }
068:
069: /** Create a new Literal, where comp must be in immediate mode. */
070: public Literal(Object value, Compilation comp) {
071: this (value, (String) null, comp);
072: }
073:
074: public Literal(Object value, String name, Compilation comp) {
075: this .value = value;
076: comp.literalTable.put(value, this );
077: this .type = Type.make(value.getClass());
078: assign(name, comp);
079: }
080:
081: /** Create a new Literal, for a value available from a static field.
082: * The field must be static and already exist. */
083: public Literal(Object value, Field field, Compilation comp) {
084: this .value = value;
085: comp.literalTable.put(value, this );
086: this .field = field;
087: this .type = field.getType();
088: flags = WRITTEN | EMITTED;
089: }
090:
091: public Literal(Object value, Type type, Compilation comp) {
092: this .value = value;
093: comp.literalTable.put(value, this );
094: this .type = type;
095: }
096:
097: Literal(Object value, Type type) {
098: this .value = value;
099: this .type = type;
100: }
101:
102: public static void emit(Compilation comp) {
103: if (!comp.immediate && comp.literalsChain != null
104: && comp.litTable == null) {
105: comp.litTable = new LitTable(comp);
106: try {
107: comp.litTable.emit();
108: } catch (Throwable ex) {
109: comp.error('e', "Literals: Internal error:" + ex);
110: ex.printStackTrace(System.err);
111: }
112: }
113: }
114: }
|