1 4 package gnu.expr; 5 import gnu.mapping.*; 6 import gnu.mapping.Location; import gnu.bytecode.*; 8 9 12 13 public class SetExp extends AccessExp 14 { 15 16 Expression new_value; 17 18 public SetExp (Object symbol, Expression val) 19 { this.symbol = symbol; new_value = val; } 20 21 public SetExp (Declaration decl, Expression val) 22 { 23 this.binding = decl; 24 symbol = decl.getSymbol(); 25 new_value = val; 26 } 27 28 public static SetExp makeDefinition (Object symbol, Expression val) 29 { 30 SetExp sexp = new SetExp(symbol, val); 31 sexp.setDefining(true); 32 return sexp; 33 } 34 35 public static SetExp makeDefinition (Declaration decl, Expression val) 36 { 37 SetExp sexp = new SetExp(decl, val); 38 sexp.setDefining(true); 39 return sexp; 40 } 41 42 43 public final Expression getNewValue() { return new_value; } 44 45 public static final int DEFINING_FLAG = NEXT_AVAIL_FLAG; 46 public static final int GLOBAL_FLAG = NEXT_AVAIL_FLAG << 1; 47 public static final int PREFER_BINDING2 = NEXT_AVAIL_FLAG << 2; 48 public static final int PROCEDURE = NEXT_AVAIL_FLAG << 3; 49 public static final int SET_IF_UNBOUND = NEXT_AVAIL_FLAG << 4; 50 public static final int HAS_VALUE = NEXT_AVAIL_FLAG << 5; 51 52 public final boolean isDefining () 53 { 54 return (flags & DEFINING_FLAG) != 0; 55 } 56 57 public final void setDefining (boolean value) 58 { 59 if (value) flags |= DEFINING_FLAG; else flags &= ~DEFINING_FLAG; 60 } 61 62 63 public final boolean getHasValue() 64 { return (flags & HAS_VALUE) != 0; } 65 66 public final void setHasValue (boolean value) 67 { if (value) flags |= HAS_VALUE; else flags &= ~HAS_VALUE; } 68 69 70 public final boolean isFuncDef() 71 { return (flags & PROCEDURE) != 0; } 72 73 public final void setFuncDef (boolean value) 74 { if (value) flags |= PROCEDURE; else flags &= ~PROCEDURE; } 75 76 public final boolean isSetIfUnbound() 77 { return (flags & SET_IF_UNBOUND) != 0; } 78 79 public final void setSetIfUnbound (boolean value) 80 { if (value) flags |= SET_IF_UNBOUND; else flags &= ~SET_IF_UNBOUND; } 81 82 protected boolean mustCompile () { return false; } 83 84 public void apply (CallContext ctx) throws Throwable 85 { 86 Environment env = ctx.getEnvironment(); 87 Symbol sym = symbol instanceof Symbol ? (Symbol) symbol 88 : env.getSymbol(symbol.toString()); 89 Object property = null; 90 Language language = Language.getDefaultLanguage(); 91 if (isFuncDef() && language.hasSeparateFunctionNamespace()) 92 property = EnvironmentKey.FUNCTION; 93 if (isSetIfUnbound()) 94 { 95 Location loc = env.getLocation(sym, property); 96 if (! loc.isBound()) 97 loc.set(new_value.eval (env)); 98 if (getHasValue()) 99 ctx.writeValue(loc); 100 return; 101 } 102 103 Object new_val = new_value.eval (env); 104 if (binding != null && ! (binding.context instanceof ModuleExp)) 105 { 106 Object [] evalFrame = ctx.evalFrames[ScopeExp.nesting(binding.context)]; 107 if (binding.isIndirectBinding()) 108 { 109 Location loc; 110 if (isDefining()) 111 evalFrame[binding.evalIndex] = Location.make(sym); 112 loc = (Location) evalFrame[binding.evalIndex]; 113 loc.set(new_value); 114 } 115 else 116 evalFrame[binding.evalIndex] = new_val; 117 } 118 else if (isDefining ()) 119 { 120 125 env.define(sym, property, new_val); 126 } 127 else 128 { 129 env.put(sym, property, new_val); 130 } 131 if (getHasValue()) 132 ctx.writeValue(new_val); 133 } 134 135 public void compile (Compilation comp, Target target) 136 { 137 if (new_value instanceof LambdaExp 138 && target instanceof IgnoreTarget 139 && ((LambdaExp) new_value).getInlineOnly()) 140 return; 141 Type type; 142 gnu.bytecode.CodeAttr code = comp.getCode(); 143 boolean needValue = getHasValue() && ! (target instanceof IgnoreTarget); 145 146 boolean valuePushed = false; 150 151 157 Declaration decl = binding; 158 Expression declValue = decl.getValue(); 159 if (decl.getFlag(Declaration.EARLY_INIT) 160 && isDefining() && ! decl.ignorable()) 161 { 162 BindingInitializer.create(decl, new_value, comp); 163 } 164 else if (declValue instanceof LambdaExp 165 && decl.context instanceof ModuleExp 166 && (! decl.isPrivate() || declValue instanceof ClassExp) 167 && ((LambdaExp) declValue).getName() != null && declValue == new_value) 169 { 170 ((LambdaExp) new_value).compileSetField(comp); 171 } 172 else if (decl.context instanceof ModuleExp 173 && (decl.getFlag(Declaration.IS_CONSTANT) || decl.isAlias()) 174 && isDefining() 175 && declValue != null) 176 { if (needValue) 178 { 179 decl.load(this, 0, comp, Target.pushObject); 180 valuePushed = true; 181 } 182 } 183 else 184 { 185 AccessExp access = this; 186 Declaration owner = contextDecl(); 187 if (! isDefining()) 188 { 189 while (decl != null && decl.isAlias()) 190 { 191 declValue = decl.getValue(); 192 if (! (declValue instanceof ReferenceExp)) 193 break; 194 ReferenceExp rexp = (ReferenceExp) declValue; 195 Declaration orig = rexp.binding; 196 if (orig == null) 197 break; 198 if (owner != null && orig.needsContext()) 199 break; 200 owner = rexp.contextDecl(); 201 access = rexp; 202 decl = orig; 203 } 204 } 205 if (decl.ignorable()) 206 new_value.compile (comp, Target.Ignore); 207 else if (decl.isAlias() && isDefining()) 208 { 209 decl.load(this, ReferenceExp.DONT_DEREFERENCE, 210 comp, Target.pushObject); 211 ClassType locType 212 = ClassType.make("gnu.mapping.IndirectableLocation"); 213 code.emitCheckcast(locType); 214 new_value.compile(comp, Target.pushObject); 215 Method meth = locType.getDeclaredMethod("setAlias", 1); 216 code.emitInvokeVirtual(meth); 217 } 218 else if (decl.isIndirectBinding()) 219 { 220 decl.load(access, ReferenceExp.DONT_DEREFERENCE, 221 comp, Target.pushObject); 222 if (isSetIfUnbound()) 223 { 224 if (needValue) 225 { 226 code.emitDup(); 227 valuePushed = true; 228 } 229 code.pushScope(); 230 code.emitDup(); 231 Variable symLoc = code.addLocal(Compilation.typeLocation); 232 code.emitStore(symLoc); 233 code.emitInvokeVirtual(Compilation.typeLocation 234 .getDeclaredMethod("isBound", 0)); 235 code.emitIfIntEqZero(); 236 code.emitLoad(symLoc); 237 } 238 new_value.compile (comp, Target.pushObject); 239 if (needValue && ! isSetIfUnbound()) 240 { 241 code.emitDupX(); 242 valuePushed = true; 243 } 244 String setterName = "set"; 245 code.emitInvokeVirtual(Compilation.typeLocation 246 .getDeclaredMethod(setterName, 1)); 247 if (isSetIfUnbound()) 248 { 249 code.emitFi(); 250 code.popScope(); 251 } 252 } 253 else if (decl.isSimple ()) 254 { 255 type = decl.getType(); 256 new_value.compile(comp, decl); 257 if (needValue) 258 { 259 code.emitDup(type); valuePushed = true; 261 } 262 Variable var = decl.getVariable(); 263 if (var == null) 264 var = decl.allocateVariable(code); 265 code.emitStore(var); 266 } 267 else if (decl.context instanceof ClassExp && decl.field == null 268 && ! getFlag(PROCEDURE) 269 && ((ClassExp) decl.context).isMakingClassPair()) 270 { 271 String setName = ClassExp.slotToMethodName("set", decl.getName()); 272 ClassExp cl = (ClassExp) decl.context; 273 Method setter = cl.type.getDeclaredMethod(setName, 1); 274 cl.loadHeapFrame(comp); 275 new_value.compile(comp, decl); 276 if (needValue) 277 { 278 code.emitDupX(); 279 valuePushed = true; 280 } 281 code.emitInvoke(setter); 282 } 283 else 284 { 285 Field field = decl.field; 286 if (! field.getStaticFlag()) 287 decl.loadOwningObject(owner, comp); 288 type = field.getType(); 289 new_value.compile(comp, decl); 290 if (field.getStaticFlag()) 291 { 292 if (needValue) 293 { 294 code.emitDup(type); 295 valuePushed = true; 296 } 297 code.emitPutStatic(field); 298 } 299 else 300 { 301 if (needValue) 302 { 303 code.emitDupX(); 304 valuePushed = true; 305 } 306 code.emitPutField(field); 307 } 308 } 309 } 310 311 if (needValue && ! valuePushed) 312 throw new Error ("SetExp.compile: not implemented - return value"); 313 314 if (needValue) 315 target.compileFromStack(comp, getType()); 316 else 317 comp.compileConstant(Values.empty, target); 318 } 319 320 public final gnu.bytecode.Type getType() 321 { 322 return ! getHasValue() ? Type.void_type 323 : binding == null ? Type.pointer_type : binding.getType(); 324 } 325 326 protected Expression walk (ExpWalker walker) 327 { 328 return walker.walkSetExp(this); 329 } 330 331 protected void walkChildren (ExpWalker walker) 332 { 333 new_value = (Expression) walker.walk(new_value); 334 } 335 336 public void print (OutPort out) 337 { 338 out.startLogicalBlock(isDefining () ? "(Define" : "(Set", ")", 2); 339 out.writeSpaceFill(); 340 printLineColumn(out); 341 if (binding == null || symbol.toString() != binding.getName()) 342 { 343 out.print('/'); 344 out.print(symbol); 345 } 346 if (binding != null) 347 { 348 out.print('/'); 349 out.print(binding); 350 } 351 out.writeSpaceLinear(); 352 new_value.print(out); 353 out.endLogicalBlock(")"); 354 } 355 356 public String toString() 357 { 358 return "SetExp["+symbol+":="+new_value+']'; 359 } 360 } 361 | Popular Tags |