1 4 package gnu.expr; 5 import gnu.bytecode.*; 6 import gnu.mapping.*; 7 8 12 13 public class ReferenceExp extends AccessExp 14 { 15 static int counter; 16 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 23 public static final int CREATE_FIELD_REFERENCE = NEXT_AVAIL_FLAG << 3; 24 25 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 42 public final boolean isProcedureName() 43 { 44 return (flags & PROCEDURE_NAME) != 0; 45 } 46 47 48 public final void setProcedureName(boolean setting) 49 { 50 setFlag(setting, PROCEDURE_NAME); 51 } 52 53 public ReferenceExp (Object symbol) 54 { 55 this.symbol = symbol; 56 } 57 58 public ReferenceExp (Object 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 73 { 74 Object 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 instance = binding.field.getStaticFlag() ? null 98 : contextDecl().getValue().eval(ctx); 99 value = binding.field.getReflectField().get(instance); 100 } 101 catch (Exception ex) 102 { 103 String msg = "exception evaluating "+symbol 104 +" from "+binding.field+" - "+ex; 105 throw new UnboundLocationException(msg, this); 107 } 108 } 109 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 property = getFlag(PREFER_BINDING2) && isProcedureName() 127 ? EnvironmentKey.FUNCTION 128 : null; 129 if (getDontDereference()) 130 value = env.getLocation(sym, property); 131 else 132 { 133 Object 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; 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 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 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 toString() 230 { 231 return "RefExp/"+symbol+'/'+id+'/'; 232 } 233 } 234 | Popular Tags |