/*
* Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.quercus.expr;
import com.caucho.quercus.Location;
import com.caucho.quercus.env.*;
import com.caucho.quercus.parser.QuercusParser;
import com.caucho.quercus.statement.Statement;
import com.caucho.util.L10N;
import java.io.IOException;
/**
* Represents a PHP expression.
*/
abstract public class Expr {
private static final L10N L = new L10N(Expr.class);
public static final int COMPILE_ARG_MAX = 5;
private final Location _location;
public Expr(Location location)
{
_location = location;
}
public Expr()
{
_location = Location.UNKNOWN;
}
/**
* Returns the location.
*/
final public Location getLocation()
{
return _location;
}
/**
* Returns the filename.
*/
public String getFileName()
{
if (_location != Location.UNKNOWN)
return _location.getFileName();
else
return null;
}
/**
* Returns the line number in the file.
*/
public int getLine()
{
return _location.getLineNumber();
}
/**
* Returns the function name.
*/
public String getFunctionLocation()
{
return "";
}
/**
* Returns the file name and line number, if location is known.
*/
public String getLocationLine()
{
if (_location != Location.UNKNOWN)
return _location.getFileName() + ":" + getLine() + ": ";
else
return "";
}
/**
* Returns true for a reference.
*/
public boolean isRef()
{
return false;
}
/**
* Returns true for a constant expression.
*/
public boolean isConstant()
{
return isLiteral();
}
/**
* Returns true for a literal expression.
*/
public boolean isLiteral()
{
return false;
}
/**
* Returns true if a static true value.
*/
public boolean isTrue()
{
return false;
}
/**
* Returns true if a static false value.
*/
public boolean isFalse()
{
return false;
}
/*
* Returns true if this is an assign expr.
*/
public boolean isAssign()
{
return false;
}
/**
* Returns true for an expression that can be read (only $a[] uses this)
*/
public boolean canRead()
{
return true;
}
public Expr createAssign(QuercusParser parser, Expr value)
throws IOException
{
String msg = (L.l("{0} is an invalid left-hand side of an assignment.",
this));
if (parser != null)
throw parser.error(msg);
else
throw new IOException(msg);
}
/**
* Mark as an assignment for a list()
*/
public void assign(QuercusParser parser)
throws IOException
{
String msg = L.l("{0} is an invalid left-hand side of an assignment.",
this);
if (parser != null)
throw parser.error(msg);
else
throw new IOException(msg);
}
public Expr createAssignRef(QuercusParser parser, Expr value)
throws IOException
{
// XXX: need real exception
String msg = L.l("{0} is an invalid left-hand side of an assignment.",
this);
if (parser != null)
throw parser.error(msg);
else
throw new IOException(msg);
}
/**
* Creates a reference.
* @param location
*/
public Expr createRef(QuercusParser parser)
throws IOException
{
return this;
}
public Expr createDeref(ExprFactory factory)
throws IOException
{
return this;
}
/**
* Creates a assignment
* @param location
*/
public Expr createCopy(ExprFactory factory)
{
return this;
}
/**
* Copy for things like $a .= "test";
* @param location
*/
/*
public Expr copy()
{
return this;
}
*/
/**
* Creates a field ref
*/
public Expr createFieldGet(ExprFactory factory,
Location location,
StringValue name)
{
return factory.createFieldGet(location, this, name);
}
/**
* Creates a field ref
*/
public Expr createFieldGet(ExprFactory factory,
Location location,
Expr name)
{
return factory.createFieldVarGet(location, this, name);
}
/**
* Creates a assignment
*/
public Statement createUnset(ExprFactory factory, Location location)
throws IOException
{
throw new IOException(L.l("{0} is an illegal value to unset",
this));
}
/**
* Creates an isset expression
*/
public Expr createIsset(ExprFactory factory)
throws IOException
{
throw new IOException(L.l("{0} is an illegal value to isset",
this));
}
/**
* Returns true if the expression evaluates to a boolean.
*/
public boolean isBoolean()
{
return false;
}
/**
* Returns true if the expression evaluates to a long.
*/
public boolean isLong()
{
return false;
}
/**
* Returns true if the expression evaluates to a double.
*/
public boolean isDouble()
{
return false;
}
/**
* Returns true if the expression evaluates to a number.
*/
public boolean isNumber()
{
return isLong() || isDouble();
}
/**
* Returns true if the expression evaluates to a string.
*/
public boolean isString()
{
return false;
}
/**
* Returns true if the expression evaluates to an array.
*/
public boolean isArray()
{
return false;
}
/**
* Evaluates the expression as a constant.
*
* @return the expression value.
*/
public Value evalConstant()
{
throw new IllegalStateException(L.l("{0} is not a constant expression", this));
}
/**
* Evaluates the expression.
*
* @param env the calling environment.
*
* @return the expression value.
*/
abstract public Value eval(Env env);
/**
* Evaluates the expression, with the object expected to be modified,
* e.g. from an unset.
*
* @param env the calling environment.
*
* @return the expression value.
*/
public Value evalDirty(Env env)
{
return eval(env);
}
/**
* Evaluates the expression, creating an array for unassigned values.
*
* @param env the calling environment.
*
* @return the expression value.
*/
public Value evalArray(Env env)
{
return eval(env);
}
/**
* Evaluates the expression, creating an object for unassigned values.
*
* @param env the calling environment.
*
* @return the expression value.
*/
public Value evalObject(Env env)
{
return eval(env);
}
/**
* Evaluates the expression as a reference.
*
* @param env the calling environment.
*
* @return the expression value.
*/
public Value evalRef(Env env)
{
return eval(env);
}
/**
* Evaluates the expression as a copy
*
* @param env the calling environment.
*
* @return the expression value.
*/
public Value evalCopy(Env env)
{
return eval(env);
}
/**
* Evaluates the expression as a function argument where it is unknown
* if the value is a reference.
*
* @param env the calling environment.
* @param isTail true for the top expression
*
* @return the expression value.
*/
public Value evalArg(Env env, boolean isTop)
{
return eval(env);
}
/**
* Needed to handle list.
*/
public void evalAssign(Env env, Value value)
{
throw new RuntimeException(L.l("{0} is an invalid left-hand side of an assignment.",
this));
}
/**
* Handles post increments.
*/
public Value evalPostIncrement(Env env, int incr)
{
Value value = evalRef(env);
return value.postincr(incr);
}
/**
* Handles post increments.
*/
public Value evalPreIncrement(Env env, int incr)
{
Value value = evalRef(env);
return value.preincr(incr);
}
/**
* Evaluates the expression as a string
*
* @param env the calling environment.
*
* @return the expression value.
*/
public String evalString(Env env)
{
Value value = eval(env);
if (value.isObject())
return value.toReprString(env).toString();
else
return value.toString();
}
/**
* Evaluates the expression as a string value
*
* @param env the calling environment.
*
* @return the expression value.
*/
public StringValue evalStringValue(Env env)
{
return eval(env).toStringValue(env);
}
/**
* Evaluates the expression as a string
*
* @param env the calling environment.
*
* @return the expression value.
*/
public char evalChar(Env env)
{
return eval(env).toChar();
}
/**
* Evaluates the expression as a boolean.
*
* @param env the calling environment.
*
* @return the expression value.
*/
public boolean evalBoolean(Env env)
{
return eval(env).toBoolean();
}
/**
* Evaluates the expression as a long
*
* @param env the calling environment.
*
* @return the expression value.
*/
public long evalLong(Env env)
{
return eval(env).toLong();
}
/**
* Evaluates the expression as a double
*
* @param env the calling environment.
*
* @return the expression value.
*/
public double evalDouble(Env env)
{
return eval(env).toDouble();
}
/**
* Prints to the output as an echo.
*/
public void print(Env env)
throws IOException
{
eval(env).print(env);
}
public String toString()
{
return "Expr[]";
}
}