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:
08: /**
09: * Class used to implement "fluid-let" for Scheme and "let" for Emacs.
10: * @author Per Bothner
11: */
12:
13: public class FluidLetExp extends LetExp {
14: public FluidLetExp(Expression[] i) {
15: super (i);
16: }
17:
18: public void compile(Compilation comp, Target target) {
19: CodeAttr code = comp.getCode();
20: code.pushScope();
21: Type result_type = target instanceof IgnoreTarget ? null
22: : getType();
23: Target ttarg;
24: if (result_type == null)
25: ttarg = Target.Ignore;
26: else if (result_type == Type.pointer_type)
27: ttarg = Target.pushObject;
28: else
29: ttarg = new StackTarget(result_type);
30: Variable future = code.addLocal(typeFuture);
31: code.emitInvokeStatic(getContextMethod);
32: code.emitDup(1);
33: code.emitStore(future);
34: code.emitDup(1);
35: code.emitGetField(fluidBindingsField);
36: Variable old_bindings = code.addLocal(typeFluidBinding);
37: code.emitDup(1);
38: code.emitStore(old_bindings);
39: code.enterScope(scope);
40: Declaration decl = firstDecl();
41: for (int i = 0; i < inits.length; i++, decl = decl.nextDecl()) {
42: decl.allocateVariable(code);
43: inits[i].compile(comp, Target.pushObject);
44: decl.base.load(comp);
45: code.emitInvokeStatic(makeFluidBindingMethod);
46: code.emitDup(1);
47: code.emitStore(decl.getVariable());
48: }
49: code.emitInvokeVirtual(setFluidsMethod);
50: code.emitTryStart(true, result_type);
51: body.compileWithPosition(comp, ttarg);
52: code.emitTryEnd();
53: code.emitFinallyStart();
54: code.emitLoad(future);
55: code.emitLoad(old_bindings);
56: code.emitInvokeVirtual(resetFluidsMethod);
57: code.emitTryCatchEnd();
58: code.popScope();
59: code.popScope();
60: if (result_type != null)
61: target.compileFromStack(comp, result_type);
62: }
63:
64: protected Expression walk(ExpWalker walker) {
65: return walker.walkFluidLetExp(this );
66: }
67:
68: static ClassType typeFuture = ClassType.make("gnu.mapping.Future");
69: static Method getContextMethod = typeFuture.addMethod("getContext",
70: Type.typeArray0, typeFuture, Access.STATIC | Access.PUBLIC);
71: public static ClassType typeFluidBinding = ClassType
72: .make("gnu.mapping.FluidBinding");
73: static Field fluidBindingsField = typeFuture.addField(
74: "fluidBindings", typeFluidBinding, Access.STATIC
75: | Access.PUBLIC);
76: public static Field valueField = typeFluidBinding.addField("value",
77: Type.pointer_type, Access.PUBLIC);
78: static Method setFluidsMethod;
79: static Method resetFluidsMethod;
80: static Method makeFluidBindingMethod;
81: static {
82: Type[] args = { typeFluidBinding };
83: setFluidsMethod = typeFuture.addMethod("setFluids", args,
84: Type.void_type, Access.PUBLIC);
85: resetFluidsMethod = typeFuture.addMethod("resetFluids", args,
86: Type.void_type, Access.PUBLIC);
87: args = new Type[3];
88: args[0] = typeFluidBinding;
89: args[1] = Type.pointer_type;
90: args[2] = ClassType.make("gnu.mapping.Binding");
91: makeFluidBindingMethod = typeFluidBinding.addMethod("make",
92: args, typeFluidBinding, Access.PUBLIC | Access.STATIC);
93: }
94: }
|