001: package gnu.expr;
002:
003: import gnu.bytecode.*;
004: import gnu.mapping.*;
005:
006: /**
007: * This class represents try/catch/finally.
008: * @author Per Bothner
009: */
010:
011: public class TryExp extends Expression {
012: Expression try_clause;
013:
014: CatchClause catch_clauses;
015:
016: Expression finally_clause;
017:
018: public final CatchClause getCatchClauses() {
019: return catch_clauses;
020: }
021:
022: public final void setCatchClauses(CatchClause catch_clauses) {
023: this .catch_clauses = catch_clauses;
024: }
025:
026: public TryExp(Expression try_clause, Expression finally_clause) {
027: this .try_clause = try_clause;
028: this .finally_clause = finally_clause;
029: }
030:
031: protected boolean mustCompile() {
032: return catch_clauses != null;
033: }
034:
035: public void apply(CallContext ctx) throws Throwable {
036: if (catch_clauses != null)
037: throw new RuntimeException(
038: "internal error - TryExp.eval called");
039: try {
040: try_clause.apply(ctx);
041: ctx.runUntilDone();
042: } catch (Throwable ex) {
043: for (CatchClause clause = catch_clauses; clause != null; clause = clause.next) {
044: // Declaration decl = clause.firstDecl();
045: // FIXME
046: }
047: throw ex;
048: } finally {
049: finally_clause.eval(ctx);
050: }
051: }
052:
053: public void compile(Compilation comp, Target target) {
054: CodeAttr code = comp.getCode();
055: boolean has_finally = finally_clause != null;
056: Type result_type = target instanceof IgnoreTarget ? null
057: : getType();
058: Target ttarg;
059: if (result_type == null)
060: ttarg = Target.Ignore;
061: else if (result_type == Type.pointer_type)
062: ttarg = Target.pushObject;
063: else
064: ttarg = new StackTarget(result_type);
065: code.emitTryStart(has_finally, result_type);
066: try_clause.compileWithPosition(comp, ttarg);
067: code.emitTryEnd();
068:
069: CatchClause catch_clause = catch_clauses;
070: for (; catch_clause != null; catch_clause = catch_clause
071: .getNext()) {
072: catch_clause.compile(comp, ttarg);
073: }
074:
075: if (finally_clause != null) {
076: code.emitFinallyStart();
077: finally_clause.compileWithPosition(comp, Target.Ignore);
078: code.emitFinallyEnd();
079: }
080: code.emitTryCatchEnd();
081: if (result_type != null)
082: target.compileFromStack(comp, result_type);
083: }
084:
085: protected Expression walk(ExpWalker walker) {
086: return walker.walkTryExp(this );
087: }
088:
089: protected void walkChildren(ExpWalker walker) {
090: try_clause = walker.walk(try_clause);
091: CatchClause catch_clause = catch_clauses;
092: while (walker.exitValue == null && catch_clause != null) {
093: walker.walk(catch_clause);
094: catch_clause = catch_clause.getNext();
095: }
096:
097: if (walker.exitValue == null && finally_clause != null)
098: finally_clause = walker.walk(finally_clause);
099: }
100:
101: public void print(OutPort ps) {
102: ps.startLogicalBlock("(Try", ")", 2);
103: ps.writeSpaceFill();
104: try_clause.print(ps);
105: CatchClause catch_clause = catch_clauses;
106: for (; catch_clause != null; catch_clause = catch_clause
107: .getNext()) {
108: catch_clause.print(ps);
109: }
110: if (finally_clause != null) {
111: ps.writeSpaceLinear();
112: ps.print(" finally: ");
113: finally_clause.print(ps);
114: }
115: ps.endLogicalBlock(")");
116: }
117: }
|