KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > expr > IfExp


1 // Copyright (c) 2001 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.expr;
5 import gnu.bytecode.*;
6 import gnu.mapping.*;
7
8 /**
9  * This class represents a conditional.
10  * @author Per Bothner
11  */

12
13 public class IfExp extends Expression
14 {
15   Expression test;
16   Expression then_clause;
17   Expression else_clause;
18
19   public IfExp (Expression i, Expression t, Expression e)
20   {
21     test = i; then_clause = t; else_clause = e;
22   }
23
24   protected final Language getLanguage()
25   {
26     return Language.getDefaultLanguage(); // FIXME
27
}
28
29   protected boolean mustCompile () { return false; }
30
31   public void apply (CallContext ctx) throws Throwable JavaDoc
32   {
33     if (getLanguage().isTrue(test.eval(ctx)))
34       then_clause.apply(ctx);
35     else if (else_clause != null)
36       else_clause.apply(ctx);
37   }
38
39   public void compile (Compilation comp, Target target)
40   {
41     compile(test, then_clause,
42         else_clause == null ? QuoteExp.voidExp : else_clause,
43         comp, target);
44   }
45
46   public static void compile (Expression test, Expression then_clause,
47                   Expression else_clause,
48                   Compilation comp, Target target)
49   {
50     Language language = comp.getLanguage();
51     gnu.bytecode.CodeAttr code = comp.getCode();
52     Label trueLabel, falseLabel;
53     boolean trueInherited, falseInherited;
54     // A constant else_clause results from the expansion of (and ...),
55
// and also if the else_clause if elided, so we optimize this case.
56
if (target instanceof ConditionalTarget
57     && else_clause instanceof QuoteExp)
58       {
59     falseInherited = true;
60     Object JavaDoc value = ((QuoteExp) else_clause).getValue();
61     if (language.isTrue(value))
62       falseLabel = ((ConditionalTarget) target).ifTrue;
63     else
64       falseLabel = ((ConditionalTarget) target).ifFalse;
65       }
66     else if (else_clause instanceof ExitExp
67              && ((ExitExp) else_clause).result instanceof QuoteExp
68              && ((ExitExp) else_clause).block.subTarget instanceof IgnoreTarget)
69       {
70         falseInherited = true;
71         falseLabel = ((ExitExp) else_clause).block.exitLabel;
72       }
73     else
74       {
75     falseInherited = false;
76     falseLabel = new Label(code);
77       }
78     // The expansion of "or" creates an IfExp with test==then_clause.
79
// In that case, we know that the then_clause must be true.
80
// Let's optimize that case.
81
if (test == then_clause && target instanceof ConditionalTarget
82     && then_clause instanceof ReferenceExp)
83       {
84     trueInherited = true;
85     trueLabel = ((ConditionalTarget) target).ifTrue;
86       }
87     else
88       {
89     trueInherited = false;
90     trueLabel = new Label(code);
91       }
92     ConditionalTarget ctarget
93       = new ConditionalTarget(trueLabel, falseLabel, language);
94     if (trueInherited)
95       ctarget.trueBranchComesFirst = false;
96     test.compile(comp, ctarget);
97     code.emitIfThen();
98     if (! trueInherited /* && trueLabel.hasFixups()*/)
99       {
100     trueLabel.define(code);
101         // An alternative to saving and restoring callContextVar
102
// would be to surround the compile with a pushScope and popScope.
103
// That would also release any "dangling" callContextVar.
104
Variable callContextSave = comp.callContextVar;
105     then_clause.compileWithPosition(comp, target);
106         comp.callContextVar = callContextSave;
107       }
108     if (! falseInherited /* && falseLabel.hasFixups()*/)
109       {
110     code.emitElse();
111     falseLabel.define(code);
112         // See note above for then_clause.
113
Variable callContextSave = comp.callContextVar;
114     if (else_clause == null)
115       comp.compileConstant(Values.empty, target);
116     else
117       else_clause.compileWithPosition(comp, target);
118         comp.callContextVar = callContextSave;
119       }
120     else
121       code.setUnreachable();
122     code.emitFi();
123   }
124
125   protected Expression walk (ExpWalker walker)
126   {
127     return walker.walkIfExp(this);
128   }
129
130   protected void walkChildren(ExpWalker walker)
131   {
132     test = test.walk(walker);
133     if (walker.exitValue == null)
134       then_clause = walker.walk(then_clause);
135     if (walker.exitValue == null && else_clause != null)
136      else_clause = walker.walk(else_clause);
137   }
138
139   public gnu.bytecode.Type getType()
140   {
141     Type t1 = then_clause.getType();
142     Type t2 = else_clause == null ? Type.void_type : else_clause.getType();
143     if (t1 == t2)
144       return t1;
145     // FIXME - implement union types
146
return Type.pointer_type;
147   }
148
149   public void print (OutPort out)
150   {
151     out.startLogicalBlock("(If ", false, ")");
152     out.setIndentation(-2, false);
153     test.print(out);
154     out.writeSpaceLinear();
155     then_clause.print (out);
156     if (else_clause != null)
157       {
158     out.writeSpaceLinear();
159     else_clause.print (out);
160       }
161     out.endLogicalBlock(")");
162   }
163 }
164
Popular Tags