01: // Copyright (c) 1999, 2000 Per M.A. Bothner.
02: // This is free software; for terms and warranty disclaimer see ./COPYING.
03:
04: package gnu.expr;
05:
06: import gnu.bytecode.*;
07: import gnu.mapping.*;
08:
09: /**
10: * Class used to implement "fluid-let" for Scheme and "let" for Emacs.
11: * @author Per Bothner
12: */
13:
14: public class FluidLetExp extends LetExp {
15: public FluidLetExp(Expression[] i) {
16: super (i);
17: }
18:
19: protected boolean mustCompile() {
20: return true;
21: }
22:
23: public void compile(Compilation comp, Target target) {
24: CodeAttr code = comp.getCode();
25: Type result_type = target instanceof IgnoreTarget ? null
26: : getType();
27: Target ttarg;
28: if (result_type == null)
29: ttarg = Target.Ignore;
30: else if (result_type == Type.pointer_type)
31: ttarg = Target.pushObject;
32: else
33: ttarg = new StackTarget(result_type);
34: Scope scope = getVarScope();
35: code.enterScope(scope);
36: Variable ctx = scope.addVariable(code,
37: Compilation.typeCallContext, null);
38: comp.loadCallContext();
39: code.emitStore(ctx);
40: Variable[] save = new Variable[inits.length];
41:
42: Declaration decl = firstDecl();
43: doInits(decl, 0, save, comp, ctx);
44: code.emitTryStart(true, result_type);
45: body.compileWithPosition(comp, ttarg);
46: code.emitTryEnd();
47: code.emitFinallyStart();
48:
49: for (int i = 0; i < inits.length; i++, decl = decl.nextDecl()) {
50: decl.load(null, ReferenceExp.DONT_DEREFERENCE, comp,
51: Target.pushObject);
52: code.emitLoad(save[i]);
53: code.emitLoad(ctx);
54: code.emitInvokeVirtual(Compilation.typeLocation
55: .getDeclaredMethod("setRestore", 2));
56:
57: }
58: code.emitTryCatchEnd();
59: popScope(code);
60: if (result_type != null)
61: target.compileFromStack(comp, result_type);
62: }
63:
64: private void doInits(Declaration decl, int i, Variable[] save,
65: Compilation comp, Variable ctx) {
66: if (i >= inits.length)
67: return;
68: CodeAttr code = comp.getCode();
69: save[i] = code.addLocal(Type.pointer_type);
70: decl.allocateVariable(code);
71: decl.base.load(null, ReferenceExp.DONT_DEREFERENCE, comp,
72: Target.pushObject);
73: code.emitDup();
74: code.emitStore(decl.getVariable());
75: inits[i].compile(comp, Target.pushObject);
76: doInits(decl.nextDecl(), i + 1, save, comp, ctx);
77: code.emitLoad(ctx);
78: code.emitInvokeVirtual(Compilation.typeLocation
79: .getDeclaredMethod("setWithSave", 2));
80: code.emitStore(save[i]);
81: }
82:
83: protected Expression walk(ExpWalker walker) {
84: return walker.walkFluidLetExp(this );
85: }
86:
87: public void print(OutPort out) {
88: print(out, "(FluidLet", ")");
89: }
90: }
|