Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move AExpression mutable members into isolated Input/Output objects #53075

Merged
merged 16 commits into from
Mar 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,37 +27,39 @@
*/
public enum Operation {

MUL ( "*" ),
DIV ( "/" ),
REM ( "%" ),
ADD ( "+" ),
SUB ( "-" ),
FIND ( "=~" ),
MATCH ( "==~" ),
LSH ( "<<" ),
RSH ( ">>" ),
USH ( ">>>" ),
BWNOT ( "~" ),
BWAND ( "&" ),
XOR ( "^" ),
BWOR ( "|" ),
NOT ( "!" ),
AND ( "&&" ),
OR ( "||" ),
LT ( "<" ),
LTE ( "<=" ),
GT ( ">" ),
GTE ( ">=" ),
EQ ( "==" ),
EQR ( "===" ),
NE ( "!=" ),
NER ( "!==" ),
INCR ( "++" ),
DECR ( "--" );
MUL ( "*" , "multiplication" ),
DIV ( "/" , "division" ),
REM ( "%" , "remainder" ),
ADD ( "+" , "addition" ),
SUB ( "-" , "subtraction" ),
FIND ( "=~" , "find" ),
MATCH ( "==~" , "match" ),
LSH ( "<<" , "left shift" ),
RSH ( ">>" , "right shift" ),
USH ( ">>>" , "unsigned shift" ),
BWNOT ( "~" , "bitwise not" ),
BWAND ( "&" , "bitwise and" ),
XOR ( "^" , "bitwise xor" ),
BWOR ( "|" , "boolean or" ),
NOT ( "!" , "boolean not" ),
AND ( "&&" , "boolean and" ),
OR ( "||" , "boolean or" ),
LT ( "<" , "less than" ),
LTE ( "<=" , "less than or equals" ),
GT ( ">" , "greater than" ),
GTE ( ">=" , "greater than or equals" ),
EQ ( "==" , "equals" ),
EQR ( "===" , "reference equals" ),
NE ( "!=" , "not equals" ),
NER ( "!==" , "reference not equals" ),
INCR ( "++" , "increment" ),
DECR ( "--" , "decrement" );

public final String symbol;
public final String name;

Operation(final String symbol) {
Operation(final String symbol, final String name) {
this.symbol = symbol;
this.name = name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,52 @@
*/
public abstract class AExpression extends ANode {

public static class Input {

/**
* Set to false when an expression will not be read from such as
* a basic assignment. Note this variable is always set by the parent
* as input.
*/
boolean read = true;

/**
* Set to the expected type this node needs to be. Note this variable
* is always set by the parent as input and should never be read from.
*/
Class<?> expected = null;

/**
* Set by {@link EExplicit} if a cast made on an expression node should be
* explicit.
*/
boolean explicit = false;

/**
* Set to true if a cast is allowed to boxed/unboxed. This is used
* for method arguments because casting may be required.
*/
boolean internal = false;
}

public static class Output {

/**
* Set to true when an expression can be considered a stand alone
* statement. Used to prevent extraneous bytecode. This is always
* set by the node as output.
*/
boolean statement = false;

/**
* Set to the actual type this node is. Note this variable is always
* set by the node as output and should only be read from outside of the
* node itself. <b>Also, actual can always be read after a cast is
* called on this node to get the type of the node after the cast.</b>
*/
Class<?> actual = null;
}

/**
* Prefix is the predecessor to this node in a variable chain.
* This is used to analyze and write variable chains in a
Expand All @@ -44,50 +90,13 @@ public abstract class AExpression extends ANode {
*/
AExpression prefix;

/**
* Set to false when an expression will not be read from such as
* a basic assignment. Note this variable is always set by the parent
* as input.
*/
boolean read = true;

/**
* Set to true when an expression can be considered a stand alone
* statement. Used to prevent extraneous bytecode. This is always
* set by the node as output.
*/
boolean statement = false;

/**
* Set to the expected type this node needs to be. Note this variable
* is always set by the parent as input and should never be read from.
*/
Class<?> expected = null;

/**
* Set to the actual type this node is. Note this variable is always
* set by the node as output and should only be read from outside of the
* node itself. <b>Also, actual can always be read after a cast is
* called on this node to get the type of the node after the cast.</b>
*/
Class<?> actual = null;

/**
* Set by {@link EExplicit} if a cast made on an expression node should be
* explicit.
*/
boolean explicit = false;

/**
* Set to true if a cast is allowed to boxed/unboxed. This is used
* for method arguments because casting may be required.
*/
boolean internal = false;

// This is used to support the transition from a mutable to immutable state.
// TODO: remove placeholders once analysis and write are combined into build
// This are used to support the transition from a mutable to immutable state.
// Currently, the IR tree is built during the user tree "write" phase, so
// this is stored on the node to set during the "semantic" phase and then
// these are stored on the node to set during the "semantic" phase and then
// use during the "write" phase.
Input input = null;
Output output = null;
PainlessCast cast = null;

/**
Expand All @@ -111,15 +120,17 @@ public abstract class AExpression extends ANode {
/**
* Checks for errors and collects data for the writing phase.
*/
abstract void analyze(ScriptRoot scriptRoot, Scope scope);
Output analyze(ScriptRoot scriptRoot, Scope scope, Input input) {
throw new UnsupportedOperationException();
}

/**
* Writes ASM based on the data collected during the analysis phase.
*/
abstract ExpressionNode write(ClassNode classNode);

void cast() {
cast = AnalyzerCaster.getLegalCast(location, actual, expected, explicit, internal);
cast = AnalyzerCaster.getLegalCast(location, output.actual, input.expected, input.explicit, input.internal);
}

ExpressionNode cast(ExpressionNode expressionNode) {
Expand All @@ -129,7 +140,7 @@ ExpressionNode cast(ExpressionNode expressionNode) {

CastNode castNode = new CastNode();
castNode.setLocation(location);
castNode.setExpressionType(expected);
castNode.setExpressionType(cast.targetType);
castNode.setCast(cast);
castNode.setChildNode(expressionNode);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
package org.elasticsearch.painless.node;

import org.elasticsearch.painless.Location;
import org.elasticsearch.painless.Scope;
import org.elasticsearch.painless.symbol.ScriptRoot;

import java.util.Objects;

Expand All @@ -28,11 +30,14 @@
*/
abstract class AStoreable extends AExpression {

/**
* Set to true when this node is an lhs-expression and will be storing
* a value from an rhs-expression.
*/
boolean write = false;
public static class Input extends AExpression.Input {

/**
* Set to true when this node is an lhs-expression and will be storing
* a value from an rhs-expression.
*/
boolean write = false;
}

/**
* Standard constructor with location used for error tracking.
Expand All @@ -52,6 +57,10 @@ abstract class AStoreable extends AExpression {
this.prefix = Objects.requireNonNull(prefix);
}

Output analyze(ScriptRoot scriptRoot, Scope scope, Input input) {
throw new UnsupportedOperationException();
}

/**
* Returns true if this node or a sub-node of this node can be optimized with
* rhs actual type to avoid an unnecessary cast.
Expand Down
Loading