001: package gnu.expr;
002:
003: import gnu.mapping.*;
004: import gnu.bytecode.Type;
005:
006: /**
007: * An Expression that evaluates to a constant value.
008: * @author Per Bothner
009: */
010:
011: public class QuoteExp extends Expression {
012: Object value;
013:
014: public final Object getValue() {
015: return value;
016: }
017:
018: public final Object valueIfConstant() {
019: return value;
020: }
021:
022: protected Type type;
023:
024: public final gnu.bytecode.Type getType() {
025: if (type != null)
026: return type;
027: if (value == Values.empty)
028: return Type.void_type;
029: else if (value == null)
030: return Type.nullType;
031: else if (this == undefined_exp)
032: return Type.pointer_type;
033: else
034: return Type.make(value.getClass());
035: }
036:
037: static public QuoteExp undefined_exp = new QuoteExp(
038: Special.undefined);
039: static public QuoteExp voidExp = new QuoteExp(Values.empty,
040: Type.void_type);
041: static public QuoteExp trueExp = new QuoteExp(Boolean.TRUE);
042: static public QuoteExp falseExp = new QuoteExp(Boolean.FALSE);
043: static public QuoteExp nullExp = new QuoteExp(null, Type.nullType);
044:
045: public static QuoteExp getInstance(Object value) {
046: if (value == null)
047: return nullExp;
048: if (value == Special.undefined)
049: return undefined_exp;
050: if (value == Values.empty)
051: return voidExp;
052: if (value instanceof Boolean)
053: return ((Boolean) value).booleanValue() ? trueExp
054: : falseExp;
055: return new QuoteExp(value);
056: }
057:
058: public QuoteExp(Object val) {
059: value = val;
060: }
061:
062: public QuoteExp(Object val, Type type) {
063: value = val;
064: this .type = type;
065: }
066:
067: protected boolean mustCompile() {
068: return false;
069: }
070:
071: public void apply(CallContext ctx) {
072: ctx.writeValue(value);
073: }
074:
075: public void compile(Compilation comp, Target target) {
076: if (type == null
077: || type == Type.pointer_type
078: || target instanceof IgnoreTarget
079: || (type instanceof gnu.bytecode.ObjectType && type
080: .isInstance(value)))
081: comp.compileConstant(value, target);
082: else {
083: comp.compileConstant(value, StackTarget.getInstance(type));
084: target.compileFromStack(comp, type);
085: }
086: }
087:
088: protected Expression walk(ExpWalker walker) {
089: return walker.walkQuoteExp(this );
090: }
091:
092: public Expression inline(ApplyExp exp, InlineCalls walker,
093: Declaration decl) {
094: if (this == QuoteExp.undefined_exp)
095: return exp;
096: Object fval = getValue();
097: if (!(fval instanceof Procedure))
098: return walker
099: .noteError(decl == null || fval == null ? "called value is not a procedure"
100: : ("calling " + decl.getName()
101: + " which is a " + fval.getClass()
102: .getName()));
103: Procedure proc = (Procedure) fval;
104: int nargs = exp.getArgCount();
105: String msg = WrongArguments.checkArgCount(proc, nargs);
106: if (msg != null)
107: return walker.noteError(msg);
108: if (proc instanceof CanInline)
109: return ((CanInline) proc).inline(exp, walker);
110: if (exp.getFlag(ApplyExp.INLINE_IF_CONSTANT)) {
111: Expression e = exp.inlineIfConstant(proc, walker);
112: if (e != exp)
113: return walker.walk(e);
114: }
115: Compilation comp = walker.getCompilation();
116: if (comp.inlineOk(proc)) {
117: if (proc instanceof Inlineable) {
118: if (exp.getFunction() == this )
119: return exp;
120: return new ApplyExp(this , exp.getArgs()).setLine(exp);
121: }
122: PrimProcedure mproc = PrimProcedure.getMethodFor(proc,
123: decl, exp.args, comp.getLanguage());
124: if (mproc != null) {
125: ApplyExp nexp;
126: if (mproc.getStaticFlag() || decl == null)
127: nexp = new ApplyExp(mproc, exp.args);
128: else if (decl.base == null)
129: return exp;
130: else {
131: Expression[] margs = new Expression[1 + nargs];
132: System.arraycopy(exp.getArgs(), 0, margs, 1, nargs);
133: margs[0] = new ReferenceExp(decl.base);
134: nexp = new ApplyExp(mproc, margs);
135: }
136: return nexp.setLine(exp);
137: }
138: }
139: return exp;
140: }
141:
142: public boolean side_effects() {
143: return false;
144: }
145:
146: public String toString() {
147: return "QuoteExp[" + value + "]";
148: }
149:
150: public void print(OutPort out) {
151: out.startLogicalBlock("(Quote", ")", 2);
152: out.writeSpaceLinear();
153: if (value instanceof Expression)
154: value = value.toString(); // To avoid cycles.
155: gnu.lists.AbstractFormat saveFormat = out.objectFormat;
156: try {
157: out.objectFormat = Language.getDefaultLanguage().getFormat(
158: true);
159: out.print(value);
160: /*
161: if (value != null)
162: {
163: out.print(" ::");
164: out.print(value.getClass().getName());
165: }
166: */
167: } finally {
168: out.objectFormat = saveFormat;
169: }
170: out.endLogicalBlock(")");
171: }
172: }
|