KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > expr > ReferenceExp


1 // Copyright (c) 1999, 2005 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.expr;
5 import gnu.bytecode.*;
6 import gnu.mapping.*;
7
8 /**
9  * This class represents a variable reference (an identifier).
10  * @author Per Bothner
11  */

12
13 public class ReferenceExp extends AccessExp
14 {
15   static int counter;
16   /** Unique id number, to ease print-outs and debugging. */
17   int id = ++counter;
18
19   public static final int DONT_DEREFERENCE = NEXT_AVAIL_FLAG;
20   public static final int PROCEDURE_NAME = NEXT_AVAIL_FLAG << 1;
21   public static final int PREFER_BINDING2 = NEXT_AVAIL_FLAG << 2;
22   /** Create a FieldLocation referencing the binding. */
23   public static final int CREATE_FIELD_REFERENCE = NEXT_AVAIL_FLAG << 3;
24
25   /* If true, must have binding.isIndirectBinding(). Don't dereference it. */
26   public final boolean getDontDereference()
27   {
28     return (flags & DONT_DEREFERENCE) != 0;
29   }
30
31   public final void setDontDereference(boolean setting)
32   { setFlag(setting, DONT_DEREFERENCE); }
33
34   public final boolean isUnknown ()
35   {
36     return Declaration.isUnknown(binding);
37   }
38
39   /** True if this identifier appears in "function call position".
40    * If so, it should be interpreted as a function name, which makes a
41    * difference for languages (like Common Lisp) that have two name spaces. */

42   public final boolean isProcedureName()
43   {
44     return (flags & PROCEDURE_NAME) != 0;
45   }
46
47   /** Note if this identifier appears in "function call position". */
48   public final void setProcedureName(boolean setting)
49   {
50     setFlag(setting, PROCEDURE_NAME);
51   }
52
53   public ReferenceExp (Object JavaDoc symbol)
54   {
55     this.symbol = symbol;
56   }
57
58   public ReferenceExp (Object JavaDoc symbol, Declaration binding)
59   {
60     this.symbol = symbol;
61     this.binding = binding;
62   }
63
64   public ReferenceExp (Declaration binding)
65   {
66     this(binding.getSymbol(), binding);
67   }
68
69   protected boolean mustCompile () { return false; }
70
71   public void apply (CallContext ctx)
72     throws Throwable JavaDoc
73   {
74     Object JavaDoc value;
75     if (binding != null && binding.isAlias() && ! getDontDereference()
76         && binding.value instanceof ReferenceExp)
77       {
78         ReferenceExp rexp = (ReferenceExp) binding.value;
79         if (rexp.getDontDereference() && rexp.binding != null)
80           {
81             Expression v = rexp.binding.getValue();
82             if (v instanceof QuoteExp || v instanceof ReferenceExp
83                 || v instanceof LambdaExp)
84               {
85                 v.apply(ctx);
86                 return;
87               }
88           }
89         value = binding.value.eval(ctx);
90       }
91     else if (binding != null && binding.field != null
92              && binding.field.getDeclaringClass().isExisting()
93              && (! getDontDereference() || binding.isIndirectBinding()))
94       {
95         try
96           {
97             Object JavaDoc instance = binding.field.getStaticFlag() ? null
98               : contextDecl().getValue().eval(ctx);
99             value = binding.field.getReflectField().get(instance);
100           }
101         catch (Exception JavaDoc ex)
102           {
103             String JavaDoc msg = "exception evaluating "+symbol
104               +" from "+binding.field+" - "+ex;
105             // We abuse msg as a UnboundLocationException name.
106
throw new UnboundLocationException(msg, this);
107           }
108       }
109     // This isn't just an optimization - it's needed for evaluating procedural
110
// macros (e.g. syntax-case) defined in a not-yet-compiled module.
111
else if (binding != null
112         && (binding.value instanceof QuoteExp
113             || binding.value instanceof LambdaExp)
114         && binding.value != QuoteExp.undefined_exp
115         && (! getDontDereference() || binding.isIndirectBinding()))
116       {
117         value = binding.value.eval(ctx);
118       }
119     else if (binding == null
120              || (binding.context instanceof ModuleExp
121                 && ! binding.isPrivate()))
122       {
123         Environment env = ctx.getEnvironment();
124         Symbol sym = symbol instanceof Symbol ? (Symbol) symbol
125           : env.getSymbol(symbol.toString());
126         Object JavaDoc property = getFlag(PREFER_BINDING2) && isProcedureName()
127           ? EnvironmentKey.FUNCTION
128           : null;
129         if (getDontDereference())
130           value = env.getLocation(sym, property);
131         else
132           {
133             Object JavaDoc unb = gnu.mapping.Location.UNBOUND;
134             value = env.get(sym, property, unb);
135             if (value == unb)
136               throw new UnboundLocationException(sym, this);
137           }
138         ctx.writeValue(value);
139         return;
140       }
141     else
142       value = ctx.evalFrames[ScopeExp.nesting(binding.context)][binding.evalIndex];
143     if (! getDontDereference() && binding.isIndirectBinding())
144       value = ((gnu.mapping.Location) value).get();
145     ctx.writeValue(value);
146   }
147
148   public void compile (Compilation comp, Target target)
149   {
150     if (! (target instanceof ConsumerTarget)
151         || ! ((ConsumerTarget) target).compileWrite(this, comp))
152       binding.load(this, flags, comp, target);
153   }
154
155   protected Expression walk (ExpWalker walker)
156   {
157     return walker.walkReferenceExp(this);
158   }
159   public Expression inline (ApplyExp exp, InlineCalls walker, Declaration decl)
160   {
161     decl = this.binding; // We don't use the passed-in Declaration.
162
if (decl != null && ! decl.getFlag(Declaration.IS_UNKNOWN))
163       {
164         decl = Declaration.followAliases(decl);
165         if (decl.isIndirectBinding())
166           return exp;
167         Expression dval = decl.getValue();
168         if (dval != null)
169           return dval.inline(exp, walker, decl);
170       }
171     else if (getSymbol() instanceof Symbol)
172       {
173         Symbol symbol = (Symbol) getSymbol();
174         Object JavaDoc fval = Environment.getCurrent().getFunction(symbol, null);
175         if (fval instanceof Procedure)
176           return new QuoteExp(fval).inline(exp, walker, null);
177       }
178     return exp;
179   }
180
181   public void print (OutPort ps)
182   {
183     ps.print("(Ref/");
184     ps.print(id);
185     if (symbol != null
186     && (binding == null || symbol.toString() != binding.getName()))
187       {
188     ps.print('/');
189     ps.print(symbol);
190       }
191     if (binding != null)
192       {
193     ps.print('/');
194     ps.print(binding);
195       }
196     ps.print(")");
197   }
198
199   public gnu.bytecode.Type getType()
200   {
201     Declaration decl = binding;
202     if (decl == null || decl.isFluid())
203       return Type.pointer_type;
204     if (getDontDereference())
205       return Compilation.typeLocation;
206     decl = Declaration.followAliases(decl);
207     Type type = decl.getType();
208     if (type == null || type == Type.pointer_type)
209       {
210         Expression value = decl.getValue();
211         if (value != null)
212           {
213             // Kludge to guard against cycles.
214
// Not verified if it is really needed, but just in case ...
215
Expression save = decl.value;
216             decl.value = null;
217             type = value.getType();
218             decl.value = save;
219           }
220       }
221     return type;
222   }
223
224   public boolean side_effects ()
225   {
226     return binding == null || ! binding.isLexical();
227   }
228
229   public String JavaDoc toString()
230   {
231     return "RefExp/"+symbol+'/'+id+'/';
232   }
233 }
234
Popular Tags