1 4 package gnu.expr; 5 import gnu.bytecode.*; 6 import gnu.mapping.*; 7 8 12 13 public class BlockExp extends Expression 14 { 15 Declaration label; 16 Expression body; 17 18 19 Expression exitBody; 20 21 public void setBody(Expression body) 22 { 23 this.body = body; 24 } 25 26 public void setBody(Expression body, Expression exitBody) 27 { 28 this.body = body; 29 this.exitBody = exitBody; 30 } 31 32 33 Target subTarget; 34 35 Label exitLabel; 36 37 TryState oldTryState; 38 39 protected boolean mustCompile () { return false; } 40 41 public void apply (CallContext ctx) throws Throwable 42 { 43 Object result; 44 try 45 { 46 result = body.eval(ctx); 47 } 48 catch (BlockExitException ex) 49 { 50 if (ex.exit.block != this) 51 throw ex; 52 result = ex.exit.result; 53 if (exitBody != null) 54 result = exitBody.eval(ctx); 55 } 56 ctx.writeValue(result); 57 } 58 59 public void compile (Compilation comp, Target target) 60 { 61 Target subTarget; 62 if (target instanceof IgnoreTarget 63 || target == Target.pushObject) 64 subTarget = target; 65 else 66 { 67 subTarget = new StackTarget(getType()); 70 } 71 gnu.bytecode.CodeAttr code = comp.getCode(); 72 oldTryState = code.getCurrentTry(); 73 exitLabel = new Label(code); 74 this.subTarget = exitBody == null ? subTarget : Target.Ignore; 75 body.compileWithPosition(comp, subTarget); 76 if (exitBody != null) 77 { 78 Label doneLabel = new Label(code); 79 code.emitGoto(doneLabel); 80 exitLabel.define(code); 81 exitBody.compileWithPosition(comp, subTarget); 82 doneLabel.define(code); 83 } 84 else 85 exitLabel.define(code); 86 if (subTarget != target) 87 target.compileFromStack(comp, subTarget.getType()); 88 oldTryState = null; 89 } 90 91 protected Expression walk (ExpWalker walker) 92 { 93 return walker.walkBlockExp(this); 94 } 95 96 protected void walkChildren (ExpWalker walker) 97 { 98 body = walker.walk(body); 99 if (walker.exitValue == null && exitBody != null) 100 exitBody = walker.walk(exitBody); 101 } 102 103 public void print (OutPort out) 104 { 105 out.startLogicalBlock("(Block", ")", 2); 106 if (label != null) 107 out.print(label.getName()); 108 out.writeSpaceLinear(); 109 body.print(out); 110 if (exitBody != null) 111 { 112 out.writeSpaceLinear(); 113 out.print("else "); 114 exitBody.print(out); 115 } 116 out.endLogicalBlock(")"); 117 } 118 } 119 120 class BlockExitException extends RuntimeException 121 { 122 ExitExp exit; 123 Object result; 124 public BlockExitException (ExitExp exit, Object result) 125 { 126 this.exit = exit; 127 this.result = result; 128 } 129 } 130 | Popular Tags |