1 29 30 package com.caucho.quercus.program; 31 32 import com.caucho.quercus.Location; 33 import com.caucho.quercus.env.Env; 34 import com.caucho.quercus.env.NullValue; 35 import com.caucho.quercus.env.Value; 36 import com.caucho.quercus.env.Var; 37 import com.caucho.quercus.expr.Expr; 38 import com.caucho.quercus.expr.ExprFactory; 39 import com.caucho.util.L10N; 40 41 import java.util.ArrayList ; 42 import java.util.HashMap ; 43 import java.util.logging.Logger ; 44 45 48 public class Function extends AbstractFunction { 49 private static final Logger log = Logger.getLogger(Function.class.getName()); 50 private static final L10N L = new L10N(Function.class); 51 52 protected final FunctionInfo _info; 53 protected final boolean _isReturnsReference; 54 55 protected final String _name; 56 protected final Arg []_args; 57 protected final Statement _statement; 58 59 protected boolean _isStatic = true; 60 61 protected boolean _hasReturn; 62 63 Function(Location location, 64 String name, 65 FunctionInfo info, 66 Arg []args, 67 Statement []statements) 68 { 69 super(location); 70 71 _name = name.intern(); 72 _info = info; 73 _info.setFunction(this); 74 _isReturnsReference = info.isReturnsReference(); 75 _args = args; 76 _statement = new BlockStatement(location, statements); 77 78 setGlobal(info.isPageStatic()); 79 } 80 81 public Function(ExprFactory exprFactory, 82 Location location, 83 String name, 84 FunctionInfo info, 85 ArrayList <Arg> argList, 86 ArrayList <Statement> statementList) 87 { 88 super(location); 89 90 _name = name.intern(); 91 _info = info; 92 _info.setFunction(this); 93 _isReturnsReference = info.isReturnsReference(); 94 95 _args = new Arg[argList.size()]; 96 argList.toArray(_args); 97 98 Statement []statements = new Statement[statementList.size()]; 99 statementList.toArray(statements); 100 101 _statement = exprFactory.createBlock(location, statements); 102 103 setGlobal(info.isPageStatic()); 104 } 105 106 109 public String getName() 110 { 111 return _name; 112 } 113 114 117 public Arg []getArgs() 118 { 119 return _args; 120 } 121 122 public void setStatic(boolean isStatic) 123 { 124 _isStatic = isStatic; 125 } 126 127 public boolean isStatic() 128 { 129 return _isStatic; 130 } 131 132 public boolean isObjectMethod() 133 { 134 return false; 135 } 136 137 140 public boolean isReturnsReference() 141 { 142 return _isReturnsReference; 143 } 144 145 public String getClassName() 146 { 147 throw new UnsupportedOperationException (); 148 } 149 150 public Value execute(Env env) 151 { 152 return null; 153 } 154 155 158 @Override 159 public Value []evalArguments(Env env, Expr fun, Expr []args) 160 { 161 Value []values = new Value[args.length]; 162 163 for (int i = 0; i < args.length; i++) { 164 Arg arg = null; 165 166 if (i < _args.length) 167 arg = _args[i]; 168 169 if (arg == null) 170 values[i] = args[i].eval(env).copy(); 171 else if (arg.isReference()) 172 values[i] = args[i].evalRef(env); 173 else { 174 values[i] = args[i].eval(env); 176 } 177 } 178 179 return values; 180 } 181 182 public Value call(Env env, Expr []args) 183 { 184 return callImpl(env, args, false); 185 } 186 187 public Value callCopy(Env env, Expr []args) 188 { 189 return callImpl(env, args, false); 190 } 191 192 public Value callRef(Env env, Expr []args) 193 { 194 return callImpl(env, args, true); 195 } 196 197 private Value callImpl(Env env, Expr []args, boolean isRef) 198 { 199 HashMap <String ,Var> map = new HashMap <String ,Var>(); 200 201 Value []values = new Value[args.length]; 202 203 for (int i = 0; i < args.length; i++) { 204 Arg arg = null; 205 206 if (i < _args.length) { 207 arg = _args[i]; 208 } 209 210 if (arg == null) { 211 values[i] = args[i].eval(env).copy(); 212 } 213 else if (arg.isReference()) { 214 values[i] = args[i].evalRef(env); 215 216 map.put(arg.getName(), values[i].toRefVar()); 217 } 218 else { 219 values[i] = args[i].eval(env); 221 222 Var var = values[i].toVar(); 223 224 map.put(arg.getName(), var); 225 226 values[i] = var.toValue(); 227 } 228 } 229 230 for (int i = args.length; i < _args.length; i++) { 231 Arg arg = _args[i]; 232 233 Expr defaultExpr = arg.getDefault(); 234 235 if (defaultExpr == null) 236 return env.error("expected default expression"); 237 else if (arg.isReference()) 238 map.put(arg.getName(), defaultExpr.evalRef(env).toVar()); 239 else { 240 map.put(arg.getName(), defaultExpr.eval(env).copy().toVar()); 241 } 242 } 243 244 HashMap <String ,Var> oldMap = env.pushEnv(map); 245 Value []oldArgs = env.setFunctionArgs(values); 247 try { 248 Value value = _statement.execute(env); 249 250 if (value == null) 251 return NullValue.NULL; 252 else if (_isReturnsReference && isRef) 253 return value; 254 else 255 return value.copyReturn(); 256 } finally { 257 env.restoreFunctionArgs(oldArgs); 258 env.popEnv(oldMap); 259 } 260 } 261 262 public Value call(Env env, Value []args) 263 { 264 return callImpl(env, args, false); 265 } 266 267 public Value callCopy(Env env, Value []args) 268 { 269 return callImpl(env, args, false); 270 } 271 272 public Value callRef(Env env, Value []args) 273 { 274 return callImpl(env, args, true); 275 } 276 277 private Value callImpl(Env env, Value []args, boolean isRef) 278 { 279 HashMap <String ,Var> map = new HashMap <String ,Var>(); 280 281 for (int i = 0; i < args.length; i++) { 282 Arg arg = null; 283 284 if (i < _args.length) { 285 arg = _args[i]; 286 } 287 288 if (arg == null) { 289 } 290 else if (arg.isReference()) 291 map.put(arg.getName(), args[i].toRefVar()); 292 else { 293 map.put(arg.getName(), args[i].copy().toVar()); 295 } 296 } 297 298 for (int i = args.length; i < _args.length; i++) { 299 Arg arg = _args[i]; 300 301 Expr defaultExpr = arg.getDefault(); 302 303 if (defaultExpr == null) 304 return env.error("expected default expression"); 305 else if (arg.isReference()) 306 map.put(arg.getName(), defaultExpr.evalRef(env).toVar()); 307 else { 308 map.put(arg.getName(), defaultExpr.eval(env).copy().toVar()); 309 } 310 } 311 312 HashMap <String ,Var> oldMap = env.pushEnv(map); 313 Value []oldArgs = env.setFunctionArgs(args); 314 315 try { 316 Value value = _statement.execute(env); 317 318 if (value == null) 319 return NullValue.NULL; 320 else if (_isReturnsReference && isRef) 321 return value; 322 else 323 return value.copyReturn(); 324 } finally { 325 env.restoreFunctionArgs(oldArgs); 326 env.popEnv(oldMap); 327 } 328 } 329 330 private boolean isVariableArgs() 331 { 332 return _info.isVariableArgs() || _args.length > 5; 333 } 334 335 private boolean isVariableMap() 336 { 337 return _info.isUsesSymbolTable() || _info.isVariableVar(); 340 } 341 342 public String toString() 343 { 344 return "Function[" + _name + "]"; 345 } 346 } 347 348 | Popular Tags |