/**
* Copyright 2015 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DEVTOOLS_CDBG_DEBUGLETS_JAVA_JAVA_EXPRESSION_H_
#define DEVTOOLS_CDBG_DEBUGLETS_JAVA_JAVA_EXPRESSION_H_
#include
#include
#include "common.h"
#include "expression_util.h"
namespace devtools {
namespace cdbg {
class ExpressionEvaluator;
struct FormatMessageModel;
// Interface representing a node in parsed expression tree.
class JavaExpression {
public:
virtual ~JavaExpression() { }
// Prints the expression subtree to the stream. When "concise" is true, the
// function prints expression in Java format. When "concise" is false, a
// much more verbose format is used (this mode is used by unit test to
// disambiguate different types of expressions that might look the same in
// concise format).
virtual void Print(std::ostream* os, bool concise) = 0;
// Tries to convert the expression subtree into a type name. For
// example: Member("String", Member("lang", Identifier("java")) can be
// converted to "java.lang.String". At the same time (a+b) cannot.
virtual bool TryGetTypeName(string* name) const = 0;
// Compiles the expression into executable format. The caller owns the
// returned instance. If a particular language feature is not yet supported,
// the function returns null and prints description in "error_message".
virtual CompiledExpression CreateEvaluator() = 0;
};
// Represents (a ? b : c) conditional expression.
class ConditionalJavaExpression : public JavaExpression {
public:
// Takes ownership over the passed instances of "JavaExpression";
ConditionalJavaExpression(
JavaExpression* condition,
JavaExpression* if_true,
JavaExpression* if_false);
void Print(std::ostream* os, bool concise) override;
bool TryGetTypeName(string* name) const override { return false; }
CompiledExpression CreateEvaluator() override;
private:
std::unique_ptr condition_;
std::unique_ptr if_true_;
std::unique_ptr if_false_;
DISALLOW_COPY_AND_ASSIGN(ConditionalJavaExpression);
};
// Represents any kind of binary expression (like a + b).
class BinaryJavaExpression : public JavaExpression {
public:
enum class Type {
add,
sub,
mul,
div,
mod,
conditional_and,
conditional_or,
eq,
ne,
le,
ge,
lt,
gt,
bitwise_and,
bitwise_or,
bitwise_xor,
shl,
shr_s,
shr_u
};
// Takes ownership over "a" and "b" expression subtrees.
BinaryJavaExpression(Type type, JavaExpression* a, JavaExpression* b);
void Print(std::ostream* os, bool concise) override;
bool TryGetTypeName(string* name) const override { return false; }
CompiledExpression CreateEvaluator() override;
private:
const Type type_;
std::unique_ptr a_;
std::unique_ptr b_;
DISALLOW_COPY_AND_ASSIGN(BinaryJavaExpression);
};
// Represents unary expression (like ~a).
class UnaryJavaExpression : public JavaExpression {
public:
enum class Type {
plus,
minus,
bitwise_complement,
logical_complement
};
// Takes ownership over "a" expression subtree.
UnaryJavaExpression(Type type, JavaExpression* a);
void Print(std::ostream* os, bool concise) override;
bool TryGetTypeName(string* name) const override { return false; }
CompiledExpression CreateEvaluator() override;
private:
const Type type_;
std::unique_ptr a_;
DISALLOW_COPY_AND_ASSIGN(UnaryJavaExpression);
};
class JavaIntLiteral : public JavaExpression {
public:
JavaIntLiteral() : is_long_(false) { }
// Parses an integer in the given base from the given string.
bool ParseString(const string& str, int base);
void Print(std::ostream* os, bool concise) override;
bool TryGetTypeName(string* name) const override { return false; }
CompiledExpression CreateEvaluator() override;
private:
// Returns true if this is a long integer.
bool IsLong() const { return is_long_; }
private:
// Indicates whether this is an int or a long.
bool is_long_;
jlong n_;
DISALLOW_COPY_AND_ASSIGN(JavaIntLiteral);
};
class JavaFloatLiteral : public JavaExpression {
public:
JavaFloatLiteral() : is_double_(true) { }
// Parses a floating point number from the given string.
bool ParseString(const string& str);
void Print(std::ostream* os, bool concise) override;
bool TryGetTypeName(string* name) const override { return false; }
CompiledExpression CreateEvaluator() override;
// Returns true if this is a double.
bool IsDouble() const { return is_double_; }
private:
// Indicates whether this is an float or a double.
bool is_double_;
jdouble d_;
DISALLOW_COPY_AND_ASSIGN(JavaFloatLiteral);
};
// Represents character constant. All characters in Java are Unicode, so
// this is a 16 bit integer.
class JavaCharLiteral : public JavaExpression {
public:
JavaCharLiteral() : ch_('\0') { }
// Decodes the potentially escaped character into a Unicode character.
// Examples for encoding are: '\n', '\\', '\293', '\u5C7f'.
bool ParseString(const string& str);
void Print(std::ostream* os, bool concise) override;
bool TryGetTypeName(string* name) const override { return false; }
CompiledExpression CreateEvaluator() override;
private:
jchar ch_;
DISALLOW_COPY_AND_ASSIGN(JavaCharLiteral);
};
// Represents a Java string constant.
class JavaStringLiteral : public JavaExpression {
public:
JavaStringLiteral() { }
// Decodes the potentially escaped characters sequence into Java string.
// Example of encoded string: "This\n is\t an\" \u1E3B encoded \88 string".
bool ParseString(const string& str);
void Print(std::ostream* os, bool concise) override;
bool TryGetTypeName(string* name) const override { return false; }
CompiledExpression CreateEvaluator() override;
private:
std::vector str_;
DISALLOW_COPY_AND_ASSIGN(JavaStringLiteral);
};
// Represents a boolean constant.
class JavaBooleanLiteral : public JavaExpression {
public:
explicit JavaBooleanLiteral(jboolean n) : n_(n) { }
void Print(std::ostream* os, bool concise) override;
bool TryGetTypeName(string* name) const override { return false; }
CompiledExpression CreateEvaluator() override;
private:
const jboolean n_;
DISALLOW_COPY_AND_ASSIGN(JavaBooleanLiteral);
};
// Represents Java "null".
class JavaNullLiteral : public JavaExpression {
public:
JavaNullLiteral() { }
void Print(std::ostream* os, bool concise) override;
bool TryGetTypeName(string* name) const override { return false; }
CompiledExpression CreateEvaluator() override;
private:
DISALLOW_COPY_AND_ASSIGN(JavaNullLiteral);
};
// Represents a local or a static variable.
class JavaIdentifier : public JavaExpression {
public:
explicit JavaIdentifier(string identifier)
: identifier_(identifier) {
}
void Print(std::ostream* os, bool concise) override;
bool TryGetTypeName(string* name) const override;
CompiledExpression CreateEvaluator() override;
private:
const string identifier_;
DISALLOW_COPY_AND_ASSIGN(JavaIdentifier);
};
// Represents a type cast for classes or interfaces.
class TypeCastJavaExpression : public JavaExpression {
public:
explicit TypeCastJavaExpression(string type, JavaExpression* source)
: type_(type),
source_(std::unique_ptr(source)) {
}
void Print(std::ostream* os, bool concise) override;
bool TryGetTypeName(string* name) const override { return false; }
CompiledExpression CreateEvaluator() override;
private:
const string type_;
std::unique_ptr source_;
DISALLOW_COPY_AND_ASSIGN(TypeCastJavaExpression);
};
// Base class representing additional transformation applied to an object. Two
// types of selectors are currently supported:
// 1. Array indexer: a[8].
// 2. Dereferencing a member: a.member.
class JavaExpressionSelector : public JavaExpression {
public:
// Setter for "source_". See "source_" comments for explanation. Takes
// ownership over the "source" expression subtree.
void set_source(JavaExpression* source) {
source_.reset(source);
}
protected:
// Represents the base expression on which the selector is applied. In the
// two examples above, "source_" will be "a". A more complicated example:
// (flag ? a1 : a2)[8]
// In this case "source_" will be the expression corresponding to
// "flag ? a1 : a2".
std::unique_ptr source_;
};
// Selector for array item. The index is also expression to support
// constructions like a[x + y].
class JavaExpressionIndexSelector : public JavaExpressionSelector {
public:
// Takes ownership over the "index" expression subtree.
explicit JavaExpressionIndexSelector(JavaExpression* index) : index_(index) {
}
void Print(std::ostream* os, bool concise) override;
bool TryGetTypeName(string* name) const override { return false; }
CompiledExpression CreateEvaluator() override;
private:
std::unique_ptr index_;
DISALLOW_COPY_AND_ASSIGN(JavaExpressionIndexSelector);
};
// Selector for a class member.
class JavaExpressionMemberSelector : public JavaExpressionSelector {
public:
explicit JavaExpressionMemberSelector(const string& member)
: member_(member) {
}
void Print(std::ostream* os, bool concise) override;
bool TryGetTypeName(string* name) const override;
CompiledExpression CreateEvaluator() override;
private:
const string member_;
DISALLOW_COPY_AND_ASSIGN(JavaExpressionMemberSelector);
};
// List of arguments for method invocation.
class MethodArguments {
public:
// Empty arguments list.
MethodArguments() {}
// Single argument. Takes ownership over "argument".
MethodArguments(JavaExpression* argument, MethodArguments* tail) {
if (tail) {
arguments_.swap(tail->arguments_);
delete tail;
}
arguments_.push_front(std::unique_ptr(argument));
}
std::list<:unique_ptr>>::iterator begin() {
return arguments_.begin();
}
std::list<:unique_ptr>>::iterator end() {
return arguments_.end();
}
private:
std::list<:unique_ptr>> arguments_;
DISALLOW_COPY_AND_ASSIGN(MethodArguments);
};
// Represents method call (with arguments). The method call can be either
// direct like f(1) or through selectors like my.util.f(1) or a.getY().f(1).
// In case of direct method call, "source_" will be null.
class MethodCallExpression : public JavaExpressionSelector {
public:
// Takes ownership over "method" and "arguments".
MethodCallExpression(const string& method, MethodArguments* arguments)
: method_(method),
arguments_(std::unique_ptr(arguments)) {
}
void Print(std::ostream* os, bool concise) override;
bool TryGetTypeName(string* name) const override { return false; }
CompiledExpression CreateEvaluator() override;
private:
const string method_;
std::unique_ptr arguments_;
DISALLOW_COPY_AND_ASSIGN(MethodCallExpression);
};
} // namespace cdbg
} // namespace devtools
#endif // DEVTOOLS_CDBG_DEBUGLETS_JAVA_JAVA_EXPRESSION_H_