1 4 package gnu.expr; 5 import gnu.bytecode.*; 6 import gnu.mapping.*; 7 8 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(); } 28 29 protected boolean mustCompile () { return false; } 30 31 public void apply (CallContext ctx) throws Throwable 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 if (target instanceof ConditionalTarget 57 && else_clause instanceof QuoteExp) 58 { 59 falseInherited = true; 60 Object 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 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 ) 99 { 100 trueLabel.define(code); 101 Variable callContextSave = comp.callContextVar; 105 then_clause.compileWithPosition(comp, target); 106 comp.callContextVar = callContextSave; 107 } 108 if (! falseInherited ) 109 { 110 code.emitElse(); 111 falseLabel.define(code); 112 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 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 |