1 package gnu.expr; 2 import gnu.bytecode.*; 3 import gnu.kawa.io.OutPort; 4 import gnu.mapping.CallContext; 5 6 /** 7 * This class represents try/catch/finally. 8 * @author Per Bothner 9 */ 10 11 public class TryExp extends Expression 12 { 13 Expression try_clause; 14 15 CatchClause catch_clauses; 16 17 Expression finally_clause; 18 getCatchClauses()19 public final CatchClause getCatchClauses () { return catch_clauses; } getFinallyClause()20 public final Expression getFinallyClause () { return finally_clause; } setCatchClauses(CatchClause catch_clauses)21 public final void setCatchClauses (CatchClause catch_clauses) 22 { 23 this.catch_clauses = catch_clauses; 24 } 25 addCatchClause(Declaration decl, Expression body)26 public void addCatchClause(Declaration decl, Expression body) { 27 CatchClause clause = new CatchClause(decl, body); 28 CatchClause last = catch_clauses; 29 if (last == null) 30 catch_clauses = clause; 31 else { 32 while (last.next != null) 33 last = last.next; 34 last.next = clause; 35 } 36 } 37 TryExp(Expression try_clause, Expression finally_clause)38 public TryExp (Expression try_clause, Expression finally_clause) 39 { 40 this.try_clause = try_clause; 41 this.finally_clause = finally_clause; 42 } 43 mustCompile()44 protected boolean mustCompile () { return false; } 45 46 @Override apply(CallContext ctx)47 public void apply (CallContext ctx) throws Throwable 48 { 49 try 50 { 51 try_clause.apply(ctx); 52 ctx.runUntilDone(); 53 } 54 catch (Throwable ex) 55 { 56 for (CatchClause clause = catch_clauses; clause != null; 57 clause = clause.next) 58 { 59 Declaration decl = clause.firstDecl(); 60 ClassType typeVal = (ClassType) decl.getTypeExp().eval(ctx); 61 if (typeVal.isInstance(ex)) 62 { 63 ctx.setupApply(clause, ex); 64 ctx.runUntilDone(); 65 return; 66 } 67 } 68 throw ex; 69 } 70 finally 71 { 72 if (finally_clause != null) 73 finally_clause.eval(ctx); 74 } 75 } 76 compile(Compilation comp, Target target)77 public void compile (Compilation comp, Target target) 78 { 79 CodeAttr code = comp.getCode(); 80 boolean has_finally = finally_clause != null; 81 Target ttarg; 82 if (target instanceof StackTarget 83 || target instanceof ConsumerTarget || target instanceof IgnoreTarget 84 || (target instanceof ConditionalTarget && finally_clause == null)) 85 ttarg = target; 86 else 87 ttarg = Target.pushValue(target.getType()); 88 code.emitTryStart(has_finally, 89 ttarg instanceof StackTarget ? ttarg.getType() : null); 90 try_clause.compileWithPosition(comp, ttarg); 91 CatchClause catch_clause = catch_clauses; 92 for (; catch_clause != null; catch_clause = catch_clause.getNext()) 93 { 94 Variable callContextSave = comp.callContextVar; 95 catch_clause.compile(comp, ttarg); 96 comp.callContextVar = callContextSave; 97 } 98 99 if (finally_clause != null) 100 { 101 code.emitFinallyStart(); 102 finally_clause.compileWithPosition(comp, Target.Ignore); 103 code.emitFinallyEnd(); 104 } 105 code.emitTryCatchEnd(); 106 if (ttarg != target) 107 target.compileFromStack(comp, target.getType()); 108 } 109 visit(ExpVisitor<R,D> visitor, D d)110 protected <R,D> R visit (ExpVisitor<R,D> visitor, D d) 111 { 112 return visitor.visitTryExp(this, d); 113 } 114 visitChildren(ExpVisitor<R,D> visitor, D d)115 protected <R,D> void visitChildren (ExpVisitor<R,D> visitor, D d) 116 { 117 try_clause = visitor.visitAndUpdate(try_clause, d); 118 CatchClause catch_clause = catch_clauses; 119 while (visitor.exitValue == null && catch_clause != null) 120 { 121 visitor.visit(catch_clause, d); // FIXME update? 122 catch_clause = catch_clause.getNext(); 123 } 124 125 if (visitor.exitValue == null && finally_clause != null) 126 finally_clause = visitor.visitAndUpdate(finally_clause, d); 127 } 128 calculateType()129 protected gnu.bytecode.Type calculateType() { 130 Type t = try_clause.getType(); 131 for (CatchClause clause = catch_clauses; 132 clause != null; clause = clause.getNext()) { 133 t = Language.unionType(t, clause.getType()); 134 } 135 return t; 136 } 137 print(OutPort ps)138 public void print (OutPort ps) 139 { 140 ps.startLogicalBlock("(Try", ")", 2); 141 ps.writeSpaceFill(); 142 try_clause.print(ps); 143 CatchClause catch_clause = catch_clauses; 144 for (; catch_clause != null; catch_clause = catch_clause.getNext()) 145 { 146 catch_clause.print(ps); 147 } 148 if (finally_clause != null) 149 { 150 ps.writeSpaceLinear(); 151 ps.print(" finally: "); 152 finally_clause.print(ps); 153 } 154 ps.endLogicalBlock(")"); 155 } 156 } 157