From e3aab1295e429f99139dab3a2c8c67f03c0a4226 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Fri, 4 Oct 2019 08:36:44 -0700 Subject: [PATCH] Add a ScriptRoot to consolidate global data necessary for multiple passes (#47532) This PR is to get plumbing in for a ScriptRoot class that will consolidate several pieces of state required by potentially multiple passes including PainlessLookup, CompilerSettings, FunctionTable, the root class node, and a synthetic counter. It's possible more may be added to this as we move forward and slowly make the the nodes have less mutable state. --- .../org/elasticsearch/painless/Locals.java | 49 +----- .../elasticsearch/painless/ScriptRoot.java | 75 +++++++++ .../painless/node/AExpression.java | 10 +- .../elasticsearch/painless/node/ANode.java | 4 +- .../painless/node/EAssignment.java | 29 ++-- .../elasticsearch/painless/node/EBinary.java | 150 +++++++++--------- .../elasticsearch/painless/node/EBool.java | 12 +- .../elasticsearch/painless/node/EBoolean.java | 4 +- .../painless/node/ECallLocal.java | 21 +-- .../painless/node/ECapturingFunctionRef.java | 6 +- .../elasticsearch/painless/node/ECast.java | 4 +- .../elasticsearch/painless/node/EComp.java | 100 ++++++------ .../painless/node/EConditional.java | 16 +- .../painless/node/EConstant.java | 4 +- .../elasticsearch/painless/node/EDecimal.java | 4 +- .../elasticsearch/painless/node/EElvis.java | 12 +- .../painless/node/EExplicit.java | 14 +- .../painless/node/EFunctionRef.java | 6 +- .../painless/node/EInstanceof.java | 11 +- .../elasticsearch/painless/node/ELambda.java | 21 +-- .../painless/node/EListInit.java | 12 +- .../elasticsearch/painless/node/EMapInit.java | 16 +- .../painless/node/ENewArray.java | 10 +- .../painless/node/ENewArrayFunctionRef.java | 16 +- .../elasticsearch/painless/node/ENewObj.java | 12 +- .../elasticsearch/painless/node/ENull.java | 4 +- .../elasticsearch/painless/node/ENumeric.java | 4 +- .../elasticsearch/painless/node/ERegex.java | 4 +- .../elasticsearch/painless/node/EStatic.java | 6 +- .../elasticsearch/painless/node/EString.java | 4 +- .../elasticsearch/painless/node/EUnary.java | 36 ++--- .../painless/node/EVariable.java | 4 +- .../elasticsearch/painless/node/PBrace.java | 10 +- .../painless/node/PCallInvoke.java | 12 +- .../elasticsearch/painless/node/PField.java | 20 +-- .../painless/node/PSubArrayLength.java | 4 +- .../painless/node/PSubBrace.java | 8 +- .../painless/node/PSubCallInvoke.java | 8 +- .../painless/node/PSubDefArray.java | 8 +- .../painless/node/PSubDefCall.java | 8 +- .../painless/node/PSubDefField.java | 4 +- .../painless/node/PSubField.java | 4 +- .../painless/node/PSubListShortcut.java | 12 +- .../painless/node/PSubMapShortcut.java | 12 +- .../painless/node/PSubNullSafeCallInvoke.java | 6 +- .../painless/node/PSubNullSafeField.java | 6 +- .../painless/node/PSubShortcut.java | 4 +- .../elasticsearch/painless/node/SBlock.java | 7 +- .../elasticsearch/painless/node/SBreak.java | 4 +- .../elasticsearch/painless/node/SCatch.java | 9 +- .../elasticsearch/painless/node/SClass.java | 22 +-- .../painless/node/SContinue.java | 4 +- .../painless/node/SDeclBlock.java | 6 +- .../painless/node/SDeclaration.java | 10 +- .../org/elasticsearch/painless/node/SDo.java | 11 +- .../elasticsearch/painless/node/SEach.java | 14 +- .../painless/node/SExpression.java | 8 +- .../org/elasticsearch/painless/node/SFor.java | 20 +-- .../painless/node/SFunction.java | 6 +- .../org/elasticsearch/painless/node/SIf.java | 10 +- .../elasticsearch/painless/node/SIfElse.java | 12 +- .../elasticsearch/painless/node/SReturn.java | 8 +- .../painless/node/SSubEachArray.java | 4 +- .../painless/node/SSubEachIterable.java | 6 +- .../elasticsearch/painless/node/SThrow.java | 8 +- .../org/elasticsearch/painless/node/STry.java | 8 +- .../elasticsearch/painless/node/SWhile.java | 10 +- .../painless/DefOptimizationTests.java | 4 +- .../elasticsearch/painless/FunctionTests.java | 2 +- 69 files changed, 520 insertions(+), 479 deletions(-) create mode 100644 modules/lang-painless/src/main/java/org/elasticsearch/painless/ScriptRoot.java diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Locals.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Locals.java index 728b107b15f..99edb10fa24 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Locals.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Locals.java @@ -20,7 +20,6 @@ package org.elasticsearch.painless; import org.elasticsearch.painless.ScriptClassInfo.MethodArgument; -import org.elasticsearch.painless.lookup.PainlessLookup; import org.elasticsearch.painless.lookup.PainlessLookupUtility; import java.util.Arrays; @@ -38,19 +37,6 @@ import static org.elasticsearch.painless.lookup.PainlessLookupUtility.typeToJava * Tracks user defined variables across compilation phases. */ public final class Locals { - private int syntheticCounter = 0; - - /** - * Returns a unique identifier for generating the name of a synthetic method. - */ - public String getNextSyntheticName() { - Locals locals = this; - while (locals.getParent() != null) { - locals = locals.getParent(); - } - - return "lambda$" + locals.syntheticCounter++; - } /** Reserved word: loop counter */ public static final String LOOP = "#loop"; @@ -64,9 +50,7 @@ public final class Locals { /** Creates a new local variable scope (e.g. loop) inside the current scope */ public static Locals newLocalScope(Locals currentScope) { - Locals locals = new Locals(currentScope); - - return locals; + return new Locals(currentScope); } /** @@ -76,7 +60,7 @@ public final class Locals { */ public static Locals newLambdaScope(Locals programScope, String name, Class returnType, List parameters, int captureCount, int maxLoopCounter) { - Locals locals = new Locals(programScope, programScope.painlessLookup, programScope.baseClass, returnType, KEYWORDS); + Locals locals = new Locals(programScope, returnType, KEYWORDS); List> typeParameters = parameters.stream().map(parameter -> typeToJavaType(parameter.clazz)).collect(Collectors.toList()); for (int i = 0; i < parameters.size(); i++) { Parameter parameter = parameters.get(i); @@ -96,7 +80,7 @@ public final class Locals { /** Creates a new function scope inside the current scope */ public static Locals newFunctionScope(Locals programScope, Class returnType, List parameters, int maxLoopCounter) { - Locals locals = new Locals(programScope, programScope.painlessLookup, programScope.baseClass, returnType, KEYWORDS); + Locals locals = new Locals(programScope, returnType, KEYWORDS); for (Parameter parameter : parameters) { locals.addVariable(parameter.location, parameter.clazz, parameter.name, false); } @@ -109,8 +93,7 @@ public final class Locals { /** Creates a new main method scope */ public static Locals newMainMethodScope(ScriptClassInfo scriptClassInfo, Locals programScope, int maxLoopCounter) { - Locals locals = new Locals(programScope, programScope.painlessLookup, - scriptClassInfo.getBaseClass(), scriptClassInfo.getExecuteMethodReturnType(), KEYWORDS); + Locals locals = new Locals(programScope, scriptClassInfo.getExecuteMethodReturnType(), KEYWORDS); // This reference. Internal use only. locals.defineVariable(null, Object.class, THIS, true); @@ -127,8 +110,8 @@ public final class Locals { } /** Creates a new program scope as the root of all scopes */ - public static Locals newProgramScope(ScriptClassInfo scriptClassInfo, PainlessLookup painlessLookup) { - return new Locals(null, painlessLookup, scriptClassInfo.getBaseClass(), null, null); + public static Locals newProgramScope() { + return new Locals(null, null, null); } /** Checks if a variable exists or not, in this scope or any parents. */ @@ -180,22 +163,8 @@ public final class Locals { return locals; } - /** Whitelist against which this script is being compiled. */ - public PainlessLookup getPainlessLookup() { - return painlessLookup; - } - - /** Base class for the compiled script. */ - public Class getBaseClass() { - return baseClass; - } - ///// private impl - /** Whitelist against which this script is being compiled. */ - private final PainlessLookup painlessLookup; - /** Base class for the compiled script. */ - private final Class baseClass; // parent scope private final Locals parent; // return type of this scope @@ -211,16 +180,14 @@ public final class Locals { * Create a new Locals */ private Locals(Locals parent) { - this(parent, parent.painlessLookup, parent.baseClass, parent.returnType, parent.keywords); + this(parent, parent.returnType, parent.keywords); } /** * Create a new Locals with specified return type */ - private Locals(Locals parent, PainlessLookup painlessLookup, Class baseClass, Class returnType, Set keywords) { + private Locals(Locals parent, Class returnType, Set keywords) { this.parent = parent; - this.painlessLookup = painlessLookup; - this.baseClass = baseClass; this.returnType = returnType; this.keywords = keywords; if (parent == null) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/ScriptRoot.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/ScriptRoot.java new file mode 100644 index 00000000000..72d5e50a8a6 --- /dev/null +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/ScriptRoot.java @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you 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. + */ + +package org.elasticsearch.painless; + +import org.elasticsearch.painless.lookup.PainlessLookup; +import org.elasticsearch.painless.node.SClass; +import org.elasticsearch.painless.symbol.FunctionTable; + +import java.util.Objects; + +/** + * Stores information for use across the entirety of compilation. + */ +public class ScriptRoot { + + protected final PainlessLookup painlessLookup; + protected final CompilerSettings compilerSettings; + protected final ScriptClassInfo scriptClassInfo; + + protected final SClass classNode; + + protected final FunctionTable functionTable = new FunctionTable(); + protected int syntheticCounter = 0; + + public ScriptRoot(PainlessLookup painlessLookup, CompilerSettings compilerSettings, ScriptClassInfo scriptClassInfo, SClass classRoot) { + this.painlessLookup = Objects.requireNonNull(painlessLookup); + this.compilerSettings = Objects.requireNonNull(compilerSettings); + this.scriptClassInfo = Objects.requireNonNull(scriptClassInfo); + this.classNode = Objects.requireNonNull(classRoot); + } + + public PainlessLookup getPainlessLookup() { + return painlessLookup; + } + + public CompilerSettings getCompilerSettings() { + return compilerSettings; + } + + public ScriptClassInfo getScriptClassInfo() { + return scriptClassInfo; + } + + public SClass getClassNode() { + return classNode; + } + + public FunctionTable getFunctionTable() { + return functionTable; + } + + /** + * Returns a unique identifier for generating the name of a synthetic value. + */ + public String getNextSyntheticName(String prefix) { + return prefix + "$synthetic$" + syntheticCounter++; + } +} diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/AExpression.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/AExpression.java index 6ed655bff50..dd9abfbfd65 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/AExpression.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/AExpression.java @@ -24,7 +24,7 @@ import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.lookup.PainlessCast; import org.elasticsearch.painless.lookup.PainlessLookupUtility; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; @@ -118,7 +118,7 @@ public abstract class AExpression extends ANode { * nodes with the constant variable set to a non-null value with {@link EConstant}. * @return The new child node for the parent node calling this method. */ - AExpression cast(FunctionTable functions, Locals locals) { + AExpression cast(ScriptRoot scriptRoot, Locals locals) { PainlessCast cast = AnalyzerCaster.getLegalCast(location, actual, expected, explicit, internal); if (cast == null) { @@ -136,7 +136,7 @@ public abstract class AExpression extends ANode { // will already be the same. EConstant econstant = new EConstant(location, constant); - econstant.analyze(functions, locals); + econstant.analyze(scriptRoot, locals); if (!expected.equals(econstant.actual)) { throw createError(new IllegalStateException("Illegal tree structure.")); @@ -170,7 +170,7 @@ public abstract class AExpression extends ANode { constant = AnalyzerCaster.constCast(location, constant, cast); EConstant econstant = new EConstant(location, constant); - econstant.analyze(functions, locals); + econstant.analyze(scriptRoot, locals); if (!expected.equals(econstant.actual)) { throw createError(new IllegalStateException("Illegal tree structure.")); @@ -201,7 +201,7 @@ public abstract class AExpression extends ANode { // the EConstant will already be the same. EConstant econstant = new EConstant(location, constant); - econstant.analyze(functions, locals); + econstant.analyze(scriptRoot, locals); if (!actual.equals(econstant.actual)) { throw createError(new IllegalStateException("Illegal tree structure.")); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ANode.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ANode.java index 087b906e9fe..ca821cf05f8 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ANode.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ANode.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.ArrayList; import java.util.Arrays; @@ -72,7 +72,7 @@ public abstract class ANode { /** * Checks for errors and collects data for the writing phase. */ - abstract void analyze(FunctionTable functions, Locals locals); + abstract void analyze(ScriptRoot scriptRoot, Locals locals); /** * Writes ASM based on the data collected during the analysis phase. diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EAssignment.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EAssignment.java index 7d7b67448ec..a92f85b4788 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EAssignment.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EAssignment.java @@ -31,7 +31,7 @@ import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.Operation; import org.elasticsearch.painless.lookup.PainlessCast; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.ArrayList; import java.util.List; @@ -84,26 +84,26 @@ public final class EAssignment extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { - analyzeLHS(functions, locals); + void analyze(ScriptRoot scriptRoot, Locals locals) { + analyzeLHS(scriptRoot, locals); analyzeIncrDecr(); if (operation != null) { - analyzeCompound(functions, locals); + analyzeCompound(scriptRoot, locals); } else if (rhs != null) { - analyzeSimple(functions, locals); + analyzeSimple(scriptRoot, locals); } else { throw new IllegalStateException("Illegal tree structure."); } } - private void analyzeLHS(FunctionTable functions, Locals locals) { + private void analyzeLHS(ScriptRoot scriptRoot, Locals locals) { if (lhs instanceof AStoreable) { AStoreable lhs = (AStoreable)this.lhs; lhs.read = read; lhs.write = true; - lhs.analyze(functions, locals); + lhs.analyze(scriptRoot, locals); } else { throw new IllegalArgumentException("Left-hand side cannot be assigned a value."); } @@ -147,9 +147,8 @@ public final class EAssignment extends AExpression { } } - private void analyzeCompound(FunctionTable functions, Locals locals) { - rhs.analyze(functions, locals); - + private void analyzeCompound(ScriptRoot scriptRoot, Locals locals) { + rhs.analyze(scriptRoot, locals); boolean shift = false; if (operation == Operation.MUL) { @@ -211,7 +210,7 @@ public final class EAssignment extends AExpression { rhs.expected = promote; } - rhs = rhs.cast(functions, locals); + rhs = rhs.cast(scriptRoot, locals); there = AnalyzerCaster.getLegalCast(location, lhs.actual, promote, false, false); back = AnalyzerCaster.getLegalCast(location, promote, lhs.actual, true, false); @@ -220,12 +219,12 @@ public final class EAssignment extends AExpression { this.actual = read ? lhs.actual : void.class; } - private void analyzeSimple(FunctionTable functions, Locals locals) { + private void analyzeSimple(ScriptRoot scriptRoot, Locals locals) { AStoreable lhs = (AStoreable)this.lhs; // If the lhs node is a def optimized node we update the actual type to remove the need for a cast. if (lhs.isDefOptimized()) { - rhs.analyze(functions, locals); + rhs.analyze(scriptRoot, locals); if (rhs.actual == void.class) { throw createError(new IllegalArgumentException("Right-hand side cannot be a [void] type for assignment.")); @@ -236,10 +235,10 @@ public final class EAssignment extends AExpression { // Otherwise, we must adapt the rhs type to the lhs type with a cast. } else { rhs.expected = lhs.actual; - rhs.analyze(functions, locals); + rhs.analyze(scriptRoot, locals); } - rhs = rhs.cast(functions, locals); + rhs = rhs.cast(scriptRoot, locals); this.statement = true; this.actual = read ? lhs.actual : void.class; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java index 448657f3198..ec7ce5dcdc8 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java @@ -31,7 +31,7 @@ import org.elasticsearch.painless.Operation; import org.elasticsearch.painless.WriterConstants; import org.elasticsearch.painless.lookup.PainlessLookupUtility; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -73,43 +73,43 @@ public final class EBinary extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { originallyExplicit = explicit; if (operation == Operation.MUL) { - analyzeMul(functions, locals); + analyzeMul(scriptRoot, locals); } else if (operation == Operation.DIV) { - analyzeDiv(functions, locals); + analyzeDiv(scriptRoot, locals); } else if (operation == Operation.REM) { - analyzeRem(functions, locals); + analyzeRem(scriptRoot, locals); } else if (operation == Operation.ADD) { - analyzeAdd(functions, locals); + analyzeAdd(scriptRoot, locals); } else if (operation == Operation.SUB) { - analyzeSub(functions, locals); + analyzeSub(scriptRoot, locals); } else if (operation == Operation.FIND) { - analyzeRegexOp(functions, locals); + analyzeRegexOp(scriptRoot, locals); } else if (operation == Operation.MATCH) { - analyzeRegexOp(functions, locals); + analyzeRegexOp(scriptRoot, locals); } else if (operation == Operation.LSH) { - analyzeLSH(functions, locals); + analyzeLSH(scriptRoot, locals); } else if (operation == Operation.RSH) { - analyzeRSH(functions, locals); + analyzeRSH(scriptRoot, locals); } else if (operation == Operation.USH) { - analyzeUSH(functions, locals); + analyzeUSH(scriptRoot, locals); } else if (operation == Operation.BWAND) { - analyzeBWAnd(functions, locals); + analyzeBWAnd(scriptRoot, locals); } else if (operation == Operation.XOR) { - analyzeXor(functions, locals); + analyzeXor(scriptRoot, locals); } else if (operation == Operation.BWOR) { - analyzeBWOr(functions, locals); + analyzeBWOr(scriptRoot, locals); } else { throw createError(new IllegalStateException("Illegal tree structure.")); } } - private void analyzeMul(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeMul(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); @@ -132,8 +132,8 @@ public final class EBinary extends AExpression { right.expected = promote; } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { if (promote == int.class) { @@ -150,9 +150,9 @@ public final class EBinary extends AExpression { } } - private void analyzeDiv(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeDiv(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); @@ -176,8 +176,8 @@ public final class EBinary extends AExpression { right.expected = promote; } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { try { @@ -198,9 +198,9 @@ public final class EBinary extends AExpression { } } - private void analyzeRem(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeRem(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); @@ -224,8 +224,8 @@ public final class EBinary extends AExpression { right.expected = promote; } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { try { @@ -246,9 +246,9 @@ public final class EBinary extends AExpression { } } - private void analyzeAdd(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeAdd(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promote = AnalyzerCaster.promoteAdd(left.actual, right.actual); @@ -284,8 +284,8 @@ public final class EBinary extends AExpression { right.expected = promote; } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { if (promote == int.class) { @@ -305,9 +305,9 @@ public final class EBinary extends AExpression { } - private void analyzeSub(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeSub(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); @@ -331,8 +331,8 @@ public final class EBinary extends AExpression { right.expected = promote; } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { if (promote == int.class) { @@ -349,23 +349,23 @@ public final class EBinary extends AExpression { } } - private void analyzeRegexOp(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeRegexOp(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); left.expected = String.class; right.expected = Pattern.class; - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); promote = boolean.class; actual = boolean.class; } - private void analyzeLSH(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeLSH(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); Class lhspromote = AnalyzerCaster.promoteNumeric(left.actual, false); Class rhspromote = AnalyzerCaster.promoteNumeric(right.actual, false); @@ -397,8 +397,8 @@ public final class EBinary extends AExpression { } } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { if (promote == int.class) { @@ -411,9 +411,9 @@ public final class EBinary extends AExpression { } } - private void analyzeRSH(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeRSH(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); Class lhspromote = AnalyzerCaster.promoteNumeric(left.actual, false); Class rhspromote = AnalyzerCaster.promoteNumeric(right.actual, false); @@ -445,8 +445,8 @@ public final class EBinary extends AExpression { } } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { if (promote == int.class) { @@ -459,9 +459,9 @@ public final class EBinary extends AExpression { } } - private void analyzeUSH(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeUSH(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); Class lhspromote = AnalyzerCaster.promoteNumeric(left.actual, false); Class rhspromote = AnalyzerCaster.promoteNumeric(right.actual, false); @@ -493,8 +493,8 @@ public final class EBinary extends AExpression { } } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { if (promote == int.class) { @@ -507,9 +507,9 @@ public final class EBinary extends AExpression { } } - private void analyzeBWAnd(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeBWAnd(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, false); @@ -533,8 +533,8 @@ public final class EBinary extends AExpression { right.expected = promote; } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { if (promote == int.class) { @@ -547,9 +547,9 @@ public final class EBinary extends AExpression { } } - private void analyzeXor(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeXor(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promote = AnalyzerCaster.promoteXor(left.actual, right.actual); @@ -572,8 +572,8 @@ public final class EBinary extends AExpression { right.expected = promote; } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { if (promote == boolean.class) { @@ -588,9 +588,9 @@ public final class EBinary extends AExpression { } } - private void analyzeBWOr(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeBWOr(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, false); @@ -613,8 +613,8 @@ public final class EBinary extends AExpression { right.expected = promote; } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { if (promote == int.class) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBool.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBool.java index b98eeb35b1c..3012ab46617 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBool.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBool.java @@ -26,7 +26,7 @@ import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.Operation; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; @@ -63,14 +63,14 @@ public final class EBool extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { left.expected = boolean.class; - left.analyze(functions, locals); - left = left.cast(functions, locals); + left.analyze(scriptRoot, locals); + left = left.cast(scriptRoot, locals); right.expected = boolean.class; - right.analyze(functions, locals); - right = right.cast(functions, locals); + right.analyze(scriptRoot, locals); + right = right.cast(scriptRoot, locals); if (left.constant != null && right.constant != null) { if (operation == Operation.AND) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBoolean.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBoolean.java index e553314fafc..42a3f3c46f6 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBoolean.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBoolean.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Set; @@ -51,7 +51,7 @@ public final class EBoolean extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (!read) { throw createError(new IllegalArgumentException("Must read from constant [" + constant + "].")); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECallLocal.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECallLocal.java index 741c8ea7612..fe594ec9c24 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECallLocal.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECallLocal.java @@ -28,6 +28,7 @@ import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessClassBinding; import org.elasticsearch.painless.lookup.PainlessInstanceBinding; import org.elasticsearch.painless.lookup.PainlessMethod; +import org.elasticsearch.painless.ScriptRoot; import org.elasticsearch.painless.symbol.FunctionTable; import org.objectweb.asm.Label; import org.objectweb.asm.Type; @@ -76,8 +77,8 @@ public final class ECallLocal extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { - localFunction = functions.getFunction(name, arguments.size()); + void analyze(ScriptRoot scriptRoot, Locals locals) { + localFunction = scriptRoot.getFunctionTable().getFunction(name, arguments.size()); // user cannot call internal functions, reset to null if an internal function is found if (localFunction != null && localFunction.isInternal()) { @@ -85,14 +86,14 @@ public final class ECallLocal extends AExpression { } if (localFunction == null) { - importedMethod = locals.getPainlessLookup().lookupImportedPainlessMethod(name, arguments.size()); + importedMethod = scriptRoot.getPainlessLookup().lookupImportedPainlessMethod(name, arguments.size()); if (importedMethod == null) { - classBinding = locals.getPainlessLookup().lookupPainlessClassBinding(name, arguments.size()); + classBinding = scriptRoot.getPainlessLookup().lookupPainlessClassBinding(name, arguments.size()); // check to see if this class binding requires an implicit this reference if (classBinding != null && classBinding.typeParameters.isEmpty() == false && - classBinding.typeParameters.get(0) == locals.getBaseClass()) { + classBinding.typeParameters.get(0) == scriptRoot.getScriptClassInfo().getBaseClass()) { classBinding = null; } @@ -103,11 +104,11 @@ public final class ECallLocal extends AExpression { // will likely involve adding a class instance binding where any instance can have a class binding // as part of its API. However, the situation at run-time is difficult and will modifications that // are a substantial change if even possible to do. - classBinding = locals.getPainlessLookup().lookupPainlessClassBinding(name, arguments.size() + 1); + classBinding = scriptRoot.getPainlessLookup().lookupPainlessClassBinding(name, arguments.size() + 1); if (classBinding != null) { if (classBinding.typeParameters.isEmpty() == false && - classBinding.typeParameters.get(0) == locals.getBaseClass()) { + classBinding.typeParameters.get(0) == scriptRoot.getScriptClassInfo().getBaseClass()) { classBindingOffset = 1; } else { classBinding = null; @@ -115,7 +116,7 @@ public final class ECallLocal extends AExpression { } if (classBinding == null) { - instanceBinding = locals.getPainlessLookup().lookupPainlessInstanceBinding(name, arguments.size()); + instanceBinding = scriptRoot.getPainlessLookup().lookupPainlessInstanceBinding(name, arguments.size()); if (instanceBinding == null) { throw createError(new IllegalArgumentException( @@ -152,8 +153,8 @@ public final class ECallLocal extends AExpression { expression.expected = typeParameters.get(argument + classBindingOffset); expression.internal = true; - expression.analyze(functions, locals); - arguments.set(argument, expression.cast(functions, locals)); + expression.analyze(scriptRoot, locals); + arguments.set(argument, expression.cast(scriptRoot, locals)); } statement = true; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECapturingFunctionRef.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECapturingFunctionRef.java index f9cf2a8fa3f..2b787cc1be0 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECapturingFunctionRef.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECapturingFunctionRef.java @@ -30,7 +30,7 @@ import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessLookupUtility; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; @@ -66,7 +66,7 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { captured = locals.getVariable(location, variable); if (expected == null) { if (captured.clazz == def.class) { @@ -81,7 +81,7 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda defPointer = null; // static case if (captured.clazz != def.class) { - ref = FunctionRef.create(locals.getPainlessLookup(), functions, location, + ref = FunctionRef.create(scriptRoot.getPainlessLookup(), scriptRoot.getFunctionTable(), location, expected, PainlessLookupUtility.typeToCanonicalTypeName(captured.clazz), call, 1); } actual = expected; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECast.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECast.java index d064a84dfbb..148f1c43b74 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECast.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECast.java @@ -27,7 +27,7 @@ import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessCast; import org.elasticsearch.painless.lookup.PainlessLookupUtility; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -58,7 +58,7 @@ final class ECast extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { throw createError(new IllegalStateException("Illegal tree structure.")); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EComp.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EComp.java index 14658a0ea9b..40d57a68f82 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EComp.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EComp.java @@ -30,7 +30,7 @@ import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.Operation; import org.elasticsearch.painless.lookup.PainlessLookupUtility; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import org.objectweb.asm.Type; @@ -72,31 +72,31 @@ public final class EComp extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (operation == Operation.EQ) { - analyzeEq(functions, locals); + analyzeEq(scriptRoot, locals); } else if (operation == Operation.EQR) { - analyzeEqR(functions, locals); + analyzeEqR(scriptRoot, locals); } else if (operation == Operation.NE) { - analyzeNE(functions, locals); + analyzeNE(scriptRoot, locals); } else if (operation == Operation.NER) { - analyzeNER(functions, locals); + analyzeNER(scriptRoot, locals); } else if (operation == Operation.GTE) { - analyzeGTE(functions, locals); + analyzeGTE(scriptRoot, locals); } else if (operation == Operation.GT) { - analyzeGT(functions, locals); + analyzeGT(scriptRoot, locals); } else if (operation == Operation.LTE) { - analyzeLTE(functions, locals); + analyzeLTE(scriptRoot, locals); } else if (operation == Operation.LT) { - analyzeLT(functions, locals); + analyzeLT(scriptRoot, locals); } else { throw createError(new IllegalStateException("Illegal tree structure.")); } } - private void analyzeEq(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeEq(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promotedType = AnalyzerCaster.promoteEquality(left.actual, right.actual); @@ -114,8 +114,8 @@ public final class EComp extends AExpression { right.expected = promotedType; } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.isNull && right.isNull) { throw createError(new IllegalArgumentException("Extraneous comparison of null constants.")); @@ -144,9 +144,9 @@ public final class EComp extends AExpression { actual = boolean.class; } - private void analyzeEqR(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeEqR(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promotedType = AnalyzerCaster.promoteEquality(left.actual, right.actual); @@ -159,8 +159,8 @@ public final class EComp extends AExpression { left.expected = promotedType; right.expected = promotedType; - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.isNull && right.isNull) { throw createError(new IllegalArgumentException("Extraneous comparison of null constants.")); @@ -185,9 +185,9 @@ public final class EComp extends AExpression { actual = boolean.class; } - private void analyzeNE(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeNE(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promotedType = AnalyzerCaster.promoteEquality(left.actual, right.actual); @@ -205,8 +205,8 @@ public final class EComp extends AExpression { right.expected = promotedType; } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.isNull && right.isNull) { throw createError(new IllegalArgumentException("Extraneous comparison of null constants.")); @@ -235,9 +235,9 @@ public final class EComp extends AExpression { actual = boolean.class; } - private void analyzeNER(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeNER(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promotedType = AnalyzerCaster.promoteEquality(left.actual, right.actual); @@ -250,8 +250,8 @@ public final class EComp extends AExpression { left.expected = promotedType; right.expected = promotedType; - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.isNull && right.isNull) { throw createError(new IllegalArgumentException("Extraneous comparison of null constants.")); @@ -276,9 +276,9 @@ public final class EComp extends AExpression { actual = boolean.class; } - private void analyzeGTE(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeGTE(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promotedType = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); @@ -296,8 +296,8 @@ public final class EComp extends AExpression { right.expected = promotedType; } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { if (promotedType == int.class) { @@ -316,9 +316,9 @@ public final class EComp extends AExpression { actual = boolean.class; } - private void analyzeGT(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeGT(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promotedType = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); @@ -336,8 +336,8 @@ public final class EComp extends AExpression { right.expected = promotedType; } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { if (promotedType == int.class) { @@ -356,9 +356,9 @@ public final class EComp extends AExpression { actual = boolean.class; } - private void analyzeLTE(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeLTE(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promotedType = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); @@ -376,8 +376,8 @@ public final class EComp extends AExpression { right.expected = promotedType; } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { if (promotedType == int.class) { @@ -396,9 +396,9 @@ public final class EComp extends AExpression { actual = boolean.class; } - private void analyzeLT(FunctionTable functions, Locals variables) { - left.analyze(functions, variables); - right.analyze(functions, variables); + private void analyzeLT(ScriptRoot scriptRoot, Locals variables) { + left.analyze(scriptRoot, variables); + right.analyze(scriptRoot, variables); promotedType = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true); @@ -416,8 +416,8 @@ public final class EComp extends AExpression { right.expected = promotedType; } - left = left.cast(functions, variables); - right = right.cast(functions, variables); + left = left.cast(scriptRoot, variables); + right = right.cast(scriptRoot, variables); if (left.constant != null && right.constant != null) { if (promotedType == int.class) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConditional.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConditional.java index 4c8da0de8d0..c7c12a56e5c 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConditional.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConditional.java @@ -26,7 +26,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; @@ -65,10 +65,10 @@ public final class EConditional extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { condition.expected = boolean.class; - condition.analyze(functions, locals); - condition = condition.cast(functions, locals); + condition.analyze(scriptRoot, locals); + condition = condition.cast(scriptRoot, locals); if (condition.constant != null) { throw createError(new IllegalArgumentException("Extraneous conditional statement.")); @@ -82,8 +82,8 @@ public final class EConditional extends AExpression { right.internal = internal; actual = expected; - left.analyze(functions, locals); - right.analyze(functions, locals); + left.analyze(scriptRoot, locals); + right.analyze(scriptRoot, locals); if (expected == null) { Class promote = AnalyzerCaster.promoteConditional(left.actual, right.actual, left.constant, right.constant); @@ -93,8 +93,8 @@ public final class EConditional extends AExpression { actual = promote; } - left = left.cast(functions, locals); - right = right.cast(functions, locals); + left = left.cast(scriptRoot, locals); + right = right.cast(scriptRoot, locals); } @Override diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConstant.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConstant.java index b942fe4b36b..0a7de352f41 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConstant.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EConstant.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Set; @@ -52,7 +52,7 @@ final class EConstant extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (constant instanceof String) { actual = String.class; } else if (constant instanceof Double) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EDecimal.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EDecimal.java index 983129eb85c..19e788b0c48 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EDecimal.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EDecimal.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -54,7 +54,7 @@ public final class EDecimal extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (!read) { throw createError(new IllegalArgumentException("Must read from constant [" + value + "].")); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EElvis.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EElvis.java index a46549994b4..3ea6d56d959 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EElvis.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EElvis.java @@ -26,7 +26,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import java.util.Set; @@ -61,7 +61,7 @@ public class EElvis extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (expected != null && expected.isPrimitive()) { throw createError(new IllegalArgumentException("Elvis operator cannot return primitives")); } @@ -72,8 +72,8 @@ public class EElvis extends AExpression { rhs.explicit = explicit; rhs.internal = internal; actual = expected; - lhs.analyze(functions, locals); - rhs.analyze(functions, locals); + lhs.analyze(scriptRoot, locals); + rhs.analyze(scriptRoot, locals); if (lhs.isNull) { throw createError(new IllegalArgumentException("Extraneous elvis operator. LHS is null.")); @@ -96,8 +96,8 @@ public class EElvis extends AExpression { actual = promote; } - lhs = lhs.cast(functions, locals); - rhs = rhs.cast(functions, locals); + lhs = lhs.cast(scriptRoot, locals); + rhs = rhs.cast(scriptRoot, locals); } @Override diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EExplicit.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EExplicit.java index bb3f68f1db8..a83d1ddcd70 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EExplicit.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EExplicit.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -56,8 +56,8 @@ public final class EExplicit extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { - actual = locals.getPainlessLookup().canonicalTypeNameToType(type); + void analyze(ScriptRoot scriptRoot, Locals locals) { + actual = scriptRoot.getPainlessLookup().canonicalTypeNameToType(type); if (actual == null) { throw createError(new IllegalArgumentException("Not a type [" + type + "].")); @@ -65,8 +65,8 @@ public final class EExplicit extends AExpression { child.expected = actual; child.explicit = true; - child.analyze(functions, locals); - child = child.cast(functions, locals); + child.analyze(scriptRoot, locals); + child = child.cast(scriptRoot, locals); } @Override @@ -74,12 +74,12 @@ public final class EExplicit extends AExpression { throw createError(new IllegalStateException("Illegal tree structure.")); } - AExpression cast(FunctionTable functions, Locals locals) { + AExpression cast(ScriptRoot scriptRoot, Locals locals) { child.expected = expected; child.explicit = explicit; child.internal = internal; - return child.cast(functions, locals); + return child.cast(scriptRoot, locals); } @Override diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java index b3ca02712ff..48cd251102c 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java @@ -26,7 +26,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Type; import java.util.Objects; @@ -60,14 +60,14 @@ public final class EFunctionRef extends AExpression implements ILambda { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (expected == null) { ref = null; actual = String.class; defPointer = "S" + type + "." + call + ",0"; } else { defPointer = null; - ref = FunctionRef.create(locals.getPainlessLookup(), functions, location, expected, type, call, 0); + ref = FunctionRef.create(scriptRoot.getPainlessLookup(), scriptRoot.getFunctionTable(), location, expected, type, call, 0); actual = expected; } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EInstanceof.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EInstanceof.java index b609a3643d9..06b9d964b41 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EInstanceof.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EInstanceof.java @@ -26,7 +26,7 @@ import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessLookupUtility; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -61,10 +61,9 @@ public final class EInstanceof extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { - + void analyze(ScriptRoot scriptRoot, Locals locals) { // ensure the specified type is part of the definition - Class clazz = locals.getPainlessLookup().canonicalTypeNameToType(this.type); + Class clazz = scriptRoot.getPainlessLookup().canonicalTypeNameToType(this.type); if (clazz == null) { throw createError(new IllegalArgumentException("Not a type [" + this.type + "].")); @@ -75,9 +74,9 @@ public final class EInstanceof extends AExpression { PainlessLookupUtility.typeToJavaType(clazz); // analyze and cast the expression - expression.analyze(functions, locals); + expression.analyze(scriptRoot, locals); expression.expected = expression.actual; - expression = expression.cast(functions, locals); + expression = expression.cast(scriptRoot, locals); // record if the expression returns a primitive primitiveExpression = expression.actual.isPrimitive(); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java index e2aabac77f6..1103bf60f98 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java @@ -30,7 +30,7 @@ import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessLookupUtility; import org.elasticsearch.painless.lookup.PainlessMethod; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Opcodes; import java.util.ArrayList; @@ -111,7 +111,7 @@ public final class ELambda extends AExpression implements ILambda { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { Class returnType; List actualParamTypeStrs; PainlessMethod interfaceMethod; @@ -132,7 +132,7 @@ public final class ELambda extends AExpression implements ILambda { } else { // we know the method statically, infer return type and any unknown/def types - interfaceMethod = locals.getPainlessLookup().lookupFunctionalInterfacePainlessMethod(expected); + interfaceMethod = scriptRoot.getPainlessLookup().lookupFunctionalInterfacePainlessMethod(expected); if (interfaceMethod == null) { throw createError(new IllegalArgumentException("Cannot pass lambda to " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(expected) + "], not a functional interface")); @@ -176,14 +176,15 @@ public final class ELambda extends AExpression implements ILambda { paramNames.addAll(paramNameStrs); // desugar lambda body into a synthetic method - String name = locals.getNextSyntheticName(); - desugared = new SFunction(location, PainlessLookupUtility.typeToCanonicalTypeName(returnType), name, paramTypes, paramNames, + String name = scriptRoot.getNextSyntheticName("lambda"); + desugared = new SFunction( + location, PainlessLookupUtility.typeToCanonicalTypeName(returnType), name, paramTypes, paramNames, new SBlock(location, statements), true); desugared.storeSettings(settings); - desugared.generateSignature(locals.getPainlessLookup()); - desugared.analyze(functions, Locals.newLambdaScope(locals.getProgramScope(), desugared.name, returnType, + desugared.generateSignature(scriptRoot.getPainlessLookup()); + desugared.analyze(scriptRoot, Locals.newLambdaScope(locals.getProgramScope(), desugared.name, returnType, desugared.parameters, captures.size(), settings.getMaxLoopCounter())); - functions.addFunction(desugared.name, desugared.returnType, desugared.typeParameters, true); + scriptRoot.getFunctionTable().addFunction(desugared.name, desugared.returnType, desugared.typeParameters, true); // setup method reference to synthetic method if (expected == null) { @@ -192,8 +193,8 @@ public final class ELambda extends AExpression implements ILambda { defPointer = "Sthis." + name + "," + captures.size(); } else { defPointer = null; - ref = FunctionRef.create( - locals.getPainlessLookup(), functions, location, expected, "this", desugared.name, captures.size()); + ref = FunctionRef.create(scriptRoot.getPainlessLookup(), scriptRoot.getFunctionTable(), + location, expected, "this", desugared.name, captures.size()); actual = expected; } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EListInit.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EListInit.java index b968be9e581..ba20436af69 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EListInit.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EListInit.java @@ -28,7 +28,7 @@ import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessConstructor; import org.elasticsearch.painless.lookup.PainlessMethod; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Type; import org.objectweb.asm.commons.Method; @@ -68,21 +68,21 @@ public final class EListInit extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (!read) { throw createError(new IllegalArgumentException("Must read from list initializer.")); } actual = ArrayList.class; - constructor = locals.getPainlessLookup().lookupPainlessConstructor(actual, 0); + constructor = scriptRoot.getPainlessLookup().lookupPainlessConstructor(actual, 0); if (constructor == null) { throw createError(new IllegalArgumentException( "constructor [" + typeToCanonicalTypeName(actual) + ", /0] not found")); } - method = locals.getPainlessLookup().lookupPainlessMethod(actual, false, "add", 1); + method = scriptRoot.getPainlessLookup().lookupPainlessMethod(actual, false, "add", 1); if (method == null) { throw createError(new IllegalArgumentException("method [" + typeToCanonicalTypeName(actual) + ", add/1] not found")); @@ -93,8 +93,8 @@ public final class EListInit extends AExpression { expression.expected = def.class; expression.internal = true; - expression.analyze(functions, locals); - values.set(index, expression.cast(functions, locals)); + expression.analyze(scriptRoot, locals); + values.set(index, expression.cast(scriptRoot, locals)); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EMapInit.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EMapInit.java index eb038bb1b34..2861577ff8d 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EMapInit.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EMapInit.java @@ -28,7 +28,7 @@ import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessConstructor; import org.elasticsearch.painless.lookup.PainlessMethod; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Type; import org.objectweb.asm.commons.Method; @@ -78,21 +78,21 @@ public final class EMapInit extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (!read) { throw createError(new IllegalArgumentException("Must read from map initializer.")); } actual = HashMap.class; - constructor = locals.getPainlessLookup().lookupPainlessConstructor(actual, 0); + constructor = scriptRoot.getPainlessLookup().lookupPainlessConstructor(actual, 0); if (constructor == null) { throw createError(new IllegalArgumentException( "constructor [" + typeToCanonicalTypeName(actual) + ", /0] not found")); } - method = locals.getPainlessLookup().lookupPainlessMethod(actual, false, "put", 2); + method = scriptRoot.getPainlessLookup().lookupPainlessMethod(actual, false, "put", 2); if (method == null) { throw createError(new IllegalArgumentException("method [" + typeToCanonicalTypeName(actual) + ", put/2] not found")); @@ -107,8 +107,8 @@ public final class EMapInit extends AExpression { expression.expected = def.class; expression.internal = true; - expression.analyze(functions, locals); - keys.set(index, expression.cast(functions, locals)); + expression.analyze(scriptRoot, locals); + keys.set(index, expression.cast(scriptRoot, locals)); } for (int index = 0; index < values.size(); ++index) { @@ -116,8 +116,8 @@ public final class EMapInit extends AExpression { expression.expected = def.class; expression.internal = true; - expression.analyze(functions, locals); - values.set(index, expression.cast(functions, locals)); + expression.analyze(scriptRoot, locals); + values.set(index, expression.cast(scriptRoot, locals)); } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArray.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArray.java index 997293eac77..dbf506f6de5 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArray.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArray.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.List; import java.util.Objects; @@ -63,12 +63,12 @@ public final class ENewArray extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (!read) { throw createError(new IllegalArgumentException("A newly created array must be read from.")); } - Class clazz = locals.getPainlessLookup().canonicalTypeNameToType(this.type); + Class clazz = scriptRoot.getPainlessLookup().canonicalTypeNameToType(this.type); if (clazz == null) { throw createError(new IllegalArgumentException("Not a type [" + this.type + "].")); @@ -79,8 +79,8 @@ public final class ENewArray extends AExpression { expression.expected = initialize ? clazz.getComponentType() : int.class; expression.internal = true; - expression.analyze(functions, locals); - arguments.set(argument, expression.cast(functions, locals)); + expression.analyze(scriptRoot, locals); + arguments.set(argument, expression.cast(scriptRoot, locals)); } actual = clazz; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArrayFunctionRef.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArrayFunctionRef.java index 00e085863ac..4f54d00f7dc 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArrayFunctionRef.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewArrayFunctionRef.java @@ -26,7 +26,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Type; import java.util.Arrays; @@ -63,17 +63,18 @@ public final class ENewArrayFunctionRef extends AExpression implements ILambda { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { SReturn code = new SReturn(location, new ENewArray(location, type, Arrays.asList(new EVariable(location, "size")), false)); - function = new SFunction(location, type, locals.getNextSyntheticName(), + function = new SFunction( + location, type, scriptRoot.getNextSyntheticName("newarray"), Collections.singletonList("int"), Collections.singletonList("size"), new SBlock(location, Collections.singletonList(code)), true); function.storeSettings(settings); - function.generateSignature(locals.getPainlessLookup()); + function.generateSignature(scriptRoot.getPainlessLookup()); function.extractVariables(null); - function.analyze(functions, Locals.newLambdaScope(locals.getProgramScope(), function.name, function.returnType, + function.analyze(scriptRoot, Locals.newLambdaScope(locals.getProgramScope(), function.name, function.returnType, function.parameters, 0, settings.getMaxLoopCounter())); - functions.addFunction(function.name, function.returnType, function.typeParameters, true); + scriptRoot.getFunctionTable().addFunction(function.name, function.returnType, function.typeParameters, true); if (expected == null) { ref = null; @@ -81,7 +82,8 @@ public final class ENewArrayFunctionRef extends AExpression implements ILambda { defPointer = "Sthis." + function.name + ",0"; } else { defPointer = null; - ref = FunctionRef.create(locals.getPainlessLookup(), functions, location, expected, "this", function.name, 0); + ref = FunctionRef.create(scriptRoot.getPainlessLookup(), scriptRoot.getFunctionTable(), + location, expected, "this", function.name, 0); actual = expected; } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewObj.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewObj.java index 24bfe7e3357..c6041efa2b8 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewObj.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENewObj.java @@ -27,7 +27,7 @@ import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessConstructor; import org.elasticsearch.painless.lookup.PainlessLookupUtility; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Type; import org.objectweb.asm.commons.Method; @@ -69,14 +69,14 @@ public final class ENewObj extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { - actual = locals.getPainlessLookup().canonicalTypeNameToType(this.type); + void analyze(ScriptRoot scriptRoot, Locals locals) { + actual = scriptRoot.getPainlessLookup().canonicalTypeNameToType(this.type); if (actual == null) { throw createError(new IllegalArgumentException("Not a type [" + this.type + "].")); } - constructor = locals.getPainlessLookup().lookupPainlessConstructor(actual, arguments.size()); + constructor = scriptRoot.getPainlessLookup().lookupPainlessConstructor(actual, arguments.size()); if (constructor == null) { throw createError(new IllegalArgumentException( @@ -97,8 +97,8 @@ public final class ENewObj extends AExpression { expression.expected = types[argument]; expression.internal = true; - expression.analyze(functions, locals); - arguments.set(argument, expression.cast(functions, locals)); + expression.analyze(scriptRoot, locals); + arguments.set(argument, expression.cast(scriptRoot, locals)); } statement = true; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENull.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENull.java index 763e040ce9d..79ef55d6028 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENull.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENull.java @@ -26,7 +26,7 @@ import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessLookupUtility; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Opcodes; import java.util.Set; @@ -51,7 +51,7 @@ public final class ENull extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (!read) { throw createError(new IllegalArgumentException("Must read from null constant.")); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENumeric.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENumeric.java index a26c1818c65..1e7dfb9276a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENumeric.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ENumeric.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -56,7 +56,7 @@ public final class ENumeric extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (!read) { throw createError(new IllegalArgumentException("Must read from constant [" + value + "].")); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ERegex.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ERegex.java index ad0d2fd19e0..e020d80e745 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ERegex.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ERegex.java @@ -27,7 +27,7 @@ import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.WriterConstants; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Set; import java.util.regex.Pattern; @@ -69,7 +69,7 @@ public final class ERegex extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (false == settings.areRegexesEnabled()) { throw createError(new IllegalStateException("Regexes are disabled. Set [script.painless.regex.enabled] to [true] " + "in elasticsearch.yaml to allow them. Be careful though, regexes break out of Painless's protection against deep " diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EStatic.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EStatic.java index 79a75e5c37a..9bc387137e3 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EStatic.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EStatic.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -54,8 +54,8 @@ public final class EStatic extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { - actual = locals.getPainlessLookup().canonicalTypeNameToType(type); + void analyze(ScriptRoot scriptRoot, Locals locals) { + actual = scriptRoot.getPainlessLookup().canonicalTypeNameToType(type); if (actual == null) { throw createError(new IllegalArgumentException("Not a type [" + type + "].")); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EString.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EString.java index c2abfb0e101..71802bd371b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EString.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EString.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -52,7 +52,7 @@ public final class EString extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (!read) { throw createError(new IllegalArgumentException("Must read from constant [" + constant + "].")); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java index 12983643585..7e9d04f17fb 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java @@ -30,7 +30,7 @@ import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.Operation; import org.elasticsearch.painless.lookup.PainlessLookupUtility; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; @@ -67,26 +67,26 @@ public final class EUnary extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { originallyExplicit = explicit; if (operation == Operation.NOT) { - analyzeNot(functions, locals); + analyzeNot(scriptRoot, locals); } else if (operation == Operation.BWNOT) { - analyzeBWNot(functions, locals); + analyzeBWNot(scriptRoot, locals); } else if (operation == Operation.ADD) { - analyzerAdd(functions, locals); + analyzerAdd(scriptRoot, locals); } else if (operation == Operation.SUB) { - analyzerSub(functions, locals); + analyzerSub(scriptRoot, locals); } else { throw createError(new IllegalStateException("Illegal tree structure.")); } } - void analyzeNot(FunctionTable functions, Locals variables) { + void analyzeNot(ScriptRoot scriptRoot, Locals variables) { child.expected = boolean.class; - child.analyze(functions, variables); - child = child.cast(functions, variables); + child.analyze(scriptRoot, variables); + child = child.cast(scriptRoot, variables); if (child.constant != null) { constant = !(boolean)child.constant; @@ -95,8 +95,8 @@ public final class EUnary extends AExpression { actual = boolean.class; } - void analyzeBWNot(FunctionTable functions, Locals variables) { - child.analyze(functions, variables); + void analyzeBWNot(ScriptRoot scriptRoot, Locals variables) { + child.analyze(scriptRoot, variables); promote = AnalyzerCaster.promoteNumeric(child.actual, false); @@ -106,7 +106,7 @@ public final class EUnary extends AExpression { } child.expected = promote; - child = child.cast(functions, variables); + child = child.cast(scriptRoot, variables); if (child.constant != null) { if (promote == int.class) { @@ -125,8 +125,8 @@ public final class EUnary extends AExpression { } } - void analyzerAdd(FunctionTable functions, Locals variables) { - child.analyze(functions, variables); + void analyzerAdd(ScriptRoot scriptRoot, Locals variables) { + child.analyze(scriptRoot, variables); promote = AnalyzerCaster.promoteNumeric(child.actual, true); @@ -136,7 +136,7 @@ public final class EUnary extends AExpression { } child.expected = promote; - child = child.cast(functions, variables); + child = child.cast(scriptRoot, variables); if (child.constant != null) { if (promote == int.class) { @@ -159,8 +159,8 @@ public final class EUnary extends AExpression { } } - void analyzerSub(FunctionTable functions, Locals variables) { - child.analyze(functions, variables); + void analyzerSub(ScriptRoot scriptRoot, Locals variables) { + child.analyze(scriptRoot, variables); promote = AnalyzerCaster.promoteNumeric(child.actual, true); @@ -170,7 +170,7 @@ public final class EUnary extends AExpression { } child.expected = promote; - child = child.cast(functions, variables); + child = child.cast(scriptRoot, variables); if (child.constant != null) { if (promote == int.class) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EVariable.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EVariable.java index a9ff333f853..ad474b56c2e 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EVariable.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EVariable.java @@ -26,7 +26,7 @@ import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Locals.Variable; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Opcodes; import java.util.Objects; @@ -58,7 +58,7 @@ public final class EVariable extends AStoreable { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { variable = locals.getVariable(location, name); if (write && variable.readonly) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PBrace.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PBrace.java index 000044e0ec6..0526caefe2a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PBrace.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PBrace.java @@ -27,7 +27,7 @@ import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessLookupUtility; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.List; import java.util.Map; @@ -62,10 +62,10 @@ public final class PBrace extends AStoreable { } @Override - void analyze(FunctionTable functions, Locals locals) { - prefix.analyze(functions, locals); + void analyze(ScriptRoot scriptRoot, Locals locals) { + prefix.analyze(scriptRoot, locals); prefix.expected = prefix.actual; - prefix = prefix.cast(functions, locals); + prefix = prefix.cast(scriptRoot, locals); if (prefix.actual.isArray()) { sub = new PSubBrace(location, prefix.actual, index); @@ -84,7 +84,7 @@ public final class PBrace extends AStoreable { sub.read = read; sub.expected = expected; sub.explicit = explicit; - sub.analyze(functions, locals); + sub.analyze(scriptRoot, locals); actual = sub.actual; } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PCallInvoke.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PCallInvoke.java index ace0e8f9028..b1c1081a935 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PCallInvoke.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PCallInvoke.java @@ -27,7 +27,7 @@ import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessMethod; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.List; import java.util.Objects; @@ -73,16 +73,16 @@ public final class PCallInvoke extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { - prefix.analyze(functions, locals); + void analyze(ScriptRoot scriptRoot, Locals locals) { + prefix.analyze(scriptRoot, locals); prefix.expected = prefix.actual; - prefix = prefix.cast(functions, locals); + prefix = prefix.cast(scriptRoot, locals); if (prefix.actual == def.class) { sub = new PSubDefCall(location, name, arguments); } else { PainlessMethod method = - locals.getPainlessLookup().lookupPainlessMethod(prefix.actual, prefix instanceof EStatic, name, arguments.size()); + scriptRoot.getPainlessLookup().lookupPainlessMethod(prefix.actual, prefix instanceof EStatic, name, arguments.size()); if (method == null) { throw createError(new IllegalArgumentException( @@ -98,7 +98,7 @@ public final class PCallInvoke extends AExpression { sub.expected = expected; sub.explicit = explicit; - sub.analyze(functions, locals); + sub.analyze(scriptRoot, locals); actual = sub.actual; statement = true; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PField.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PField.java index 5ebe8ab2b95..063291625a9 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PField.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PField.java @@ -29,7 +29,7 @@ import org.elasticsearch.painless.lookup.PainlessField; import org.elasticsearch.painless.lookup.PainlessLookupUtility; import org.elasticsearch.painless.lookup.PainlessMethod; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.List; import java.util.Map; @@ -66,38 +66,38 @@ public final class PField extends AStoreable { } @Override - void analyze(FunctionTable functions, Locals locals) { - prefix.analyze(functions, locals); + void analyze(ScriptRoot scriptRoot, Locals locals) { + prefix.analyze(scriptRoot, locals); prefix.expected = prefix.actual; - prefix = prefix.cast(functions, locals); + prefix = prefix.cast(scriptRoot, locals); if (prefix.actual.isArray()) { sub = new PSubArrayLength(location, PainlessLookupUtility.typeToCanonicalTypeName(prefix.actual), value); } else if (prefix.actual == def.class) { sub = new PSubDefField(location, value); } else { - PainlessField field = locals.getPainlessLookup().lookupPainlessField(prefix.actual, prefix instanceof EStatic, value); + PainlessField field = scriptRoot.getPainlessLookup().lookupPainlessField(prefix.actual, prefix instanceof EStatic, value); if (field == null) { PainlessMethod getter; PainlessMethod setter; - getter = locals.getPainlessLookup().lookupPainlessMethod(prefix.actual, false, + getter = scriptRoot.getPainlessLookup().lookupPainlessMethod(prefix.actual, false, "get" + Character.toUpperCase(value.charAt(0)) + value.substring(1), 0); if (getter == null) { - getter = locals.getPainlessLookup().lookupPainlessMethod(prefix.actual, false, + getter = scriptRoot.getPainlessLookup().lookupPainlessMethod(prefix.actual, false, "is" + Character.toUpperCase(value.charAt(0)) + value.substring(1), 0); } - setter = locals.getPainlessLookup().lookupPainlessMethod(prefix.actual, false, + setter = scriptRoot.getPainlessLookup().lookupPainlessMethod(prefix.actual, false, "set" + Character.toUpperCase(value.charAt(0)) + value.substring(1), 0); if (getter != null || setter != null) { sub = new PSubShortcut(location, value, PainlessLookupUtility.typeToCanonicalTypeName(prefix.actual), getter, setter); } else { EConstant index = new EConstant(location, value); - index.analyze(functions, locals); + index.analyze(scriptRoot, locals); if (Map.class.isAssignableFrom(prefix.actual)) { sub = new PSubMapShortcut(location, prefix.actual, index); @@ -125,7 +125,7 @@ public final class PField extends AStoreable { sub.read = read; sub.expected = expected; sub.explicit = explicit; - sub.analyze(functions, locals); + sub.analyze(scriptRoot, locals); actual = sub.actual; } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubArrayLength.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubArrayLength.java index 4f92897314d..52ad98ae239 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubArrayLength.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubArrayLength.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -56,7 +56,7 @@ final class PSubArrayLength extends AStoreable { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if ("length".equals(value)) { if (write) { throw createError(new IllegalArgumentException("Cannot write to read-only field [length] for an array.")); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubBrace.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubBrace.java index 800cb8fbfa6..6a15556f799 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubBrace.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubBrace.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -56,10 +56,10 @@ final class PSubBrace extends AStoreable { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { index.expected = int.class; - index.analyze(functions, locals); - index = index.cast(functions, locals); + index.analyze(scriptRoot, locals); + index = index.cast(scriptRoot, locals); actual = clazz.getComponentType(); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubCallInvoke.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubCallInvoke.java index 7016175841b..4c13ebe5cae 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubCallInvoke.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubCallInvoke.java @@ -26,7 +26,7 @@ import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessMethod; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.List; import java.util.Objects; @@ -60,14 +60,14 @@ final class PSubCallInvoke extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { for (int argument = 0; argument < arguments.size(); ++argument) { AExpression expression = arguments.get(argument); expression.expected = method.typeParameters.get(argument); expression.internal = true; - expression.analyze(functions, locals); - arguments.set(argument, expression.cast(functions, locals)); + expression.analyze(scriptRoot, locals); + arguments.set(argument, expression.cast(scriptRoot, locals)); } statement = true; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefArray.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefArray.java index e6e9ad342a0..1bbe2b89a6b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefArray.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefArray.java @@ -27,7 +27,7 @@ import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Type; import java.time.ZonedDateTime; @@ -57,10 +57,10 @@ final class PSubDefArray extends AStoreable { } @Override - void analyze(FunctionTable functions, Locals locals) { - index.analyze(functions, locals); + void analyze(ScriptRoot scriptRoot, Locals locals) { + index.analyze(scriptRoot, locals); index.expected = index.actual; - index = index.cast(functions, locals); + index = index.cast(scriptRoot, locals); // TODO: remove ZonedDateTime exception when JodaCompatibleDateTime is removed actual = expected == null || expected == ZonedDateTime.class || explicit ? def.class : expected; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefCall.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefCall.java index 57dd6aeeee0..64d90602f91 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefCall.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefCall.java @@ -27,7 +27,7 @@ import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Type; import java.time.ZonedDateTime; @@ -66,7 +66,7 @@ final class PSubDefCall extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { recipe = new StringBuilder(); int totalCaptures = 0; @@ -74,7 +74,7 @@ final class PSubDefCall extends AExpression { AExpression expression = arguments.get(argument); expression.internal = true; - expression.analyze(functions, locals); + expression.analyze(scriptRoot, locals); if (expression instanceof ILambda) { ILambda lambda = (ILambda) expression; @@ -90,7 +90,7 @@ final class PSubDefCall extends AExpression { } expression.expected = expression.actual; - arguments.set(argument, expression.cast(functions, locals)); + arguments.set(argument, expression.cast(scriptRoot, locals)); } // TODO: remove ZonedDateTime exception when JodaCompatibleDateTime is removed diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefField.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefField.java index 9ce4bafdf30..6bad888cf54 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefField.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubDefField.java @@ -27,7 +27,7 @@ import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.time.ZonedDateTime; import java.util.Objects; @@ -57,7 +57,7 @@ final class PSubDefField extends AStoreable { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { // TODO: remove ZonedDateTime exception when JodaCompatibleDateTime is removed actual = expected == null || expected == ZonedDateTime.class || explicit ? def.class : expected; } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubField.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubField.java index 1de9b4b3f6f..102a1118331 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubField.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubField.java @@ -27,7 +27,7 @@ import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessField; import org.elasticsearch.painless.lookup.PainlessLookupUtility; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Type; import java.lang.reflect.Modifier; @@ -58,7 +58,7 @@ final class PSubField extends AStoreable { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (write && Modifier.isFinal(field.javaField.getModifiers())) { throw createError(new IllegalArgumentException("Cannot write to read-only field [" + field.javaField.getName() + "] " + "for type [" + PainlessLookupUtility.typeToCanonicalTypeName(field.javaField.getDeclaringClass()) + "].")); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubListShortcut.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubListShortcut.java index 3768bb4a3e1..4226252b16f 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubListShortcut.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubListShortcut.java @@ -28,7 +28,7 @@ import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.WriterConstants; import org.elasticsearch.painless.lookup.PainlessLookupUtility; import org.elasticsearch.painless.lookup.PainlessMethod; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -62,11 +62,11 @@ final class PSubListShortcut extends AStoreable { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { String canonicalClassName = PainlessLookupUtility.typeToCanonicalTypeName(targetClass); - getter = locals.getPainlessLookup().lookupPainlessMethod(targetClass, false, "get", 1); - setter = locals.getPainlessLookup().lookupPainlessMethod(targetClass, false, "set", 2); + getter = scriptRoot.getPainlessLookup().lookupPainlessMethod(targetClass, false, "get", 1); + setter = scriptRoot.getPainlessLookup().lookupPainlessMethod(targetClass, false, "set", 2); if (getter != null && (getter.returnType == void.class || getter.typeParameters.size() != 1 || getter.typeParameters.get(0) != int.class)) { @@ -84,8 +84,8 @@ final class PSubListShortcut extends AStoreable { if ((read || write) && (!read || getter != null) && (!write || setter != null)) { index.expected = int.class; - index.analyze(functions, locals); - index = index.cast(functions, locals); + index.analyze(scriptRoot, locals); + index = index.cast(scriptRoot, locals); actual = setter != null ? setter.typeParameters.get(1) : getter.returnType; } else { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubMapShortcut.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubMapShortcut.java index c74ce8ed770..99a2ab0fa2b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubMapShortcut.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubMapShortcut.java @@ -27,7 +27,7 @@ import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessLookupUtility; import org.elasticsearch.painless.lookup.PainlessMethod; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -61,11 +61,11 @@ final class PSubMapShortcut extends AStoreable { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { String canonicalClassName = PainlessLookupUtility.typeToCanonicalTypeName(targetClass); - getter = locals.getPainlessLookup().lookupPainlessMethod(targetClass, false, "get", 1); - setter = locals.getPainlessLookup().lookupPainlessMethod(targetClass, false, "put", 2); + getter = scriptRoot.getPainlessLookup().lookupPainlessMethod(targetClass, false, "get", 1); + setter = scriptRoot.getPainlessLookup().lookupPainlessMethod(targetClass, false, "put", 2); if (getter != null && (getter.returnType == void.class || getter.typeParameters.size() != 1)) { throw createError(new IllegalArgumentException("Illegal map get shortcut for type [" + canonicalClassName + "].")); @@ -82,8 +82,8 @@ final class PSubMapShortcut extends AStoreable { if ((read || write) && (!read || getter != null) && (!write || setter != null)) { index.expected = setter != null ? setter.typeParameters.get(0) : getter.typeParameters.get(0); - index.analyze(functions, locals); - index = index.cast(functions, locals); + index.analyze(scriptRoot, locals); + index = index.cast(scriptRoot, locals); actual = setter != null ? setter.typeParameters.get(1) : getter.returnType; } else { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeCallInvoke.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeCallInvoke.java index 84918b20d9c..8d02a904150 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeCallInvoke.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeCallInvoke.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import java.util.Set; @@ -57,8 +57,8 @@ public class PSubNullSafeCallInvoke extends AExpression { } @Override - void analyze(FunctionTable functions, Locals locals) { - guarded.analyze(functions, locals); + void analyze(ScriptRoot scriptRoot, Locals locals) { + guarded.analyze(scriptRoot, locals); actual = guarded.actual; if (actual.isPrimitive()) { throw new IllegalArgumentException("Result of null safe operator must be nullable"); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeField.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeField.java index ee9ed69c216..80dbca86d0a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeField.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubNullSafeField.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import java.util.Set; @@ -52,12 +52,12 @@ public class PSubNullSafeField extends AStoreable { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (write) { throw createError(new IllegalArgumentException("Can't write to null safe reference")); } guarded.read = read; - guarded.analyze(functions, locals); + guarded.analyze(scriptRoot, locals); actual = guarded.actual; if (actual.isPrimitive()) { throw new IllegalArgumentException("Result of null safe operator must be nullable"); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubShortcut.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubShortcut.java index 6e1a9c559f3..b9266d8590a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubShortcut.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/PSubShortcut.java @@ -26,7 +26,7 @@ import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessMethod; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Set; @@ -60,7 +60,7 @@ final class PSubShortcut extends AStoreable { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (getter != null && (getter.returnType == void.class || !getter.typeParameters.isEmpty())) { throw createError(new IllegalArgumentException( "Illegal get shortcut on field [" + value + "] for type [" + type + "].")); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBlock.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBlock.java index 71e35cadd21..992e23d9acf 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBlock.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBlock.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Collections; import java.util.List; @@ -61,7 +61,7 @@ public final class SBlock extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (statements == null || statements.isEmpty()) { throw createError(new IllegalArgumentException("A block must contain at least one statement.")); } @@ -78,8 +78,7 @@ public final class SBlock extends AStatement { statement.inLoop = inLoop; statement.lastSource = lastSource && statement == last; statement.lastLoop = (beginLoop || lastLoop) && statement == last; - - statement.analyze(functions, locals); + statement.analyze(scriptRoot, locals); methodEscape = statement.methodEscape; loopEscape = statement.loopEscape; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBreak.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBreak.java index 8d6796baf85..fb8522ab8f9 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBreak.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SBreak.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Set; @@ -49,7 +49,7 @@ public final class SBreak extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (!inLoop) { throw createError(new IllegalArgumentException("Break statement outside of a loop.")); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SCatch.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SCatch.java index 87400c5b28b..04842110e55 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SCatch.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SCatch.java @@ -26,7 +26,7 @@ import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Locals.Variable; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; @@ -73,8 +73,8 @@ public final class SCatch extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { - Class clazz = locals.getPainlessLookup().canonicalTypeNameToType(this.type); + void analyze(ScriptRoot scriptRoot, Locals locals) { + Class clazz = scriptRoot.getPainlessLookup().canonicalTypeNameToType(this.type); if (clazz == null) { throw createError(new IllegalArgumentException("Not a type [" + this.type + "].")); @@ -90,8 +90,7 @@ public final class SCatch extends AStatement { block.lastSource = lastSource; block.inLoop = inLoop; block.lastLoop = lastLoop; - - block.analyze(functions, locals); + block.analyze(scriptRoot, locals); methodEscape = block.methodEscape; loopEscape = block.loopEscape; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SClass.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SClass.java index a71edbe5401..af241e2d847 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SClass.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SClass.java @@ -30,6 +30,7 @@ import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.ScriptClassInfo; import org.elasticsearch.painless.WriterConstants; import org.elasticsearch.painless.lookup.PainlessLookup; +import org.elasticsearch.painless.ScriptRoot; import org.elasticsearch.painless.symbol.FunctionTable; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Label; @@ -87,7 +88,7 @@ public final class SClass extends AStatement { private CompilerSettings settings; - private FunctionTable table; + private ScriptRoot table; private Locals mainMethod; private final Set extractedVariables; private final List getMethods; @@ -134,30 +135,30 @@ public final class SClass extends AStatement { } public void analyze(PainlessLookup painlessLookup) { - table = new FunctionTable(); + table = new ScriptRoot(painlessLookup, settings, scriptClassInfo, this); for (SFunction function : functions) { function.generateSignature(painlessLookup); String key = FunctionTable.buildLocalFunctionKey(function.name, function.parameters.size()); - if (table.getFunction(key) != null) { - throw createError(new IllegalArgumentException("function [" + key + "] already defined")); + if (table.getFunctionTable().getFunction(key) != null) { + throw createError(new IllegalArgumentException("Illegal duplicate functions [" + key + "].")); } - table.addFunction(function.name, function.returnType, function.typeParameters, false); + table.getFunctionTable().addFunction(function.name, function.returnType, function.typeParameters, false); } - Locals locals = Locals.newProgramScope(scriptClassInfo, painlessLookup); + Locals locals = Locals.newProgramScope(); analyze(table, locals); } @Override - void analyze(FunctionTable functions, Locals program) { + void analyze(ScriptRoot scriptRoot, Locals program) { for (SFunction function : this.functions) { Locals functionLocals = Locals.newFunctionScope(program, function.returnType, function.parameters, settings.getMaxLoopCounter()); - function.analyze(functions, functionLocals); + function.analyze(scriptRoot, functionLocals); } if (statements == null || statements.isEmpty()) { @@ -188,8 +189,7 @@ public final class SClass extends AStatement { } statement.lastSource = statement == last; - - statement.analyze(functions, mainMethod); + statement.analyze(scriptRoot, mainMethod); methodEscape = statement.methodEscape; allEscape = statement.allEscape; @@ -348,7 +348,7 @@ public final class SClass extends AStatement { bytes = classWriter.getClassBytes(); Map statics = new HashMap<>(); - statics.put("$FUNCTIONS", table); + statics.put("$FUNCTIONS", table.getFunctionTable()); for (Map.Entry instanceBinding : globals.getInstanceBindings().entrySet()) { statics.put(instanceBinding.getValue(), instanceBinding.getKey()); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SContinue.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SContinue.java index 9b85e92f96b..54e6d5c04e2 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SContinue.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SContinue.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Set; @@ -49,7 +49,7 @@ public final class SContinue extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (!inLoop) { throw createError(new IllegalArgumentException("Continue statement outside of a loop.")); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclBlock.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclBlock.java index ee83f8e44ca..c4b69574778 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclBlock.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclBlock.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Collections; import java.util.List; @@ -61,9 +61,9 @@ public final class SDeclBlock extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { for (SDeclaration declaration : declarations) { - declaration.analyze(functions, locals); + declaration.analyze(scriptRoot, locals); } statementCount = declarations.size(); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java index 4efe7258bb8..c6876d6ad9a 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java @@ -26,7 +26,7 @@ import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Locals.Variable; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Opcodes; import java.util.Objects; @@ -68,8 +68,8 @@ public final class SDeclaration extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { - Class clazz = locals.getPainlessLookup().canonicalTypeNameToType(this.type); + void analyze(ScriptRoot scriptRoot, Locals locals) { + Class clazz = scriptRoot.getPainlessLookup().canonicalTypeNameToType(this.type); if (clazz == null) { throw createError(new IllegalArgumentException("Not a type [" + this.type + "].")); @@ -77,8 +77,8 @@ public final class SDeclaration extends AStatement { if (expression != null) { expression.expected = clazz; - expression.analyze(functions, locals); - expression = expression.cast(functions, locals); + expression.analyze(scriptRoot, locals); + expression = expression.cast(scriptRoot, locals); } variable = locals.addVariable(location, clazz, name, false); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDo.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDo.java index 0add9e7ff07..298c29b72d9 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDo.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDo.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; @@ -68,7 +68,7 @@ public final class SDo extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { locals = Locals.newLocalScope(locals); if (block == null) { @@ -77,16 +77,15 @@ public final class SDo extends AStatement { block.beginLoop = true; block.inLoop = true; - - block.analyze(functions, locals); + block.analyze(scriptRoot, locals); if (block.loopEscape && !block.anyContinue) { throw createError(new IllegalArgumentException("Extraneous do while loop.")); } condition.expected = boolean.class; - condition.analyze(functions, locals); - condition = condition.cast(functions, locals); + condition.analyze(scriptRoot, locals); + condition = condition.cast(scriptRoot, locals); if (condition.constant != null) { continuous = (boolean)condition.constant; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SEach.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SEach.java index e23a6dbd876..6d02bc490b1 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SEach.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SEach.java @@ -28,7 +28,7 @@ import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessLookupUtility; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -75,12 +75,12 @@ public class SEach extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { - expression.analyze(functions, locals); + void analyze(ScriptRoot scriptRoot, Locals locals) { + expression.analyze(scriptRoot, locals); expression.expected = expression.actual; - expression = expression.cast(functions, locals); + expression = expression.cast(scriptRoot, locals); - Class clazz = locals.getPainlessLookup().canonicalTypeNameToType(this.type); + Class clazz = scriptRoot.getPainlessLookup().canonicalTypeNameToType(this.type); if (clazz == null) { throw createError(new IllegalArgumentException("Not a type [" + this.type + "].")); @@ -98,7 +98,7 @@ public class SEach extends AStatement { "[" + PainlessLookupUtility.typeToCanonicalTypeName(expression.actual) + "].")); } - sub.analyze(functions, locals); + sub.analyze(scriptRoot, locals); if (block == null) { throw createError(new IllegalArgumentException("Extraneous for each loop.")); @@ -106,7 +106,7 @@ public class SEach extends AStatement { block.beginLoop = true; block.inLoop = true; - block.analyze(functions, locals); + block.analyze(scriptRoot, locals); block.statementCount = Math.max(1, block.statementCount); if (block.loopEscape && !block.anyContinue) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java index 122876f1685..69526210f75 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -54,12 +54,12 @@ public final class SExpression extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { Class rtnType = locals.getReturnType(); boolean isVoid = rtnType == void.class; expression.read = lastSource && !isVoid; - expression.analyze(functions, locals); + expression.analyze(scriptRoot, locals); if (!lastSource && !expression.statement) { throw createError(new IllegalArgumentException("Not a statement.")); @@ -69,7 +69,7 @@ public final class SExpression extends AStatement { expression.expected = rtn ? rtnType : expression.actual; expression.internal = rtn; - expression = expression.cast(functions, locals); + expression = expression.cast(scriptRoot, locals); methodEscape = rtn; loopEscape = rtn; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFor.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFor.java index f7c4b4ee4bb..eabe03e5f1e 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFor.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFor.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; @@ -94,24 +94,24 @@ public final class SFor extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { locals = Locals.newLocalScope(locals); if (initializer != null) { if (initializer instanceof SDeclBlock) { - initializer.analyze(functions, locals); + initializer.analyze(scriptRoot, locals); } else if (initializer instanceof AExpression) { AExpression initializer = (AExpression)this.initializer; initializer.read = false; - initializer.analyze(functions, locals); + initializer.analyze(scriptRoot, locals); if (!initializer.statement) { throw createError(new IllegalArgumentException("Not a statement.")); } initializer.expected = initializer.actual; - this.initializer = initializer.cast(functions, locals); + this.initializer = initializer.cast(scriptRoot, locals); } else { throw createError(new IllegalStateException("Illegal tree structure.")); } @@ -119,8 +119,8 @@ public final class SFor extends AStatement { if (condition != null) { condition.expected = boolean.class; - condition.analyze(functions, locals); - condition = condition.cast(functions, locals); + condition.analyze(scriptRoot, locals); + condition = condition.cast(scriptRoot, locals); if (condition.constant != null) { continuous = (boolean)condition.constant; @@ -139,21 +139,21 @@ public final class SFor extends AStatement { if (afterthought != null) { afterthought.read = false; - afterthought.analyze(functions, locals); + afterthought.analyze(scriptRoot, locals); if (!afterthought.statement) { throw createError(new IllegalArgumentException("Not a statement.")); } afterthought.expected = afterthought.actual; - afterthought = afterthought.cast(functions, locals); + afterthought = afterthought.cast(scriptRoot, locals); } if (block != null) { block.beginLoop = true; block.inLoop = true; - block.analyze(functions, locals); + block.analyze(scriptRoot, locals); if (block.loopEscape && !block.anyContinue) { throw createError(new IllegalArgumentException("Extraneous for loop.")); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFunction.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFunction.java index 582ffb639b0..6b65f49be8f 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFunction.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFunction.java @@ -29,7 +29,7 @@ import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessLookup; import org.elasticsearch.painless.lookup.PainlessLookupUtility; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Opcodes; import java.lang.invoke.MethodType; @@ -127,7 +127,7 @@ public final class SFunction extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (block.statements.isEmpty()) { throw createError(new IllegalArgumentException("Cannot generate an empty function [" + name + "].")); } @@ -135,7 +135,7 @@ public final class SFunction extends AStatement { locals = Locals.newLocalScope(locals); block.lastSource = true; - block.analyze(functions, locals); + block.analyze(scriptRoot, locals); methodEscape = block.methodEscape; if (!methodEscape && returnType != void.class) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIf.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIf.java index f5d9e8172cf..32e1142a7f6 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIf.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIf.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; @@ -66,10 +66,10 @@ public final class SIf extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { condition.expected = boolean.class; - condition.analyze(functions, locals); - condition = condition.cast(functions, locals); + condition.analyze(scriptRoot, locals); + condition = condition.cast(scriptRoot, locals); if (condition.constant != null) { throw createError(new IllegalArgumentException("Extraneous if statement.")); @@ -83,7 +83,7 @@ public final class SIf extends AStatement { ifblock.inLoop = inLoop; ifblock.lastLoop = lastLoop; - ifblock.analyze(functions, Locals.newLocalScope(locals)); + ifblock.analyze(scriptRoot, Locals.newLocalScope(locals)); anyContinue = ifblock.anyContinue; anyBreak = ifblock.anyBreak; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIfElse.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIfElse.java index a594b842dfd..c0b6193d5c4 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIfElse.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SIfElse.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; @@ -79,10 +79,10 @@ public final class SIfElse extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { condition.expected = boolean.class; - condition.analyze(functions, locals); - condition = condition.cast(functions, locals); + condition.analyze(scriptRoot, locals); + condition = condition.cast(scriptRoot, locals); if (condition.constant != null) { throw createError(new IllegalArgumentException("Extraneous if statement.")); @@ -96,7 +96,7 @@ public final class SIfElse extends AStatement { ifblock.inLoop = inLoop; ifblock.lastLoop = lastLoop; - ifblock.analyze(functions, Locals.newLocalScope(locals)); + ifblock.analyze(scriptRoot, Locals.newLocalScope(locals)); anyContinue = ifblock.anyContinue; anyBreak = ifblock.anyBreak; @@ -110,7 +110,7 @@ public final class SIfElse extends AStatement { elseblock.inLoop = inLoop; elseblock.lastLoop = lastLoop; - elseblock.analyze(functions, Locals.newLocalScope(locals)); + elseblock.analyze(scriptRoot, Locals.newLocalScope(locals)); methodEscape = ifblock.methodEscape && elseblock.methodEscape; loopEscape = ifblock.loopEscape && elseblock.loopEscape; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java index 7ffc03f420c..3d264777e17 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java @@ -26,7 +26,7 @@ import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessLookupUtility; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Set; @@ -58,7 +58,7 @@ public final class SReturn extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (expression == null) { if (locals.getReturnType() != void.class) { throw location.createError(new ClassCastException("Cannot cast from " + @@ -68,8 +68,8 @@ public final class SReturn extends AStatement { } else { expression.expected = locals.getReturnType(); expression.internal = true; - expression.analyze(functions, locals); - expression = expression.cast(functions, locals); + expression.analyze(scriptRoot, locals); + expression = expression.cast(scriptRoot, locals); } methodEscape = true; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachArray.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachArray.java index 928c7cc59f7..2da43bd25fd 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachArray.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachArray.java @@ -29,7 +29,7 @@ import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; import org.elasticsearch.painless.lookup.PainlessCast; import org.elasticsearch.painless.lookup.PainlessLookupUtility; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; @@ -68,7 +68,7 @@ final class SSubEachArray extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { // We must store the array and index as variables for securing slots on the stack, and // also add the location offset to make the names unique in case of nested for each loops. array = locals.addVariable(location, expression.actual, "#array" + location.getOffset(), true); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachIterable.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachIterable.java index b029267d353..3b11f8821ef 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachIterable.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachIterable.java @@ -32,7 +32,7 @@ import org.elasticsearch.painless.lookup.PainlessCast; import org.elasticsearch.painless.lookup.PainlessLookupUtility; import org.elasticsearch.painless.lookup.PainlessMethod; import org.elasticsearch.painless.lookup.def; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; @@ -77,7 +77,7 @@ final class SSubEachIterable extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { // We must store the iterator as a variable for securing a slot on the stack, and // also add the location offset to make the name unique in case of nested for each loops. iterator = locals.addVariable(location, Iterator.class, "#itr" + location.getOffset(), true); @@ -85,7 +85,7 @@ final class SSubEachIterable extends AStatement { if (expression.actual == def.class) { method = null; } else { - method = locals.getPainlessLookup().lookupPainlessMethod(expression.actual, false, "iterator", 0); + method = scriptRoot.getPainlessLookup().lookupPainlessMethod(expression.actual, false, "iterator", 0); if (method == null) { throw createError(new IllegalArgumentException( diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SThrow.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SThrow.java index 3372613893b..e8184ccf84b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SThrow.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SThrow.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import java.util.Objects; import java.util.Set; @@ -54,10 +54,10 @@ public final class SThrow extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { expression.expected = Exception.class; - expression.analyze(functions, locals); - expression = expression.cast(functions, locals); + expression.analyze(scriptRoot, locals); + expression = expression.cast(scriptRoot, locals); methodEscape = true; loopEscape = true; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STry.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STry.java index ce6152cfed5..0923666cac3 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STry.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/STry.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import java.util.Collections; @@ -71,7 +71,7 @@ public final class STry extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { if (block == null) { throw createError(new IllegalArgumentException("Extraneous try statement.")); } @@ -80,7 +80,7 @@ public final class STry extends AStatement { block.inLoop = inLoop; block.lastLoop = lastLoop; - block.analyze(functions, Locals.newLocalScope(locals)); + block.analyze(scriptRoot, Locals.newLocalScope(locals)); methodEscape = block.methodEscape; loopEscape = block.loopEscape; @@ -95,7 +95,7 @@ public final class STry extends AStatement { catc.inLoop = inLoop; catc.lastLoop = lastLoop; - catc.analyze(functions, Locals.newLocalScope(locals)); + catc.analyze(scriptRoot, Locals.newLocalScope(locals)); methodEscape &= catc.methodEscape; loopEscape &= catc.loopEscape; diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SWhile.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SWhile.java index 4ea1263a3ce..85121e2a0ff 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SWhile.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SWhile.java @@ -25,7 +25,7 @@ import org.elasticsearch.painless.Globals; import org.elasticsearch.painless.Locals; import org.elasticsearch.painless.Location; import org.elasticsearch.painless.MethodWriter; -import org.elasticsearch.painless.symbol.FunctionTable; +import org.elasticsearch.painless.ScriptRoot; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; @@ -67,12 +67,12 @@ public final class SWhile extends AStatement { } @Override - void analyze(FunctionTable functions, Locals locals) { + void analyze(ScriptRoot scriptRoot, Locals locals) { locals = Locals.newLocalScope(locals); condition.expected = boolean.class; - condition.analyze(functions, locals); - condition = condition.cast(functions, locals); + condition.analyze(scriptRoot, locals); + condition = condition.cast(scriptRoot, locals); if (condition.constant != null) { continuous = (boolean)condition.constant; @@ -90,7 +90,7 @@ public final class SWhile extends AStatement { block.beginLoop = true; block.inLoop = true; - block.analyze(functions, locals); + block.analyze(scriptRoot, locals); if (block.loopEscape && !block.anyContinue) { throw createError(new IllegalArgumentException("Extraneous while loop.")); diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefOptimizationTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefOptimizationTests.java index 94487f0b56f..0a7c0cdcd0d 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefOptimizationTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/DefOptimizationTests.java @@ -459,11 +459,11 @@ public class DefOptimizationTests extends ScriptTestCase { public void testLambdaReturnType() { assertBytecodeExists("List l = new ArrayList(); l.removeIf(x -> x < 10)", - "synthetic lambda$0(Ljava/lang/Object;)Z"); + "synthetic lambda$synthetic$0(Ljava/lang/Object;)Z"); } public void testLambdaArguments() { assertBytecodeExists("List l = new ArrayList(); l.stream().mapToDouble(Double::valueOf).map(x -> x + 1)", - "synthetic lambda$0(D)D"); + "synthetic lambda$synthetic$0(D)D"); } } diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FunctionTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FunctionTests.java index 59ead7b0714..cc6d7b10447 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FunctionTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FunctionTests.java @@ -70,7 +70,7 @@ public class FunctionTests extends ScriptTestCase { Exception expected = expectScriptThrows(IllegalArgumentException.class, () -> { exec("void test(int x) {x = 2;} void test(def y) {y = 3;} test()"); }); - assertThat(expected.getMessage(), containsString("already defined")); + assertThat(expected.getMessage(), containsString("Illegal duplicate functions")); } public void testBadCastFromMethod() {