mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-24 22:09:24 +00:00
Improve painless compile-time exceptions
This commit is contained in:
parent
3ccd59592a
commit
b5393ce55e
@ -22,6 +22,7 @@ package org.elasticsearch.painless;
|
||||
import org.elasticsearch.painless.Definition.Cast;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.node.ANode;
|
||||
|
||||
/**
|
||||
* Used during the analysis phase to collect legal type casts and promotions
|
||||
@ -29,7 +30,7 @@ import org.elasticsearch.painless.Definition.Type;
|
||||
*/
|
||||
public final class AnalyzerCaster {
|
||||
|
||||
public static Cast getLegalCast(String location, Type actual, Type expected, boolean explicit, boolean internal) {
|
||||
public static Cast getLegalCast(Location location, Type actual, Type expected, boolean explicit, boolean internal) {
|
||||
if (actual.equals(expected)) {
|
||||
return null;
|
||||
}
|
||||
@ -653,11 +654,11 @@ public final class AnalyzerCaster {
|
||||
explicit && actual.clazz.isAssignableFrom(expected.clazz)) {
|
||||
return new Cast(actual, expected, explicit);
|
||||
} else {
|
||||
throw new ClassCastException("Error" + location + ": Cannot cast from [" + actual.name + "] to [" + expected.name + "].");
|
||||
throw location.createError(new ClassCastException("Cannot cast from [" + actual.name + "] to [" + expected.name + "]."));
|
||||
}
|
||||
}
|
||||
|
||||
public static Object constCast(final String location, final Object constant, final Cast cast) {
|
||||
public static Object constCast(Location location, final Object constant, final Cast cast) {
|
||||
final Sort fsort = cast.from.sort;
|
||||
final Sort tsort = cast.to.sort;
|
||||
|
||||
@ -685,12 +686,12 @@ public final class AnalyzerCaster {
|
||||
case FLOAT: return number.floatValue();
|
||||
case DOUBLE: return number.doubleValue();
|
||||
default:
|
||||
throw new IllegalStateException("Error" + location + ": Cannot cast from " +
|
||||
"[" + cast.from.clazz.getCanonicalName() + "] to [" + cast.to.clazz.getCanonicalName() + "].");
|
||||
throw location.createError(new IllegalStateException("Cannot cast from " +
|
||||
"[" + cast.from.clazz.getCanonicalName() + "] to [" + cast.to.clazz.getCanonicalName() + "]."));
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("Error" + location + ": Cannot cast from " +
|
||||
"[" + cast.from.clazz.getCanonicalName() + "] to [" + cast.to.clazz.getCanonicalName() + "].");
|
||||
throw location.createError(new IllegalStateException("Cannot cast from " +
|
||||
"[" + cast.from.clazz.getCanonicalName() + "] to [" + cast.to.clazz.getCanonicalName() + "]."));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ final class Compiler {
|
||||
}
|
||||
|
||||
Reserved reserved = new Reserved();
|
||||
SSource root = Walker.buildPainlessTree(source, reserved, settings);
|
||||
SSource root = Walker.buildPainlessTree(name, source, reserved, settings);
|
||||
Variables variables = Analyzer.analyze(reserved, root);
|
||||
BitSet expressions = new BitSet(source.length());
|
||||
|
||||
@ -132,7 +132,7 @@ final class Compiler {
|
||||
}
|
||||
|
||||
Reserved reserved = new Reserved();
|
||||
SSource root = Walker.buildPainlessTree(source, reserved, settings);
|
||||
SSource root = Walker.buildPainlessTree(name, source, reserved, settings);
|
||||
Variables variables = Analyzer.analyze(reserved, root);
|
||||
|
||||
return Writer.write(settings, name, source, variables, root, new BitSet(source.length()));
|
||||
|
@ -164,6 +164,11 @@ public final class Definition {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Constructor {
|
||||
|
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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 java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents a location in script code (name of script + character offset)
|
||||
*/
|
||||
public final class Location {
|
||||
private final String sourceName;
|
||||
private final int offset;
|
||||
|
||||
/**
|
||||
* Create a new Location
|
||||
* @param sourceName script's name
|
||||
* @param offset character offset of script element
|
||||
*/
|
||||
public Location(String sourceName, int offset) {
|
||||
this.sourceName = Objects.requireNonNull(sourceName);
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the script's name
|
||||
*/
|
||||
public String getSourceName() {
|
||||
return sourceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the character offset
|
||||
*/
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Augments an exception with this location's information.
|
||||
*/
|
||||
public RuntimeException createError(RuntimeException exception) {
|
||||
StackTraceElement element = new StackTraceElement(WriterConstants.CLASS_NAME, "compile", sourceName, offset + 1);
|
||||
StackTraceElement[] oldStack = exception.getStackTrace();
|
||||
StackTraceElement[] newStack = new StackTraceElement[oldStack.length + 1];
|
||||
System.arraycopy(oldStack, 0, newStack, 1, oldStack.length);
|
||||
newStack[0] = element;
|
||||
exception.setStackTrace(newStack);
|
||||
assert exception.getStackTrace().length == newStack.length : "non-writeable stacktrace for exception: " + exception.getClass();
|
||||
return exception;
|
||||
}
|
||||
|
||||
// This maximum length is theoretically 65535 bytes, but as it's CESU-8 encoded we dont know how large it is in bytes, so be safe
|
||||
private static final int MAX_NAME_LENGTH = 256;
|
||||
|
||||
/** Computes the file name (mostly important for stacktraces) */
|
||||
public static String computeSourceName(String scriptName, String source) {
|
||||
StringBuilder fileName = new StringBuilder();
|
||||
if (scriptName.equals(PainlessScriptEngineService.INLINE_NAME)) {
|
||||
// its an anonymous script, include at least a portion of the source to help identify which one it is
|
||||
// but don't create stacktraces with filenames that contain newlines or huge names.
|
||||
|
||||
// truncate to the first newline
|
||||
int limit = source.indexOf('\n');
|
||||
if (limit >= 0) {
|
||||
int limit2 = source.indexOf('\r');
|
||||
if (limit2 >= 0) {
|
||||
limit = Math.min(limit, limit2);
|
||||
}
|
||||
} else {
|
||||
limit = source.length();
|
||||
}
|
||||
|
||||
// truncate to our limit
|
||||
limit = Math.min(limit, MAX_NAME_LENGTH);
|
||||
fileName.append(source, 0, limit);
|
||||
|
||||
// if we truncated, make it obvious
|
||||
if (limit != source.length()) {
|
||||
fileName.append(" ...");
|
||||
}
|
||||
fileName.append(" @ <inline script>");
|
||||
} else {
|
||||
// its a named script, just use the name
|
||||
// but don't trust this has a reasonable length!
|
||||
if (scriptName.length() > MAX_NAME_LENGTH) {
|
||||
fileName.append(scriptName, 0, MAX_NAME_LENGTH);
|
||||
fileName.append(" ...");
|
||||
} else {
|
||||
fileName.append(scriptName);
|
||||
}
|
||||
}
|
||||
return fileName.toString();
|
||||
}
|
||||
}
|
@ -114,7 +114,8 @@ public final class MethodWriter extends GeneratorAdapter {
|
||||
* <p>
|
||||
* This is invoked for each statement boundary (leaf {@code S*} nodes).
|
||||
*/
|
||||
public void writeStatementOffset(int offset) {
|
||||
public void writeStatementOffset(Location location) {
|
||||
int offset = location.getOffset();
|
||||
// ensure we don't have duplicate stuff going in here. can catch bugs
|
||||
// (e.g. nodes get assigned wrong offsets by antlr walker)
|
||||
assert statements.get(offset) == false;
|
||||
@ -126,16 +127,16 @@ public final class MethodWriter extends GeneratorAdapter {
|
||||
* <p>
|
||||
* This is invoked before instructions that can hit exceptions.
|
||||
*/
|
||||
public void writeDebugInfo(int offset) {
|
||||
public void writeDebugInfo(Location location) {
|
||||
// TODO: maybe track these in bitsets too? this is trickier...
|
||||
Label label = new Label();
|
||||
visitLabel(label);
|
||||
visitLineNumber(offset + 1, label);
|
||||
visitLineNumber(location.getOffset() + 1, label);
|
||||
}
|
||||
|
||||
public void writeLoopCounter(int slot, int count, int offset) {
|
||||
public void writeLoopCounter(int slot, int count, Location location) {
|
||||
if (slot > -1) {
|
||||
writeDebugInfo(offset);
|
||||
writeDebugInfo(location);
|
||||
final Label end = new Label();
|
||||
|
||||
iinc(slot, -count);
|
||||
@ -281,14 +282,14 @@ public final class MethodWriter extends GeneratorAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
public void writeBinaryInstruction(final String location, final Type type, final Operation operation) {
|
||||
public void writeBinaryInstruction(Location location, Type type, Operation operation) {
|
||||
final Sort sort = type.sort;
|
||||
|
||||
if ((sort == Sort.FLOAT || sort == Sort.DOUBLE) &&
|
||||
(operation == Operation.LSH || operation == Operation.USH ||
|
||||
operation == Operation.RSH || operation == Operation.BWAND ||
|
||||
operation == Operation.XOR || operation == Operation.BWOR)) {
|
||||
throw new IllegalStateException("Error " + location + ": Illegal tree structure.");
|
||||
throw location.createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
if (sort == Sort.DEF) {
|
||||
@ -305,7 +306,7 @@ public final class MethodWriter extends GeneratorAdapter {
|
||||
case XOR: invokeStatic(DEF_UTIL_TYPE, DEF_XOR_CALL); break;
|
||||
case BWOR: invokeStatic(DEF_UTIL_TYPE, DEF_OR_CALL); break;
|
||||
default:
|
||||
throw new IllegalStateException("Error " + location + ": Illegal tree structure.");
|
||||
throw location.createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
} else {
|
||||
switch (operation) {
|
||||
@ -321,7 +322,7 @@ public final class MethodWriter extends GeneratorAdapter {
|
||||
case XOR: math(GeneratorAdapter.XOR, type.type); break;
|
||||
case BWOR: math(GeneratorAdapter.OR, type.type); break;
|
||||
default:
|
||||
throw new IllegalStateException("Error " + location + ": Illegal tree structure.");
|
||||
throw location.createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import org.elasticsearch.script.CompiledScript;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.LeafSearchScript;
|
||||
import org.elasticsearch.script.ScriptEngineService;
|
||||
import org.elasticsearch.script.ScriptException;
|
||||
import org.elasticsearch.script.SearchScript;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
@ -38,7 +39,10 @@ import java.security.AccessController;
|
||||
import java.security.Permissions;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -147,13 +151,17 @@ public final class PainlessScriptEngineService extends AbstractComponent impleme
|
||||
}
|
||||
});
|
||||
|
||||
// Drop all permissions to actually compile the code itself.
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Executable>() {
|
||||
@Override
|
||||
public Executable run() {
|
||||
return Compiler.compile(loader, scriptName == null ? INLINE_NAME : scriptName, scriptSource, compilerSettings);
|
||||
}
|
||||
}, COMPILATION_CONTEXT);
|
||||
try {
|
||||
// Drop all permissions to actually compile the code itself.
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Executable>() {
|
||||
@Override
|
||||
public Executable run() {
|
||||
return Compiler.compile(loader, scriptName == null ? INLINE_NAME : scriptName, scriptSource, compilerSettings);
|
||||
}
|
||||
}, COMPILATION_CONTEXT);
|
||||
} catch (Exception e) {
|
||||
throw convertToScriptException(scriptName == null ? scriptSource : scriptName, scriptSource, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -213,4 +221,51 @@ public final class PainlessScriptEngineService extends AbstractComponent impleme
|
||||
public void close() {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
private ScriptException convertToScriptException(String scriptName, String scriptSource, Throwable t) {
|
||||
// create a script stack: this is just the script portion
|
||||
List<String> scriptStack = new ArrayList<>();
|
||||
for (StackTraceElement element : t.getStackTrace()) {
|
||||
if (WriterConstants.CLASS_NAME.equals(element.getClassName())) {
|
||||
// found the script portion
|
||||
int offset = element.getLineNumber();
|
||||
if (offset == -1) {
|
||||
scriptStack.add("<<< unknown portion of script >>>");
|
||||
} else {
|
||||
offset--; // offset is 1 based, line numbers must be!
|
||||
int startOffset = getPreviousStatement(scriptSource, offset);
|
||||
int endOffset = getNextStatement(scriptSource, offset);
|
||||
StringBuilder snippet = new StringBuilder();
|
||||
if (startOffset > 0) {
|
||||
snippet.append("... ");
|
||||
}
|
||||
snippet.append(scriptSource.substring(startOffset, endOffset));
|
||||
if (endOffset < scriptSource.length()) {
|
||||
snippet.append(" ...");
|
||||
}
|
||||
scriptStack.add(snippet.toString());
|
||||
StringBuilder pointer = new StringBuilder();
|
||||
if (startOffset > 0) {
|
||||
pointer.append(" ");
|
||||
}
|
||||
for (int i = startOffset; i < offset; i++) {
|
||||
pointer.append(' ');
|
||||
}
|
||||
pointer.append("^---- HERE");
|
||||
scriptStack.add(pointer.toString());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
throw new ScriptException("compile error", t, scriptStack, scriptSource, PainlessScriptEngineService.NAME);
|
||||
}
|
||||
|
||||
// very simple heuristic: +/- 25 chars. can be improved later.
|
||||
private int getPreviousStatement(String scriptSource, int offset) {
|
||||
return Math.max(0, offset - 25);
|
||||
}
|
||||
|
||||
private int getNextStatement(String scriptSource, int offset) {
|
||||
return Math.min(scriptSource.length(), offset + 25);
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +173,8 @@ final class ScriptImpl implements ExecutableScript, LeafSearchScript {
|
||||
/** returns true for methods that are part of the runtime */
|
||||
private static boolean shouldFilter(StackTraceElement element) {
|
||||
return element.getClassName().startsWith("org.elasticsearch.painless.") ||
|
||||
element.getClassName().startsWith("java.lang.invoke.");
|
||||
element.getClassName().startsWith("java.lang.invoke.") ||
|
||||
element.getClassName().startsWith("sun.invoke.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,7 +69,7 @@ public final class Variables {
|
||||
}
|
||||
|
||||
public static final class Variable {
|
||||
public final String location;
|
||||
public final Location location;
|
||||
public final String name;
|
||||
public final Type type;
|
||||
public final int slot;
|
||||
@ -77,7 +77,7 @@ public final class Variables {
|
||||
|
||||
public boolean read = false;
|
||||
|
||||
private Variable(String location, String name, Type type, int slot, boolean readonly) {
|
||||
private Variable(Location location, String name, Type type, int slot, boolean readonly) {
|
||||
this.location = location;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
@ -88,6 +88,7 @@ public final class Variables {
|
||||
|
||||
final Reserved reserved;
|
||||
|
||||
// TODO: this datastructure runs in linear time for nearly all operations. use linkedhashset instead?
|
||||
private final Deque<Integer> scopes = new ArrayDeque<>();
|
||||
private final Deque<Variable> variables = new ArrayDeque<>();
|
||||
|
||||
@ -99,35 +100,35 @@ public final class Variables {
|
||||
// Method variables.
|
||||
|
||||
// This reference. Internal use only.
|
||||
addVariable("[" + Reserved.THIS + "]", Definition.getType("Object"), Reserved.THIS, true, true);
|
||||
addVariable(null, Definition.getType("Object"), Reserved.THIS, true, true);
|
||||
|
||||
// Input map of variables passed to the script.
|
||||
addVariable("[" + Reserved.PARAMS + "]", Definition.getType("Map"), Reserved.PARAMS, true, true);
|
||||
addVariable(null, Definition.getType("Map"), Reserved.PARAMS, true, true);
|
||||
|
||||
// Scorer parameter passed to the script. Internal use only.
|
||||
addVariable("[" + Reserved.SCORER + "]", Definition.DEF_TYPE, Reserved.SCORER, true, true);
|
||||
addVariable(null, Definition.DEF_TYPE, Reserved.SCORER, true, true);
|
||||
|
||||
// Doc parameter passed to the script. TODO: Currently working as a Map, we can do better?
|
||||
addVariable("[" + Reserved.DOC + "]", Definition.getType("Map"), Reserved.DOC, true, true);
|
||||
addVariable(null, Definition.getType("Map"), Reserved.DOC, true, true);
|
||||
|
||||
// Aggregation _value parameter passed to the script.
|
||||
addVariable("[" + Reserved.VALUE + "]", Definition.DEF_TYPE, Reserved.VALUE, true, true);
|
||||
addVariable(null, Definition.DEF_TYPE, Reserved.VALUE, true, true);
|
||||
|
||||
// Shortcut variables.
|
||||
|
||||
// Document's score as a read-only double.
|
||||
if (reserved.score) {
|
||||
addVariable("[" + Reserved.SCORE + "]", Definition.DOUBLE_TYPE, Reserved.SCORE, true, true);
|
||||
addVariable(null, Definition.DOUBLE_TYPE, Reserved.SCORE, true, true);
|
||||
}
|
||||
|
||||
// The ctx map set by executable scripts as a read-only map.
|
||||
if (reserved.ctx) {
|
||||
addVariable("[" + Reserved.CTX + "]", Definition.getType("Map"), Reserved.CTX, true, true);
|
||||
addVariable(null, Definition.getType("Map"), Reserved.CTX, true, true);
|
||||
}
|
||||
|
||||
// Loop counter to catch infinite loops. Internal use only.
|
||||
if (reserved.loop) {
|
||||
addVariable("[" + Reserved.LOOP + "]", Definition.INT_TYPE, Reserved.LOOP, true, true);
|
||||
addVariable(null, Definition.INT_TYPE, Reserved.LOOP, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,19 +138,20 @@ public final class Variables {
|
||||
|
||||
public void decrementScope() {
|
||||
int remove = scopes.pop();
|
||||
|
||||
|
||||
while (remove > 0) {
|
||||
Variable variable = variables.pop();
|
||||
|
||||
Variable variable = variables.pop();
|
||||
|
||||
// TODO: is this working? the code reads backwards...
|
||||
if (variable.read) {
|
||||
throw new IllegalArgumentException("Error [" + variable.location + "]: Variable [" + variable.name + "] never used.");
|
||||
throw variable.location.createError(new IllegalArgumentException("Variable [" + variable.name + "] never used."));
|
||||
}
|
||||
|
||||
|
||||
--remove;
|
||||
}
|
||||
}
|
||||
|
||||
public Variable getVariable(String location, String name) {
|
||||
public Variable getVariable(Location location, String name) {
|
||||
Iterator<Variable> itr = variables.iterator();
|
||||
|
||||
while (itr.hasNext()) {
|
||||
@ -160,20 +162,20 @@ public final class Variables {
|
||||
}
|
||||
}
|
||||
|
||||
if (location != null) {
|
||||
throw new IllegalArgumentException("Error " + location + ": Variable [" + name + "] not defined.");
|
||||
}
|
||||
|
||||
return null;
|
||||
throw location.createError(new IllegalArgumentException("Variable [" + name + "] not defined."));
|
||||
}
|
||||
|
||||
public Variable addVariable(String location, Type type, String name, boolean readonly, boolean reserved) {
|
||||
private boolean variableExists(String name) {
|
||||
return variables.contains(name);
|
||||
}
|
||||
|
||||
public Variable addVariable(Location location, Type type, String name, boolean readonly, boolean reserved) {
|
||||
if (!reserved && this.reserved.isReserved(name)) {
|
||||
throw new IllegalArgumentException("Error " + location + ": Variable name [" + name + "] is reserved.");
|
||||
throw location.createError(new IllegalArgumentException("Variable name [" + name + "] is reserved."));
|
||||
}
|
||||
|
||||
if (getVariable(null, name) != null) {
|
||||
throw new IllegalArgumentException("Error " + location + ": Variable name [" + name + "] already defined.");
|
||||
if (variableExists(name)) {
|
||||
throw new IllegalArgumentException("Variable name [" + name + "] already defined.");
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -72,9 +72,6 @@ final class Writer {
|
||||
writeEnd();
|
||||
}
|
||||
|
||||
// This maximum length is theoretically 65535 bytes, but as it's CESU-8 encoded we dont know how large it is in bytes, so be safe
|
||||
private static final int MAX_NAME_LENGTH = 256;
|
||||
|
||||
private void writeBegin() {
|
||||
final int version = Opcodes.V1_8;
|
||||
final int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_FINAL;
|
||||
@ -86,47 +83,7 @@ final class Writer {
|
||||
new String[] { WriterConstants.NEEDS_SCORE_TYPE.getInternalName() } : null;
|
||||
|
||||
writer.visit(version, access, name, null, base, interfaces);
|
||||
writer.visitSource(computeSourceName(), null);
|
||||
}
|
||||
|
||||
/** Computes the file name (mostly important for stacktraces) */
|
||||
private String computeSourceName() {
|
||||
StringBuilder fileName = new StringBuilder();
|
||||
if (scriptName.equals(PainlessScriptEngineService.INLINE_NAME)) {
|
||||
// its an anonymous script, include at least a portion of the source to help identify which one it is
|
||||
// but don't create stacktraces with filenames that contain newlines or huge names.
|
||||
|
||||
// truncate to the first newline
|
||||
int limit = source.indexOf('\n');
|
||||
if (limit >= 0) {
|
||||
int limit2 = source.indexOf('\r');
|
||||
if (limit2 >= 0) {
|
||||
limit = Math.min(limit, limit2);
|
||||
}
|
||||
} else {
|
||||
limit = source.length();
|
||||
}
|
||||
|
||||
// truncate to our limit
|
||||
limit = Math.min(limit, MAX_NAME_LENGTH);
|
||||
fileName.append(source, 0, limit);
|
||||
|
||||
// if we truncated, make it obvious
|
||||
if (limit != source.length()) {
|
||||
fileName.append(" ...");
|
||||
}
|
||||
fileName.append(" @ <inline script>");
|
||||
} else {
|
||||
// its a named script, just use the name
|
||||
// but don't trust this has a reasonable length!
|
||||
if (scriptName.length() > MAX_NAME_LENGTH) {
|
||||
fileName.append(scriptName, 0, MAX_NAME_LENGTH);
|
||||
fileName.append(" ...");
|
||||
} else {
|
||||
fileName.append(scriptName);
|
||||
}
|
||||
}
|
||||
return fileName.toString();
|
||||
writer.visitSource(Location.computeSourceName(scriptName,source), null);
|
||||
}
|
||||
|
||||
private void writeConstructor() {
|
||||
|
@ -22,16 +22,17 @@ package org.elasticsearch.painless.antlr;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.LexerNoViableAltException;
|
||||
import org.antlr.v4.runtime.misc.Interval;
|
||||
|
||||
import java.text.ParseException;
|
||||
import org.elasticsearch.painless.Location;
|
||||
|
||||
/**
|
||||
* A lexer that will override the default error behavior to fail on the first error.
|
||||
*/
|
||||
final class ErrorHandlingLexer extends PainlessLexer {
|
||||
final String sourceName;
|
||||
|
||||
ErrorHandlingLexer(final CharStream charStream) {
|
||||
ErrorHandlingLexer(CharStream charStream, String sourceName) {
|
||||
super(charStream);
|
||||
this.sourceName = sourceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -40,11 +41,7 @@ final class ErrorHandlingLexer extends PainlessLexer {
|
||||
final int startIndex = lnvae.getStartIndex();
|
||||
final String text = charStream.getText(Interval.of(startIndex, charStream.index()));
|
||||
|
||||
final ParseException parseException = new ParseException("Error [" + _tokenStartLine + ":" +
|
||||
_tokenStartCharPositionInLine + "]: unexpected character [" +
|
||||
getErrorDisplay(text) + "].", _tokenStartCharIndex);
|
||||
parseException.initCause(lnvae);
|
||||
|
||||
throw new RuntimeException(parseException);
|
||||
Location location = new Location(sourceName, _tokenStartCharIndex);
|
||||
throw location.createError(new IllegalArgumentException("unexpected character [" + getErrorDisplay(text) + "].", lnvae));
|
||||
}
|
||||
}
|
||||
|
@ -25,13 +25,17 @@ import org.antlr.v4.runtime.NoViableAltException;
|
||||
import org.antlr.v4.runtime.Parser;
|
||||
import org.antlr.v4.runtime.RecognitionException;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
import java.text.ParseException;
|
||||
import org.elasticsearch.painless.Location;
|
||||
|
||||
/**
|
||||
* An error strategy that will override the default error behavior to fail on the first parser error.
|
||||
*/
|
||||
final class ParserErrorStrategy extends DefaultErrorStrategy {
|
||||
final String sourceName;
|
||||
|
||||
ParserErrorStrategy(String sourceName) {
|
||||
this.sourceName = sourceName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recover(final Parser recognizer, final RecognitionException re) {
|
||||
@ -39,38 +43,32 @@ final class ParserErrorStrategy extends DefaultErrorStrategy {
|
||||
String message;
|
||||
|
||||
if (token == null) {
|
||||
message = "Error: no parse token found.";
|
||||
message = "no parse token found.";
|
||||
} else if (re instanceof InputMismatchException) {
|
||||
message = "Error[" + token.getLine() + ":" + token.getCharPositionInLine() + "]:" +
|
||||
" unexpected token [" + getTokenErrorDisplay(token) + "]" +
|
||||
message = "unexpected token [" + getTokenErrorDisplay(token) + "]" +
|
||||
" was expecting one of [" + re.getExpectedTokens().toString(recognizer.getVocabulary()) + "].";
|
||||
} else if (re instanceof NoViableAltException) {
|
||||
if (token.getType() == PainlessParser.EOF) {
|
||||
message = "Error: unexpected end of script.";
|
||||
message = "unexpected end of script.";
|
||||
} else {
|
||||
message = "Error[" + token.getLine() + ":" + token.getCharPositionInLine() + "]:" +
|
||||
"invalid sequence of tokens near [" + getTokenErrorDisplay(token) + "].";
|
||||
message = "invalid sequence of tokens near [" + getTokenErrorDisplay(token) + "].";
|
||||
}
|
||||
} else {
|
||||
message = "Error[" + token.getLine() + ":" + token.getCharPositionInLine() + "]:" +
|
||||
" unexpected token near [" + getTokenErrorDisplay(token) + "].";
|
||||
message = "unexpected token near [" + getTokenErrorDisplay(token) + "].";
|
||||
}
|
||||
|
||||
final ParseException parseException = new ParseException(message, token == null ? -1 : token.getStartIndex());
|
||||
parseException.initCause(re);
|
||||
|
||||
throw new RuntimeException(parseException);
|
||||
Location location = new Location(sourceName, token == null ? -1 : token.getStartIndex());
|
||||
throw location.createError(new IllegalArgumentException(message, re));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token recoverInline(final Parser recognizer) throws RecognitionException {
|
||||
final Token token = recognizer.getCurrentToken();
|
||||
final String message = "Error[" + token.getLine() + ":" + token.getCharPositionInLine() + "]:" +
|
||||
" unexpected token [" + getTokenErrorDisplay(token) + "]" +
|
||||
final String message = "unexpected token [" + getTokenErrorDisplay(token) + "]" +
|
||||
" was expecting one of [" + recognizer.getExpectedTokens().toString(recognizer.getVocabulary()) + "].";
|
||||
final ParseException parseException = new ParseException(message, token.getStartIndex());
|
||||
|
||||
throw new RuntimeException(parseException);
|
||||
Location location = new Location(sourceName, token.getStartIndex());
|
||||
throw location.createError(new IllegalArgumentException(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,6 +28,7 @@ import org.antlr.v4.runtime.RecognitionException;
|
||||
import org.antlr.v4.runtime.Recognizer;
|
||||
import org.antlr.v4.runtime.atn.PredictionMode;
|
||||
import org.elasticsearch.painless.CompilerSettings;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Operation;
|
||||
import org.elasticsearch.painless.Variables.Reserved;
|
||||
import org.elasticsearch.painless.antlr.PainlessParser.AfterthoughtContext;
|
||||
@ -135,25 +136,27 @@ import java.util.List;
|
||||
*/
|
||||
public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
|
||||
public static SSource buildPainlessTree(String source, Reserved reserved, CompilerSettings settings) {
|
||||
return new Walker(source, reserved, settings).source;
|
||||
public static SSource buildPainlessTree(String name, String sourceText, Reserved reserved, CompilerSettings settings) {
|
||||
return new Walker(name, sourceText, reserved, settings).source;
|
||||
}
|
||||
|
||||
private final Reserved reserved;
|
||||
private final SSource source;
|
||||
private final CompilerSettings settings;
|
||||
private final String sourceName;
|
||||
|
||||
private Walker(String source, Reserved reserved, CompilerSettings settings) {
|
||||
private Walker(String name, String sourceText, Reserved reserved, CompilerSettings settings) {
|
||||
this.reserved = reserved;
|
||||
this.settings = settings;
|
||||
this.source = (SSource)visit(buildAntlrTree(source));
|
||||
this.sourceName = Location.computeSourceName(name, sourceText);
|
||||
this.source = (SSource)visit(buildAntlrTree(sourceText));
|
||||
}
|
||||
|
||||
private SourceContext buildAntlrTree(String source) {
|
||||
ANTLRInputStream stream = new ANTLRInputStream(source);
|
||||
PainlessLexer lexer = new ErrorHandlingLexer(stream);
|
||||
PainlessLexer lexer = new ErrorHandlingLexer(stream, sourceName);
|
||||
PainlessParser parser = new PainlessParser(new CommonTokenStream(lexer));
|
||||
ParserErrorStrategy strategy = new ParserErrorStrategy();
|
||||
ParserErrorStrategy strategy = new ParserErrorStrategy(sourceName);
|
||||
|
||||
lexer.removeErrorListeners();
|
||||
parser.removeErrorListeners();
|
||||
@ -185,16 +188,8 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
parser.getInterpreter().setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);
|
||||
}
|
||||
|
||||
private int line(ParserRuleContext ctx) {
|
||||
return ctx.getStart().getLine();
|
||||
}
|
||||
|
||||
private int offset(ParserRuleContext ctx) {
|
||||
return ctx.getStart().getStartIndex();
|
||||
}
|
||||
|
||||
private String location(ParserRuleContext ctx) {
|
||||
return "[ " + ctx.getStart().getLine() + " : " + ctx.getStart().getCharPositionInLine() + " ]";
|
||||
private Location location(ParserRuleContext ctx) {
|
||||
return new Location(sourceName, ctx.getStart().getStartIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -205,7 +200,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
statements.add((AStatement)visit(statement));
|
||||
}
|
||||
|
||||
return new SSource(line(ctx), offset(ctx), location(ctx), statements);
|
||||
return new SSource(location(ctx), statements);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -216,9 +211,9 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
if (ctx.trailer().size() > 1) {
|
||||
SBlock elseblock = (SBlock)visit(ctx.trailer(1));
|
||||
|
||||
return new SIfElse(line(ctx), offset(ctx), location(ctx), expression, ifblock, elseblock);
|
||||
return new SIfElse(location(ctx), expression, ifblock, elseblock);
|
||||
} else {
|
||||
return new SIf(line(ctx), offset(ctx), location(ctx), expression, ifblock);
|
||||
return new SIf(location(ctx), expression, ifblock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,11 +228,11 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
if (ctx.trailer() != null) {
|
||||
SBlock block = (SBlock)visit(ctx.trailer());
|
||||
|
||||
return new SWhile(line(ctx), offset(ctx), location(ctx), settings.getMaxLoopCounter(), expression, block);
|
||||
return new SWhile(location(ctx), settings.getMaxLoopCounter(), expression, block);
|
||||
} else if (ctx.empty() != null) {
|
||||
return new SWhile(line(ctx), offset(ctx), location(ctx), settings.getMaxLoopCounter(), expression, null);
|
||||
return new SWhile(location(ctx), settings.getMaxLoopCounter(), expression, null);
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException(" Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,7 +245,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
AExpression expression = (AExpression)visitExpression(ctx.expression());
|
||||
SBlock block = (SBlock)visit(ctx.block());
|
||||
|
||||
return new SDo(line(ctx), offset(ctx), location(ctx), settings.getMaxLoopCounter(), block, expression);
|
||||
return new SDo(location(ctx), settings.getMaxLoopCounter(), block, expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -266,13 +261,13 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
if (ctx.trailer() != null) {
|
||||
SBlock block = (SBlock)visit(ctx.trailer());
|
||||
|
||||
return new SFor(line(ctx), offset(ctx), location(ctx),
|
||||
return new SFor(location(ctx),
|
||||
settings.getMaxLoopCounter(), initializer, expression, afterthought, block);
|
||||
} else if (ctx.empty() != null) {
|
||||
return new SFor(line(ctx), offset(ctx), location(ctx),
|
||||
return new SFor(location(ctx),
|
||||
settings.getMaxLoopCounter(), initializer, expression, afterthought, null);
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,19 +278,19 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public Object visitContinue(ContinueContext ctx) {
|
||||
return new SContinue(line(ctx), offset(ctx), location(ctx));
|
||||
return new SContinue(location(ctx));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitBreak(BreakContext ctx) {
|
||||
return new SBreak(line(ctx), offset(ctx), location(ctx));
|
||||
return new SBreak(location(ctx));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitReturn(ReturnContext ctx) {
|
||||
AExpression expression = (AExpression)visitExpression(ctx.expression());
|
||||
|
||||
return new SReturn(line(ctx), offset(ctx), location(ctx), expression);
|
||||
return new SReturn(location(ctx), expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -307,21 +302,21 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
catches.add((SCatch)visit(trap));
|
||||
}
|
||||
|
||||
return new STry(line(ctx), offset(ctx), location(ctx), block, catches);
|
||||
return new STry(location(ctx), block, catches);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitThrow(ThrowContext ctx) {
|
||||
AExpression expression = (AExpression)visitExpression(ctx.expression());
|
||||
|
||||
return new SThrow(line(ctx), offset(ctx), location(ctx), expression);
|
||||
return new SThrow(location(ctx), expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitExpr(ExprContext ctx) {
|
||||
AExpression expression = (AExpression)visitExpression(ctx.expression());
|
||||
|
||||
return new SExpression(line(ctx), offset(ctx), location(ctx), expression);
|
||||
return new SExpression(location(ctx), expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -332,9 +327,9 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
List<AStatement> statements = new ArrayList<>();
|
||||
statements.add((AStatement)visit(ctx.statement()));
|
||||
|
||||
return new SBlock(line(ctx), offset(ctx), location(ctx), statements);
|
||||
return new SBlock(location(ctx), statements);
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -349,13 +344,13 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
statements.add((AStatement)visit(statement));
|
||||
}
|
||||
|
||||
return new SBlock(line(ctx), offset(ctx), location(ctx), statements);
|
||||
return new SBlock(location(ctx), statements);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitEmpty(EmptyContext ctx) {
|
||||
throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -365,7 +360,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
} else if (ctx.expression() != null) {
|
||||
return visitExpression(ctx.expression());
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -383,25 +378,25 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
String name = declvar.ID().getText();
|
||||
AExpression expression = declvar.expression() == null ? null : (AExpression)visitExpression(declvar.expression());
|
||||
|
||||
declarations.add(new SDeclaration(line(declvar), offset(declvar), location(declvar), type, name, expression));
|
||||
declarations.add(new SDeclaration(location(declvar), type, name, expression));
|
||||
}
|
||||
|
||||
return new SDeclBlock(line(ctx), offset(ctx), location(ctx), declarations);
|
||||
return new SDeclBlock(location(ctx), declarations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitDecltype(DecltypeContext ctx) {
|
||||
throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitFuncref(FuncrefContext ctx) {
|
||||
return new EFunctionRef(line(ctx), offset(ctx), location(ctx), ctx.TYPE().getText(), ctx.ID().getText());
|
||||
return new EFunctionRef(location(ctx), ctx.TYPE().getText(), ctx.ID().getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitDeclvar(DeclvarContext ctx) {
|
||||
throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -410,12 +405,12 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
String name = ctx.ID().getText();
|
||||
SBlock block = (SBlock)visit(ctx.block());
|
||||
|
||||
return new SCatch(line(ctx), offset(ctx), location(ctx), type, name, block);
|
||||
return new SCatch(location(ctx), type, name, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitDelimiter(DelimiterContext ctx) {
|
||||
throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
private Object visitExpression(ExpressionContext ctx) {
|
||||
@ -425,7 +420,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<ALink> links = (List<ALink>)expression;
|
||||
|
||||
return new EChain(line(ctx), offset(ctx), location(ctx), links, false, false, null, null);
|
||||
return new EChain(location(ctx), links, false, false, null, null);
|
||||
} else {
|
||||
return expression;
|
||||
}
|
||||
@ -465,10 +460,10 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
} else if (ctx.BWOR() != null) {
|
||||
operation = Operation.BWOR;
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
||||
throw location(ctx).createError(new IllegalStateException("Unexpected state."));
|
||||
}
|
||||
|
||||
return new EBinary(line(ctx), offset(ctx), location(ctx), operation, left, right);
|
||||
return new EBinary(location(ctx), operation, left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -494,10 +489,10 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
} else if (ctx.NER() != null) {
|
||||
operation = Operation.NER;
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
||||
throw location(ctx).createError(new IllegalStateException("Unexpected state."));
|
||||
}
|
||||
|
||||
return new EComp(line(ctx), offset(ctx), location(ctx), operation, left, right);
|
||||
return new EComp(location(ctx), operation, left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -511,10 +506,10 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
} else if (ctx.BOOLOR() != null) {
|
||||
operation = Operation.OR;
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + ": Unexpected state.");
|
||||
throw location(ctx).createError(new IllegalStateException("Unexpected state."));
|
||||
}
|
||||
|
||||
return new EBool(line(ctx), offset(ctx), location(ctx), operation, left, right);
|
||||
return new EBool(location(ctx), operation, left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -523,7 +518,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
AExpression left = (AExpression)visitExpression(ctx.expression(1));
|
||||
AExpression right = (AExpression)visitExpression(ctx.expression(2));
|
||||
|
||||
return new EConditional(line(ctx), offset(ctx), location(ctx), condition, left, right);
|
||||
return new EConditional(location(ctx), condition, left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -557,12 +552,12 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
} else if (ctx.AOR() != null) {
|
||||
operation = Operation.BWOR;
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + ": Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
AExpression expression = (AExpression)visitExpression(ctx.expression());
|
||||
|
||||
return new EChain(line(ctx), offset(ctx), location(ctx), links, false, false, operation, expression);
|
||||
return new EChain(location(ctx), links, false, false, operation, expression);
|
||||
}
|
||||
|
||||
private Object visitUnary(UnaryContext ctx) {
|
||||
@ -572,7 +567,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<ALink> links = (List<ALink>)expression;
|
||||
|
||||
return new EChain(line(ctx), offset(ctx), location(ctx), links, false, false, null, null);
|
||||
return new EChain(location(ctx), links, false, false, null, null);
|
||||
} else {
|
||||
return expression;
|
||||
}
|
||||
@ -589,10 +584,10 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
} else if (ctx.DECR() != null) {
|
||||
operation = Operation.DECR;
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + ": Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
return new EChain(line(ctx), offset(ctx), location(ctx), links, true, false, operation, null);
|
||||
return new EChain(location(ctx), links, true, false, operation, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -606,10 +601,10 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
} else if (ctx.DECR() != null) {
|
||||
operation = Operation.DECR;
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + ": Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
return new EChain(line(ctx), offset(ctx), location(ctx), links, false, true, operation, null);
|
||||
return new EChain(location(ctx), links, false, true, operation, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -622,31 +617,31 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
final boolean negate = ctx.parent instanceof OperatorContext && ((OperatorContext)ctx.parent).SUB() != null;
|
||||
|
||||
if (ctx.DECIMAL() != null) {
|
||||
return new EDecimal(line(ctx), offset(ctx), location(ctx), (negate ? "-" : "") + ctx.DECIMAL().getText());
|
||||
return new EDecimal(location(ctx), (negate ? "-" : "") + ctx.DECIMAL().getText());
|
||||
} else if (ctx.HEX() != null) {
|
||||
return new ENumeric(line(ctx), offset(ctx), location(ctx), (negate ? "-" : "") + ctx.HEX().getText().substring(2), 16);
|
||||
return new ENumeric(location(ctx), (negate ? "-" : "") + ctx.HEX().getText().substring(2), 16);
|
||||
} else if (ctx.INTEGER() != null) {
|
||||
return new ENumeric(line(ctx), offset(ctx), location(ctx), (negate ? "-" : "") + ctx.INTEGER().getText(), 10);
|
||||
return new ENumeric(location(ctx), (negate ? "-" : "") + ctx.INTEGER().getText(), 10);
|
||||
} else if (ctx.OCTAL() != null) {
|
||||
return new ENumeric(line(ctx), offset(ctx), location(ctx), (negate ? "-" : "") + ctx.OCTAL().getText().substring(1), 8);
|
||||
return new ENumeric(location(ctx), (negate ? "-" : "") + ctx.OCTAL().getText().substring(1), 8);
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + ": Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitTrue(TrueContext ctx) {
|
||||
return new EBoolean(line(ctx), offset(ctx), location(ctx), true);
|
||||
return new EBoolean(location(ctx), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitFalse(FalseContext ctx) {
|
||||
return new EBoolean(line(ctx), offset(ctx), location(ctx), false);
|
||||
return new EBoolean(location(ctx), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitNull(NullContext ctx) {
|
||||
return new ENull(line(ctx), offset(ctx), location(ctx));
|
||||
return new ENull(location(ctx));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -666,10 +661,10 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
} else if (ctx.SUB() != null) {
|
||||
operation = Operation.SUB;
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
return new EUnary(line(ctx), offset(ctx), location(ctx), operation, expression);
|
||||
return new EUnary(location(ctx), operation, expression);
|
||||
}
|
||||
}
|
||||
|
||||
@ -681,11 +676,11 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
if (child instanceof List) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<ALink> links = (List<ALink>)child;
|
||||
links.add(new LCast(line(ctx), offset(ctx), location(ctx), type));
|
||||
links.add(new LCast(location(ctx), type));
|
||||
|
||||
return links;
|
||||
} else {
|
||||
return new EExplicit(line(ctx), offset(ctx), location(ctx), type, (AExpression)child);
|
||||
return new EExplicit(location(ctx), type, (AExpression)child);
|
||||
}
|
||||
}
|
||||
|
||||
@ -703,7 +698,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
|
||||
return links;
|
||||
} else if (!ctx.secondary().isEmpty()) {
|
||||
throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
} else {
|
||||
return child;
|
||||
}
|
||||
@ -714,7 +709,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
String type = ctx.decltype().getText();
|
||||
List<ALink> links = new ArrayList<>();
|
||||
|
||||
links.add(new LStatic(line(ctx), offset(ctx), location(ctx), type));
|
||||
links.add(new LStatic(location(ctx), type));
|
||||
links.add((ALink)visit(ctx.dot()));
|
||||
|
||||
for (SecondaryContext secondary : ctx.secondary()) {
|
||||
@ -734,7 +729,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
}
|
||||
|
||||
List<ALink> links = new ArrayList<>();
|
||||
links.add(new LNewArray(line(ctx), offset(ctx), location(ctx), type, expressions));
|
||||
links.add(new LNewArray(location(ctx), type, expressions));
|
||||
|
||||
if (ctx.dot() != null) {
|
||||
links.add((ALink)visit(ctx.dot()));
|
||||
@ -743,7 +738,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
links.add((ALink)visit(secondary));
|
||||
}
|
||||
} else if (!ctx.secondary().isEmpty()) {
|
||||
throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
return links;
|
||||
@ -763,7 +758,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
public Object visitString(StringContext ctx) {
|
||||
String string = ctx.STRING().getText().substring(1, ctx.STRING().getText().length() - 1);
|
||||
List<ALink> links = new ArrayList<>();
|
||||
links.add(new LString(line(ctx), offset(ctx), location(ctx), string));
|
||||
links.add(new LString(location(ctx), string));
|
||||
|
||||
return links;
|
||||
}
|
||||
@ -772,7 +767,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
public Object visitVariable(VariableContext ctx) {
|
||||
String name = ctx.ID().getText();
|
||||
List<ALink> links = new ArrayList<>();
|
||||
links.add(new LVariable(line(ctx), offset(ctx), location(ctx), name));
|
||||
links.add(new LVariable(location(ctx), name));
|
||||
|
||||
reserved.markReserved(name);
|
||||
|
||||
@ -786,7 +781,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
List<AExpression> arguments = (List<AExpression>)visit(ctx.arguments());
|
||||
|
||||
List<ALink> links = new ArrayList<>();
|
||||
links.add(new LNewObj(line(ctx), offset(ctx), location(ctx), type, arguments));
|
||||
links.add(new LNewObj(location(ctx), type, arguments));
|
||||
|
||||
return links;
|
||||
}
|
||||
@ -798,7 +793,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
} else if (ctx.brace() != null) {
|
||||
return visit(ctx.brace());
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -808,7 +803,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<AExpression> arguments = (List<AExpression>)visit(ctx.arguments());
|
||||
|
||||
return new LCall(line(ctx), offset(ctx), location(ctx), name, arguments);
|
||||
return new LCall(location(ctx), name, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -820,17 +815,17 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
} else if (ctx.DOTINTEGER() != null) {
|
||||
value = ctx.DOTINTEGER().getText();
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
return new LField(line(ctx), offset(ctx), location(ctx), value);
|
||||
return new LField(location(ctx), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitBraceaccess(BraceaccessContext ctx) {
|
||||
AExpression expression = (AExpression)visitExpression(ctx.expression());
|
||||
|
||||
return new LBrace(line(ctx), offset(ctx), location(ctx), expression);
|
||||
return new LBrace(location(ctx), expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -851,7 +846,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
|
||||
} else if (ctx.funcref() != null) {
|
||||
return visit(ctx.funcref());
|
||||
} else {
|
||||
throw new IllegalStateException("Error " + location(ctx) + " Illegal tree structure.");
|
||||
throw location(ctx).createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition.Cast;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.AnalyzerCaster;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Label;
|
||||
@ -98,8 +99,8 @@ public abstract class AExpression extends ANode {
|
||||
*/
|
||||
protected Label fals = null;
|
||||
|
||||
public AExpression(int line, int offset, String location) {
|
||||
super(line, offset, location);
|
||||
public AExpression(Location location) {
|
||||
super(location);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -124,18 +125,18 @@ public abstract class AExpression extends ANode {
|
||||
if (constant == null || this instanceof EConstant) {
|
||||
return this;
|
||||
} else {
|
||||
final EConstant econstant = new EConstant(line, offset, location, constant);
|
||||
final EConstant econstant = new EConstant(location, constant);
|
||||
econstant.analyze(variables);
|
||||
|
||||
if (!expected.equals(econstant.actual)) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
return econstant;
|
||||
}
|
||||
} else {
|
||||
if (constant == null) {
|
||||
final ECast ecast = new ECast(line, offset, location, this, cast);
|
||||
final ECast ecast = new ECast(location, this, cast);
|
||||
ecast.statement = statement;
|
||||
ecast.actual = expected;
|
||||
ecast.isNull = isNull;
|
||||
@ -145,28 +146,28 @@ public abstract class AExpression extends ANode {
|
||||
if (expected.sort.constant) {
|
||||
constant = AnalyzerCaster.constCast(location, constant, cast);
|
||||
|
||||
final EConstant econstant = new EConstant(line, offset, location, constant);
|
||||
final EConstant econstant = new EConstant(location, constant);
|
||||
econstant.analyze(variables);
|
||||
|
||||
if (!expected.equals(econstant.actual)) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
return econstant;
|
||||
} else if (this instanceof EConstant) {
|
||||
final ECast ecast = new ECast(line, offset, location, this, cast);
|
||||
final ECast ecast = new ECast(location, this, cast);
|
||||
ecast.actual = expected;
|
||||
|
||||
return ecast;
|
||||
} else {
|
||||
final EConstant econstant = new EConstant(line, offset, location, constant);
|
||||
final EConstant econstant = new EConstant(location, constant);
|
||||
econstant.analyze(variables);
|
||||
|
||||
if (!actual.equals(econstant.actual)) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
final ECast ecast = new ECast(line, offset, location, econstant, cast);
|
||||
final ECast ecast = new ECast(location, econstant, cast);
|
||||
ecast.actual = expected;
|
||||
|
||||
return ecast;
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
@ -73,8 +74,8 @@ public abstract class ALink extends ANode {
|
||||
*/
|
||||
String string = null;
|
||||
|
||||
ALink(int line, int offset, String location, int size) {
|
||||
super(line, offset, location);
|
||||
ALink(Location location, int size) {
|
||||
super(location);
|
||||
|
||||
this.size = size;
|
||||
}
|
||||
|
@ -19,33 +19,22 @@
|
||||
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Location;
|
||||
|
||||
/**
|
||||
* The superclass for all other nodes.
|
||||
*/
|
||||
public abstract class ANode {
|
||||
|
||||
/**
|
||||
* The line number in the original source used for debugging and errors.
|
||||
* The identifier of the script and character offset used for debugging and errors.
|
||||
*/
|
||||
final int line;
|
||||
final Location location;
|
||||
|
||||
/**
|
||||
* The character offset in the original source used for debugging and errors.
|
||||
*/
|
||||
final int offset;
|
||||
|
||||
/**
|
||||
* The location in the original source to be printed in error messages.
|
||||
*/
|
||||
final String location;
|
||||
|
||||
ANode(int line, int offset, String location) {
|
||||
this.line = line;
|
||||
this.offset = offset;
|
||||
ANode(Location location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public String error(final String message) {
|
||||
return "Error " + location + ": " + message;
|
||||
|
||||
public RuntimeException createError(RuntimeException exception) {
|
||||
return location.createError(exception);
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
/**
|
||||
@ -107,8 +108,8 @@ public abstract class AStatement extends ANode {
|
||||
*/
|
||||
Label brake = null;
|
||||
|
||||
AStatement(int line, int offset, String location) {
|
||||
super(line, offset, location);
|
||||
AStatement(Location location) {
|
||||
super(location);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,6 +23,7 @@ import org.elasticsearch.painless.AnalyzerCaster;
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
import org.elasticsearch.painless.Operation;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
@ -38,8 +39,8 @@ public final class EBinary extends AExpression {
|
||||
|
||||
boolean cat = false;
|
||||
|
||||
public EBinary(int line, int offset, String location, Operation operation, AExpression left, AExpression right) {
|
||||
super(line, offset, location);
|
||||
public EBinary(Location location, Operation operation, AExpression left, AExpression right) {
|
||||
super(location);
|
||||
|
||||
this.operation = operation;
|
||||
this.left = left;
|
||||
@ -71,7 +72,7 @@ public final class EBinary extends AExpression {
|
||||
} else if (operation == Operation.BWOR) {
|
||||
analyzeBWOr(variables);
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +83,7 @@ public final class EBinary extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply multiply [*] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply multiply [*] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -104,7 +105,7 @@ public final class EBinary extends AExpression {
|
||||
} else if (sort == Sort.DOUBLE) {
|
||||
constant = (double)left.constant * (double)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,7 +119,7 @@ public final class EBinary extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply divide [/] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply divide [/] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -131,16 +132,20 @@ public final class EBinary extends AExpression {
|
||||
if (left.constant != null && right.constant != null) {
|
||||
Sort sort = promote.sort;
|
||||
|
||||
if (sort == Sort.INT) {
|
||||
constant = (int)left.constant / (int)right.constant;
|
||||
} else if (sort == Sort.LONG) {
|
||||
constant = (long)left.constant / (long)right.constant;
|
||||
} else if (sort == Sort.FLOAT) {
|
||||
constant = (float)left.constant / (float)right.constant;
|
||||
} else if (sort == Sort.DOUBLE) {
|
||||
constant = (double)left.constant / (double)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
try {
|
||||
if (sort == Sort.INT) {
|
||||
constant = (int)left.constant / (int)right.constant;
|
||||
} else if (sort == Sort.LONG) {
|
||||
constant = (long)left.constant / (long)right.constant;
|
||||
} else if (sort == Sort.FLOAT) {
|
||||
constant = (float)left.constant / (float)right.constant;
|
||||
} else if (sort == Sort.DOUBLE) {
|
||||
constant = (double)left.constant / (double)right.constant;
|
||||
} else {
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
} catch (ArithmeticException e) {
|
||||
throw createError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,7 +159,7 @@ public final class EBinary extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply remainder [%] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply remainder [%] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -167,16 +172,20 @@ public final class EBinary extends AExpression {
|
||||
if (left.constant != null && right.constant != null) {
|
||||
Sort sort = promote.sort;
|
||||
|
||||
if (sort == Sort.INT) {
|
||||
constant = (int)left.constant % (int)right.constant;
|
||||
} else if (sort == Sort.LONG) {
|
||||
constant = (long)left.constant % (long)right.constant;
|
||||
} else if (sort == Sort.FLOAT) {
|
||||
constant = (float)left.constant % (float)right.constant;
|
||||
} else if (sort == Sort.DOUBLE) {
|
||||
constant = (double)left.constant % (double)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
try {
|
||||
if (sort == Sort.INT) {
|
||||
constant = (int)left.constant % (int)right.constant;
|
||||
} else if (sort == Sort.LONG) {
|
||||
constant = (long)left.constant % (long)right.constant;
|
||||
} else if (sort == Sort.FLOAT) {
|
||||
constant = (float)left.constant % (float)right.constant;
|
||||
} else if (sort == Sort.DOUBLE) {
|
||||
constant = (double)left.constant % (double)right.constant;
|
||||
} else {
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
} catch (ArithmeticException e) {
|
||||
throw createError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,7 +199,7 @@ public final class EBinary extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteAdd(left.actual, right.actual);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply add [+] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply add [+] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -228,7 +237,7 @@ public final class EBinary extends AExpression {
|
||||
} else if (sort == Sort.STRING) {
|
||||
constant = "" + left.constant + right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,7 +251,7 @@ public final class EBinary extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply subtract [-] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply subtract [-] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -264,7 +273,7 @@ public final class EBinary extends AExpression {
|
||||
} else if (sort == Sort.DOUBLE) {
|
||||
constant = (double)left.constant - (double)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,7 +287,7 @@ public final class EBinary extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, false);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply left shift [<<] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply left shift [<<] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -297,7 +306,7 @@ public final class EBinary extends AExpression {
|
||||
} else if (sort == Sort.LONG) {
|
||||
constant = (long)left.constant << (int)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -311,7 +320,7 @@ public final class EBinary extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, false);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply right shift [>>] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply right shift [>>] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -330,7 +339,7 @@ public final class EBinary extends AExpression {
|
||||
} else if (sort == Sort.LONG) {
|
||||
constant = (long)left.constant >> (int)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -344,7 +353,7 @@ public final class EBinary extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, false);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply unsigned shift [>>>] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply unsigned shift [>>>] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -363,7 +372,7 @@ public final class EBinary extends AExpression {
|
||||
} else if (sort == Sort.LONG) {
|
||||
constant = (long)left.constant >>> (int)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -377,7 +386,7 @@ public final class EBinary extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, false);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply and [&] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply and [&] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -395,7 +404,7 @@ public final class EBinary extends AExpression {
|
||||
} else if (sort == Sort.LONG) {
|
||||
constant = (long)left.constant & (long)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -409,7 +418,7 @@ public final class EBinary extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteXor(left.actual, right.actual);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply xor [^] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply xor [^] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -429,7 +438,7 @@ public final class EBinary extends AExpression {
|
||||
} else if (sort == Sort.LONG) {
|
||||
constant = (long)left.constant ^ (long)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -443,7 +452,7 @@ public final class EBinary extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, false);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply or [|] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply or [|] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -461,7 +470,7 @@ public final class EBinary extends AExpression {
|
||||
} else if (sort == Sort.LONG) {
|
||||
constant = (long)left.constant | (long)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,7 +479,7 @@ public final class EBinary extends AExpression {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
if (actual.sort == Sort.STRING && operation == Operation.ADD) {
|
||||
if (!cat) {
|
||||
writer.writeNewStrings();
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Operation;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Label;
|
||||
@ -34,8 +35,8 @@ public final class EBool extends AExpression {
|
||||
AExpression left;
|
||||
AExpression right;
|
||||
|
||||
public EBool(int line, int offset, String location, Operation operation, AExpression left, AExpression right) {
|
||||
super(line, offset, location);
|
||||
public EBool(Location location, Operation operation, AExpression left, AExpression right) {
|
||||
super(location);
|
||||
|
||||
this.operation = operation;
|
||||
this.left = left;
|
||||
@ -58,7 +59,7 @@ public final class EBool extends AExpression {
|
||||
} else if (operation == Operation.OR) {
|
||||
constant = (boolean)left.constant || (boolean)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,7 +96,7 @@ public final class EBool extends AExpression {
|
||||
writer.mark(localtru);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
} else {
|
||||
if (operation == Operation.AND) {
|
||||
@ -131,7 +132,7 @@ public final class EBool extends AExpression {
|
||||
writer.push(false);
|
||||
writer.mark(end);
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
@ -28,8 +29,8 @@ import org.elasticsearch.painless.MethodWriter;
|
||||
*/
|
||||
public final class EBoolean extends AExpression {
|
||||
|
||||
public EBoolean(int line, int offset, String location, boolean constant) {
|
||||
super(line, offset, location);
|
||||
public EBoolean(Location location, boolean constant) {
|
||||
super(location);
|
||||
|
||||
this.constant = constant;
|
||||
}
|
||||
@ -41,6 +42,6 @@ public final class EBoolean extends AExpression {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter adapter) {
|
||||
throw new IllegalArgumentException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition.Cast;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
@ -34,8 +35,8 @@ final class ECast extends AExpression {
|
||||
|
||||
Cast cast = null;
|
||||
|
||||
ECast(int line, int offset, String location, AExpression child, Cast cast) {
|
||||
super(line, offset, location);
|
||||
ECast(Location location, AExpression child, Cast cast) {
|
||||
super(location);
|
||||
|
||||
this.type = null;
|
||||
this.child = child;
|
||||
@ -45,13 +46,13 @@ final class ECast extends AExpression {
|
||||
|
||||
@Override
|
||||
void analyze(Variables variables) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
child.write(writer);
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
writer.writeCast(cast);
|
||||
writer.writeBranch(tru, fals);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Definition.Cast;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.AnalyzerCaster;
|
||||
import org.elasticsearch.painless.Operation;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
@ -46,9 +47,9 @@ public final class EChain extends AExpression {
|
||||
Cast there = null;
|
||||
Cast back = null;
|
||||
|
||||
public EChain(int line, int offset, String location, List<ALink> links,
|
||||
public EChain(Location location, List<ALink> links,
|
||||
boolean pre, boolean post, Operation operation, AExpression expression) {
|
||||
super(line, offset, location);
|
||||
super(location);
|
||||
|
||||
this.links = links;
|
||||
this.pre = pre;
|
||||
@ -114,40 +115,40 @@ public final class EChain extends AExpression {
|
||||
ALink last = links.get(links.size() - 1);
|
||||
|
||||
if (pre && post) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
} else if (pre || post) {
|
||||
if (expression != null) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
Sort sort = last.after.sort;
|
||||
|
||||
if (operation == Operation.INCR) {
|
||||
if (sort == Sort.DOUBLE) {
|
||||
expression = new EConstant(line, offset, location, 1D);
|
||||
expression = new EConstant(location, 1D);
|
||||
} else if (sort == Sort.FLOAT) {
|
||||
expression = new EConstant(line, offset, location, 1F);
|
||||
expression = new EConstant(location, 1F);
|
||||
} else if (sort == Sort.LONG) {
|
||||
expression = new EConstant(line, offset, location, 1L);
|
||||
expression = new EConstant(location, 1L);
|
||||
} else {
|
||||
expression = new EConstant(line, offset, location, 1);
|
||||
expression = new EConstant(location, 1);
|
||||
}
|
||||
|
||||
operation = Operation.ADD;
|
||||
} else if (operation == Operation.DECR) {
|
||||
if (sort == Sort.DOUBLE) {
|
||||
expression = new EConstant(line, offset, location, 1D);
|
||||
expression = new EConstant(location, 1D);
|
||||
} else if (sort == Sort.FLOAT) {
|
||||
expression = new EConstant(line, offset, location, 1F);
|
||||
expression = new EConstant(location, 1F);
|
||||
} else if (sort == Sort.LONG) {
|
||||
expression = new EConstant(line, offset, location, 1L);
|
||||
expression = new EConstant(location, 1L);
|
||||
} else {
|
||||
expression = new EConstant(line, offset, location, 1);
|
||||
expression = new EConstant(location, 1);
|
||||
}
|
||||
|
||||
operation = Operation.SUB;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -180,12 +181,12 @@ public final class EChain extends AExpression {
|
||||
} else if (operation == Operation.BWOR) {
|
||||
promote = AnalyzerCaster.promoteXor(last.after, expression.actual);
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException("Cannot apply compound assignment " +
|
||||
"[" + operation.symbol + "=] to types [" + last.after + "] and [" + expression.actual + "].");
|
||||
throw createError(new ClassCastException("Cannot apply compound assignment " +
|
||||
"[" + operation.symbol + "=] to types [" + last.after + "] and [" + expression.actual + "]."));
|
||||
}
|
||||
|
||||
cat = operation == Operation.ADD && promote.sort == Sort.STRING;
|
||||
@ -248,9 +249,8 @@ public final class EChain extends AExpression {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
if (cat) {
|
||||
writer.writeDebugInfo(offset);
|
||||
}
|
||||
// can cause class cast exception among other things at runtime
|
||||
writer.writeDebugInfo(location);
|
||||
|
||||
if (cat) {
|
||||
writer.writeNewStrings();
|
||||
|
@ -22,6 +22,7 @@ package org.elasticsearch.painless.node;
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.AnalyzerCaster;
|
||||
import org.elasticsearch.painless.Operation;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
@ -46,8 +47,8 @@ public final class EComp extends AExpression {
|
||||
AExpression left;
|
||||
AExpression right;
|
||||
|
||||
public EComp(int line, int offset, String location, Operation operation, AExpression left, AExpression right) {
|
||||
super(line, offset, location);
|
||||
public EComp(Location location, Operation operation, AExpression left, AExpression right) {
|
||||
super(location);
|
||||
|
||||
this.operation = operation;
|
||||
this.left = left;
|
||||
@ -73,7 +74,7 @@ public final class EComp extends AExpression {
|
||||
} else if (operation == Operation.LT) {
|
||||
analyzeLT(variables);
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +85,7 @@ public final class EComp extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply equals [==] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply equals [==] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -95,7 +96,7 @@ public final class EComp extends AExpression {
|
||||
right = right.cast(variables);
|
||||
|
||||
if (left.isNull && right.isNull) {
|
||||
throw new IllegalArgumentException(error("Extraneous comparison of null constants."));
|
||||
throw createError(new IllegalArgumentException("Extraneous comparison of null constants."));
|
||||
}
|
||||
|
||||
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
||||
@ -116,7 +117,7 @@ public final class EComp extends AExpression {
|
||||
} else if (!right.isNull) {
|
||||
constant = right.constant.equals(null);
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +131,7 @@ public final class EComp extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply reference equals [===] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply reference equals [===] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -141,7 +142,7 @@ public final class EComp extends AExpression {
|
||||
right = right.cast(variables);
|
||||
|
||||
if (left.isNull && right.isNull) {
|
||||
throw new IllegalArgumentException(error("Extraneous comparison of null constants."));
|
||||
throw createError(new IllegalArgumentException("Extraneous comparison of null constants."));
|
||||
}
|
||||
|
||||
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
||||
@ -172,7 +173,7 @@ public final class EComp extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply not equals [!=] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply not equals [!=] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -183,7 +184,7 @@ public final class EComp extends AExpression {
|
||||
right = right.cast(variables);
|
||||
|
||||
if (left.isNull && right.isNull) {
|
||||
throw new IllegalArgumentException(error("Extraneous comparison of null constants."));
|
||||
throw createError(new IllegalArgumentException("Extraneous comparison of null constants."));
|
||||
}
|
||||
|
||||
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
||||
@ -204,7 +205,7 @@ public final class EComp extends AExpression {
|
||||
} else if (!right.isNull) {
|
||||
constant = !right.constant.equals(null);
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,7 +219,7 @@ public final class EComp extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply reference not equals [!==] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply reference not equals [!==] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -229,7 +230,7 @@ public final class EComp extends AExpression {
|
||||
right = right.cast(variables);
|
||||
|
||||
if (left.isNull && right.isNull) {
|
||||
throw new IllegalArgumentException(error("Extraneous comparison of null constants."));
|
||||
throw createError(new IllegalArgumentException("Extraneous comparison of null constants."));
|
||||
}
|
||||
|
||||
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
||||
@ -260,7 +261,7 @@ public final class EComp extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply greater than or equals [>=] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply greater than or equals [>=] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -282,7 +283,7 @@ public final class EComp extends AExpression {
|
||||
} else if (sort == Sort.DOUBLE) {
|
||||
constant = (double)left.constant >= (double)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,7 +297,7 @@ public final class EComp extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply greater than [>] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply greater than [>] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -318,7 +319,7 @@ public final class EComp extends AExpression {
|
||||
} else if (sort == Sort.DOUBLE) {
|
||||
constant = (double)left.constant > (double)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -332,7 +333,7 @@ public final class EComp extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply less than or equals [<=] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply less than or equals [<=] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -354,7 +355,7 @@ public final class EComp extends AExpression {
|
||||
} else if (sort == Sort.DOUBLE) {
|
||||
constant = (double)left.constant <= (double)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -368,7 +369,7 @@ public final class EComp extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply less than [>=] to types " +
|
||||
throw createError(new ClassCastException("Cannot apply less than [>=] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
@ -390,7 +391,7 @@ public final class EComp extends AExpression {
|
||||
} else if (sort == Sort.DOUBLE) {
|
||||
constant = (double)left.constant < (double)right.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -399,7 +400,7 @@ public final class EComp extends AExpression {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
boolean branch = tru != null || fals != null;
|
||||
org.objectweb.asm.Type rtype = right.actual.type;
|
||||
Sort rsort = right.actual.sort;
|
||||
@ -429,12 +430,12 @@ public final class EComp extends AExpression {
|
||||
case BYTE:
|
||||
case SHORT:
|
||||
case CHAR:
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
case BOOL:
|
||||
if (eq) writer.ifZCmp(MethodWriter.EQ, jump);
|
||||
else if (ne) writer.ifZCmp(MethodWriter.NE, jump);
|
||||
else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
break;
|
||||
@ -449,7 +450,7 @@ public final class EComp extends AExpression {
|
||||
else if (gt) writer.ifCmp(rtype, MethodWriter.GT, jump);
|
||||
else if (gte) writer.ifCmp(rtype, MethodWriter.GE, jump);
|
||||
else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
break;
|
||||
@ -485,7 +486,7 @@ public final class EComp extends AExpression {
|
||||
writer.invokeStatic(DEF_UTIL_TYPE, DEF_GTE_CALL);
|
||||
writejump = false;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
if (branch && !writejump) {
|
||||
@ -518,7 +519,7 @@ public final class EComp extends AExpression {
|
||||
writer.ifCmp(rtype, MethodWriter.NE, jump);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.AnalyzerCaster;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Label;
|
||||
@ -35,8 +36,8 @@ public final class EConditional extends AExpression {
|
||||
AExpression left;
|
||||
AExpression right;
|
||||
|
||||
public EConditional(int line, int offset, String location, AExpression condition, AExpression left, AExpression right) {
|
||||
super(line, offset, location);
|
||||
public EConditional(Location location, AExpression condition, AExpression left, AExpression right) {
|
||||
super(location);
|
||||
|
||||
this.condition = condition;
|
||||
this.left = left;
|
||||
@ -50,7 +51,7 @@ public final class EConditional extends AExpression {
|
||||
condition = condition.cast(variables);
|
||||
|
||||
if (condition.constant != null) {
|
||||
throw new IllegalArgumentException(error("Extraneous conditional statement."));
|
||||
throw createError(new IllegalArgumentException("Extraneous conditional statement."));
|
||||
}
|
||||
|
||||
left.expected = expected;
|
||||
@ -78,7 +79,7 @@ public final class EConditional extends AExpression {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
Label localfals = new Label();
|
||||
Label end = new Label();
|
||||
|
||||
|
@ -21,17 +21,18 @@ package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
/**
|
||||
* Respresents a constant. Note this replaces any other expression
|
||||
* Represents a constant. Note this replaces any other expression
|
||||
* node with a constant value set during a cast. (Internal only.)
|
||||
*/
|
||||
final class EConstant extends AExpression {
|
||||
|
||||
EConstant(int line, int offset, String location, Object constant) {
|
||||
super(line, offset, location);
|
||||
EConstant(Location location, Object constant) {
|
||||
super(location);
|
||||
|
||||
this.constant = constant;
|
||||
}
|
||||
@ -57,7 +58,7 @@ final class EConstant extends AExpression {
|
||||
} else if (constant instanceof Boolean) {
|
||||
actual = Definition.BOOLEAN_TYPE;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,7 +86,7 @@ final class EConstant extends AExpression {
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
if (sort != Sort.BOOL) {
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
@ -30,8 +31,8 @@ public final class EDecimal extends AExpression {
|
||||
|
||||
final String value;
|
||||
|
||||
public EDecimal(int line, int offset, String location, String value) {
|
||||
super(line, offset, location);
|
||||
public EDecimal(Location location, String value) {
|
||||
super(location);
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
@ -43,20 +44,20 @@ public final class EDecimal extends AExpression {
|
||||
constant = Float.parseFloat(value.substring(0, value.length() - 1));
|
||||
actual = Definition.FLOAT_TYPE;
|
||||
} catch (NumberFormatException exception) {
|
||||
throw new IllegalArgumentException(error("Invalid float constant [" + value + "]."));
|
||||
throw createError(new IllegalArgumentException("Invalid float constant [" + value + "]."));
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
constant = Double.parseDouble(value);
|
||||
actual = Definition.DOUBLE_TYPE;
|
||||
} catch (NumberFormatException exception) {
|
||||
throw new IllegalArgumentException(error("Invalid double constant [" + value + "]."));
|
||||
throw createError(new IllegalArgumentException("Invalid double constant [" + value + "]."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
throw new IllegalArgumentException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
@ -31,8 +32,8 @@ public final class EExplicit extends AExpression {
|
||||
final String type;
|
||||
AExpression child;
|
||||
|
||||
public EExplicit(int line, int offset, String location, String type, AExpression child) {
|
||||
super(line, offset, location);
|
||||
public EExplicit(Location location, String type, AExpression child) {
|
||||
super(location);
|
||||
|
||||
this.type = type;
|
||||
this.child = child;
|
||||
@ -43,7 +44,7 @@ public final class EExplicit extends AExpression {
|
||||
try {
|
||||
actual = Definition.getType(this.type);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
throw new IllegalArgumentException(error("Not a type [" + this.type + "]."));
|
||||
throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
|
||||
}
|
||||
|
||||
child.expected = actual;
|
||||
@ -54,7 +55,7 @@ public final class EExplicit extends AExpression {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
throw new IllegalArgumentException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
AExpression cast(Variables variables) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
|
||||
@ -29,8 +30,8 @@ public class EFunctionRef extends AExpression {
|
||||
public String type;
|
||||
public String call;
|
||||
|
||||
public EFunctionRef(int line, int offset, String location, String type, String call) {
|
||||
super(line, offset, location);
|
||||
public EFunctionRef(Location location, String type, String call) {
|
||||
super(location);
|
||||
|
||||
this.type = type;
|
||||
this.call = call;
|
||||
@ -38,11 +39,12 @@ public class EFunctionRef extends AExpression {
|
||||
|
||||
@Override
|
||||
void analyze(Variables variables) {
|
||||
throw new UnsupportedOperationException(error("Function references [" + type + "::" + call + "] are not currently supported."));
|
||||
throw createError(new UnsupportedOperationException("Function references [" + type + "::" + call +
|
||||
"] are not currently supported."));
|
||||
}
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
@ -29,8 +30,8 @@ import org.elasticsearch.painless.MethodWriter;
|
||||
*/
|
||||
public final class ENull extends AExpression {
|
||||
|
||||
public ENull(int line, int offset, String location) {
|
||||
super(line, offset, location);
|
||||
public ENull(Location location) {
|
||||
super(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -39,7 +40,7 @@ public final class ENull extends AExpression {
|
||||
|
||||
if (expected != null) {
|
||||
if (expected.sort.primitive) {
|
||||
throw new IllegalArgumentException(error("Cannot cast null to a primitive type [" + expected.name + "]."));
|
||||
throw createError(new IllegalArgumentException("Cannot cast null to a primitive type [" + expected.name + "]."));
|
||||
}
|
||||
|
||||
actual = expected;
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
@ -32,8 +33,8 @@ public final class ENumeric extends AExpression {
|
||||
final String value;
|
||||
int radix;
|
||||
|
||||
public ENumeric(int line, int offset, String location, String value, int radix) {
|
||||
super(line, offset, location);
|
||||
public ENumeric(Location location, String value, int radix) {
|
||||
super(location);
|
||||
|
||||
this.value = value;
|
||||
this.radix = radix;
|
||||
@ -43,32 +44,32 @@ public final class ENumeric extends AExpression {
|
||||
void analyze(Variables variables) {
|
||||
if (value.endsWith("d") || value.endsWith("D")) {
|
||||
if (radix != 10) {
|
||||
throw new IllegalStateException(error("Invalid tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
try {
|
||||
constant = Double.parseDouble(value.substring(0, value.length() - 1));
|
||||
actual = Definition.DOUBLE_TYPE;
|
||||
} catch (NumberFormatException exception) {
|
||||
throw new IllegalArgumentException(error("Invalid double constant [" + value + "]."));
|
||||
throw createError(new IllegalArgumentException("Invalid double constant [" + value + "]."));
|
||||
}
|
||||
} else if (value.endsWith("f") || value.endsWith("F")) {
|
||||
if (radix != 10) {
|
||||
throw new IllegalStateException(error("Invalid tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
try {
|
||||
constant = Float.parseFloat(value.substring(0, value.length() - 1));
|
||||
actual = Definition.FLOAT_TYPE;
|
||||
} catch (NumberFormatException exception) {
|
||||
throw new IllegalArgumentException(error("Invalid float constant [" + value + "]."));
|
||||
throw createError(new IllegalArgumentException("Invalid float constant [" + value + "]."));
|
||||
}
|
||||
} else if (value.endsWith("l") || value.endsWith("L")) {
|
||||
try {
|
||||
constant = Long.parseLong(value.substring(0, value.length() - 1), radix);
|
||||
actual = Definition.LONG_TYPE;
|
||||
} catch (NumberFormatException exception) {
|
||||
throw new IllegalArgumentException(error("Invalid long constant [" + value + "]."));
|
||||
throw createError(new IllegalArgumentException("Invalid long constant [" + value + "]."));
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
@ -89,13 +90,13 @@ public final class ENumeric extends AExpression {
|
||||
actual = Definition.INT_TYPE;
|
||||
}
|
||||
} catch (NumberFormatException exception) {
|
||||
throw new IllegalArgumentException(error("Invalid int constant [" + value + "]."));
|
||||
throw createError(new IllegalArgumentException("Invalid int constant [" + value + "]."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
throw new IllegalArgumentException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.AnalyzerCaster;
|
||||
@ -40,8 +41,8 @@ public final class EUnary extends AExpression {
|
||||
final Operation operation;
|
||||
AExpression child;
|
||||
|
||||
public EUnary(int line, int offset, String location, Operation operation, AExpression child) {
|
||||
super(line, offset, location);
|
||||
public EUnary(Location location, Operation operation, AExpression child) {
|
||||
super(location);
|
||||
|
||||
this.operation = operation;
|
||||
this.child = child;
|
||||
@ -58,7 +59,7 @@ public final class EUnary extends AExpression {
|
||||
} else if (operation == Operation.SUB) {
|
||||
analyzerSub(variables);
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +81,7 @@ public final class EUnary extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(child.actual, false);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply not [~] to type [" + child.actual.name + "]."));
|
||||
throw createError(new ClassCastException("Cannot apply not [~] to type [" + child.actual.name + "]."));
|
||||
}
|
||||
|
||||
child.expected = promote;
|
||||
@ -94,7 +95,7 @@ public final class EUnary extends AExpression {
|
||||
} else if (sort == Sort.LONG) {
|
||||
constant = ~(long)child.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,7 +108,7 @@ public final class EUnary extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(child.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply positive [+] to type [" + child.actual.name + "]."));
|
||||
throw createError(new ClassCastException("Cannot apply positive [+] to type [" + child.actual.name + "]."));
|
||||
}
|
||||
|
||||
child.expected = promote;
|
||||
@ -125,7 +126,7 @@ public final class EUnary extends AExpression {
|
||||
} else if (sort == Sort.DOUBLE) {
|
||||
constant = +(double)child.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +139,7 @@ public final class EUnary extends AExpression {
|
||||
Type promote = AnalyzerCaster.promoteNumeric(child.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
throw new ClassCastException(error("Cannot apply negative [-] to type [" + child.actual.name + "]."));
|
||||
throw createError(new ClassCastException("Cannot apply negative [-] to type [" + child.actual.name + "]."));
|
||||
}
|
||||
|
||||
child.expected = promote;
|
||||
@ -156,7 +157,7 @@ public final class EUnary extends AExpression {
|
||||
} else if (sort == Sort.DOUBLE) {
|
||||
constant = -(double)child.constant;
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,7 +166,7 @@ public final class EUnary extends AExpression {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
if (operation == Operation.NOT) {
|
||||
if (tru == null && fals == null) {
|
||||
Label localfals = new Label();
|
||||
@ -199,7 +200,7 @@ public final class EUnary extends AExpression {
|
||||
} else if (sort == Sort.LONG) {
|
||||
writer.push(-1L);
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
writer.math(MethodWriter.XOR, type);
|
||||
@ -211,7 +212,7 @@ public final class EUnary extends AExpression {
|
||||
writer.math(MethodWriter.NEG, type);
|
||||
}
|
||||
} else if (operation != Operation.ADD) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
writer.writeBranch(tru, fals);
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
@ -30,8 +31,8 @@ public final class LArrayLength extends ALink {
|
||||
|
||||
final String value;
|
||||
|
||||
LArrayLength(int line, int offset, String location, String value) {
|
||||
super(line, offset, location, -1);
|
||||
LArrayLength(Location location, String value) {
|
||||
super(location, -1);
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
@ -40,14 +41,14 @@ public final class LArrayLength extends ALink {
|
||||
ALink analyze(Variables variables) {
|
||||
if ("length".equals(value)) {
|
||||
if (!load) {
|
||||
throw new IllegalArgumentException(error("Must read array field [length]."));
|
||||
throw createError(new IllegalArgumentException("Must read array field [length]."));
|
||||
} else if (store) {
|
||||
throw new IllegalArgumentException(error("Cannot write to read-only array field [length]."));
|
||||
throw createError(new IllegalArgumentException("Cannot write to read-only array field [length]."));
|
||||
}
|
||||
|
||||
after = Definition.INT_TYPE;
|
||||
} else {
|
||||
throw new IllegalArgumentException(error("Illegal field access [" + value + "]."));
|
||||
throw createError(new IllegalArgumentException("Illegal field access [" + value + "]."));
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -60,12 +61,12 @@ public final class LArrayLength extends ALink {
|
||||
|
||||
@Override
|
||||
void load(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
writer.arrayLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
@ -34,8 +35,8 @@ public final class LBrace extends ALink {
|
||||
|
||||
AExpression index;
|
||||
|
||||
public LBrace(int line, int offset, String location, AExpression index) {
|
||||
super(line, offset, location, 2);
|
||||
public LBrace(Location location, AExpression index) {
|
||||
super(location, 2);
|
||||
|
||||
this.index = index;
|
||||
}
|
||||
@ -43,7 +44,7 @@ public final class LBrace extends ALink {
|
||||
@Override
|
||||
ALink analyze(Variables variables) {
|
||||
if (before == null) {
|
||||
throw new IllegalArgumentException(error("Illegal array access made without target."));
|
||||
throw createError(new IllegalArgumentException("Illegal array access made without target."));
|
||||
}
|
||||
|
||||
final Sort sort = before.sort;
|
||||
@ -57,14 +58,14 @@ public final class LBrace extends ALink {
|
||||
|
||||
return this;
|
||||
} else if (sort == Sort.DEF) {
|
||||
return new LDefArray(line, offset, location, index).copy(this).analyze(variables);
|
||||
return new LDefArray(location, index).copy(this).analyze(variables);
|
||||
} else if (Map.class.isAssignableFrom(before.clazz)) {
|
||||
return new LMapShortcut(line, offset, location, index).copy(this).analyze(variables);
|
||||
return new LMapShortcut(location, index).copy(this).analyze(variables);
|
||||
} else if (List.class.isAssignableFrom(before.clazz)) {
|
||||
return new LListShortcut(line, offset, location, index).copy(this).analyze(variables);
|
||||
return new LListShortcut(location, index).copy(this).analyze(variables);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(error("Illegal array access on type [" + before.name + "]."));
|
||||
throw createError(new IllegalArgumentException("Illegal array access on type [" + before.name + "]."));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -74,13 +75,13 @@ public final class LBrace extends ALink {
|
||||
|
||||
@Override
|
||||
void load(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
writer.arrayLoad(after.type);
|
||||
}
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
writer.arrayStore(after.type);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Method;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Definition.Struct;
|
||||
@ -38,8 +39,8 @@ public final class LCall extends ALink {
|
||||
|
||||
Method method = null;
|
||||
|
||||
public LCall(int line, int offset, String location, String name, List<AExpression> arguments) {
|
||||
super(line, offset, location, -1);
|
||||
public LCall(Location location, String name, List<AExpression> arguments) {
|
||||
super(location, -1);
|
||||
|
||||
this.name = name;
|
||||
this.arguments = arguments;
|
||||
@ -48,11 +49,11 @@ public final class LCall extends ALink {
|
||||
@Override
|
||||
ALink analyze(Variables variables) {
|
||||
if (before == null) {
|
||||
throw new IllegalArgumentException(error("Illegal call [" + name + "] made without target."));
|
||||
throw createError(new IllegalArgumentException("Illegal call [" + name + "] made without target."));
|
||||
} else if (before.sort == Sort.ARRAY) {
|
||||
throw new IllegalArgumentException(error("Illegal call [" + name + "] on array type."));
|
||||
throw createError(new IllegalArgumentException("Illegal call [" + name + "] on array type."));
|
||||
} else if (store) {
|
||||
throw new IllegalArgumentException(error("Cannot assign a value to a call [" + name + "]."));
|
||||
throw createError(new IllegalArgumentException("Cannot assign a value to a call [" + name + "]."));
|
||||
}
|
||||
|
||||
Definition.MethodKey methodKey = new Definition.MethodKey(name, arguments.size());
|
||||
@ -74,13 +75,13 @@ public final class LCall extends ALink {
|
||||
|
||||
return this;
|
||||
} else if (before.sort == Sort.DEF) {
|
||||
ALink link = new LDefCall(line, offset, location, name, arguments);
|
||||
ALink link = new LDefCall(location, name, arguments);
|
||||
link.copy(this);
|
||||
|
||||
return link.analyze(variables);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(error("Unknown call [" + name + "] with [" + arguments.size() +
|
||||
throw createError(new IllegalArgumentException("Unknown call [" + name + "] with [" + arguments.size() +
|
||||
"] arguments on type [" + struct.name + "]."));
|
||||
}
|
||||
|
||||
@ -91,7 +92,7 @@ public final class LCall extends ALink {
|
||||
|
||||
@Override
|
||||
void load(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
for (AExpression argument : arguments) {
|
||||
argument.write(writer);
|
||||
}
|
||||
@ -111,6 +112,6 @@ public final class LCall extends ALink {
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Cast;
|
||||
import org.elasticsearch.painless.AnalyzerCaster;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
@ -34,8 +35,8 @@ public final class LCast extends ALink {
|
||||
|
||||
Cast cast = null;
|
||||
|
||||
public LCast(int line, int offset, String location, String type) {
|
||||
super(line, offset, location, -1);
|
||||
public LCast(Location location, String type) {
|
||||
super(location, -1);
|
||||
|
||||
this.type = type;
|
||||
}
|
||||
@ -43,15 +44,15 @@ public final class LCast extends ALink {
|
||||
@Override
|
||||
ALink analyze(Variables variables) {
|
||||
if (before == null) {
|
||||
throw new IllegalStateException(error("Illegal cast without a target."));
|
||||
throw createError(new IllegalStateException("Illegal cast without a target."));
|
||||
} else if (store) {
|
||||
throw new IllegalArgumentException(error("Cannot assign a value to a cast."));
|
||||
throw createError(new IllegalArgumentException("Cannot assign a value to a cast."));
|
||||
}
|
||||
|
||||
try {
|
||||
after = Definition.getType(type);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
throw new IllegalArgumentException(error("Not a type [" + type + "]."));
|
||||
throw createError(new IllegalArgumentException("Not a type [" + type + "]."));
|
||||
}
|
||||
|
||||
cast = AnalyzerCaster.getLegalCast(location, before, after, true, false);
|
||||
@ -61,7 +62,7 @@ public final class LCast extends ALink {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
writer.writeCast(cast);
|
||||
}
|
||||
|
||||
@ -72,6 +73,6 @@ public final class LCast extends ALink {
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.DefBootstrap;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Type;
|
||||
@ -34,8 +35,8 @@ final class LDefArray extends ALink implements IDefLink {
|
||||
|
||||
AExpression index;
|
||||
|
||||
LDefArray(int line, int offset, String location, AExpression index) {
|
||||
super(line, offset, location, 2);
|
||||
LDefArray(Location location, AExpression index) {
|
||||
super(location, 2);
|
||||
|
||||
this.index = index;
|
||||
}
|
||||
@ -58,14 +59,14 @@ final class LDefArray extends ALink implements IDefLink {
|
||||
|
||||
@Override
|
||||
void load(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
String desc = Type.getMethodDescriptor(after.type, Definition.DEF_TYPE.type, index.actual.type);
|
||||
writer.invokeDynamic("arrayLoad", desc, DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.ARRAY_LOAD);
|
||||
}
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
String desc = Type.getMethodDescriptor(Definition.VOID_TYPE.type, Definition.DEF_TYPE.type, index.actual.type, after.type);
|
||||
writer.invokeDynamic("arrayStore", desc, DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.ARRAY_STORE);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.DefBootstrap;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
@ -36,8 +37,8 @@ final class LDefCall extends ALink implements IDefLink {
|
||||
final String name;
|
||||
final List<AExpression> arguments;
|
||||
|
||||
LDefCall(int line, int offset, String location, String name, List<AExpression> arguments) {
|
||||
super(line, offset, location, -1);
|
||||
LDefCall(Location location, String name, List<AExpression> arguments) {
|
||||
super(location, -1);
|
||||
|
||||
this.name = name;
|
||||
this.arguments = arguments;
|
||||
@ -67,7 +68,7 @@ final class LDefCall extends ALink implements IDefLink {
|
||||
|
||||
@Override
|
||||
void load(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
StringBuilder signature = new StringBuilder();
|
||||
|
||||
signature.append('(');
|
||||
@ -88,6 +89,6 @@ final class LDefCall extends ALink implements IDefLink {
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.DefBootstrap;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Type;
|
||||
@ -34,8 +35,8 @@ final class LDefField extends ALink implements IDefLink {
|
||||
|
||||
final String value;
|
||||
|
||||
LDefField(int line, int offset, String location, String value) {
|
||||
super(line, offset, location, 1);
|
||||
LDefField(Location location, String value) {
|
||||
super(location, 1);
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
@ -55,14 +56,14 @@ final class LDefField extends ALink implements IDefLink {
|
||||
|
||||
@Override
|
||||
void load(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
String desc = Type.getMethodDescriptor(after.type, Definition.DEF_TYPE.type);
|
||||
writer.invokeDynamic(value, desc, DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.LOAD);
|
||||
}
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
String desc = Type.getMethodDescriptor(Definition.VOID_TYPE.type, Definition.DEF_TYPE.type, after.type);
|
||||
writer.invokeDynamic(value, desc, DEF_BOOTSTRAP_HANDLE, (Object)DefBootstrap.STORE);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Field;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Definition.Struct;
|
||||
@ -38,8 +39,8 @@ public final class LField extends ALink {
|
||||
|
||||
Field field;
|
||||
|
||||
public LField(int line, int offset, String location, String value) {
|
||||
super(line, offset, location, 1);
|
||||
public LField(Location location, String value) {
|
||||
super(location, 1);
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
@ -47,15 +48,15 @@ public final class LField extends ALink {
|
||||
@Override
|
||||
ALink analyze(Variables variables) {
|
||||
if (before == null) {
|
||||
throw new IllegalArgumentException(error("Illegal field [" + value + "] access made without target."));
|
||||
throw createError(new IllegalArgumentException("Illegal field [" + value + "] access made without target."));
|
||||
}
|
||||
|
||||
Sort sort = before.sort;
|
||||
|
||||
if (sort == Sort.ARRAY) {
|
||||
return new LArrayLength(line, offset, location, value).copy(this).analyze(variables);
|
||||
return new LArrayLength(location, value).copy(this).analyze(variables);
|
||||
} else if (sort == Sort.DEF) {
|
||||
return new LDefField(line, offset, location, value).copy(this).analyze(variables);
|
||||
return new LDefField(location, value).copy(this).analyze(variables);
|
||||
}
|
||||
|
||||
Struct struct = before.struct;
|
||||
@ -63,7 +64,7 @@ public final class LField extends ALink {
|
||||
|
||||
if (field != null) {
|
||||
if (store && java.lang.reflect.Modifier.isFinal(field.modifiers)) {
|
||||
throw new IllegalArgumentException(error(
|
||||
throw createError(new IllegalArgumentException(
|
||||
"Cannot write to read-only field [" + value + "] for type [" + struct.name + "]."));
|
||||
}
|
||||
|
||||
@ -80,22 +81,22 @@ public final class LField extends ALink {
|
||||
Character.toUpperCase(value.charAt(0)) + value.substring(1), 1));
|
||||
|
||||
if (shortcut) {
|
||||
return new LShortcut(line, offset, location, value).copy(this).analyze(variables);
|
||||
return new LShortcut(location, value).copy(this).analyze(variables);
|
||||
} else {
|
||||
EConstant index = new EConstant(line, offset, location, value);
|
||||
EConstant index = new EConstant(location, value);
|
||||
index.analyze(variables);
|
||||
|
||||
if (Map.class.isAssignableFrom(before.clazz)) {
|
||||
return new LMapShortcut(line, offset, location, index).copy(this).analyze(variables);
|
||||
return new LMapShortcut(location, index).copy(this).analyze(variables);
|
||||
}
|
||||
|
||||
if (List.class.isAssignableFrom(before.clazz)) {
|
||||
return new LListShortcut(line, offset, location, index).copy(this).analyze(variables);
|
||||
return new LListShortcut(location, index).copy(this).analyze(variables);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(error("Unknown field [" + value + "] for type [" + struct.name + "]."));
|
||||
throw createError(new IllegalArgumentException("Unknown field [" + value + "] for type [" + struct.name + "]."));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -105,7 +106,7 @@ public final class LField extends ALink {
|
||||
|
||||
@Override
|
||||
void load(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
if (java.lang.reflect.Modifier.isStatic(field.modifiers)) {
|
||||
writer.getStatic(field.owner.type, field.javaName, field.type.type);
|
||||
} else {
|
||||
@ -115,7 +116,7 @@ public final class LField extends ALink {
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
if (java.lang.reflect.Modifier.isStatic(field.modifiers)) {
|
||||
writer.putStatic(field.owner.type, field.javaName, field.type.type);
|
||||
} else {
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Method;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
@ -34,8 +35,8 @@ final class LListShortcut extends ALink {
|
||||
Method getter;
|
||||
Method setter;
|
||||
|
||||
LListShortcut(int line, int offset, String location, AExpression index) {
|
||||
super(line, offset, location, 2);
|
||||
LListShortcut(Location location, AExpression index) {
|
||||
super(location, 2);
|
||||
|
||||
this.index = index;
|
||||
}
|
||||
@ -47,16 +48,16 @@ final class LListShortcut extends ALink {
|
||||
|
||||
if (getter != null && (getter.rtn.sort == Sort.VOID || getter.arguments.size() != 1 ||
|
||||
getter.arguments.get(0).sort != Sort.INT)) {
|
||||
throw new IllegalArgumentException(error("Illegal list get shortcut for type [" + before.name + "]."));
|
||||
throw createError(new IllegalArgumentException("Illegal list get shortcut for type [" + before.name + "]."));
|
||||
}
|
||||
|
||||
if (setter != null && (setter.arguments.size() != 2 || setter.arguments.get(0).sort != Sort.INT)) {
|
||||
throw new IllegalArgumentException(error("Illegal list set shortcut for type [" + before.name + "]."));
|
||||
throw createError(new IllegalArgumentException("Illegal list set shortcut for type [" + before.name + "]."));
|
||||
}
|
||||
|
||||
if (getter != null && setter != null && (!getter.arguments.get(0).equals(setter.arguments.get(0))
|
||||
|| !getter.rtn.equals(setter.arguments.get(1)))) {
|
||||
throw new IllegalArgumentException(error("Shortcut argument types must match."));
|
||||
throw createError(new IllegalArgumentException("Shortcut argument types must match."));
|
||||
}
|
||||
|
||||
if ((load || store) && (!load || getter != null) && (!store || setter != null)) {
|
||||
@ -66,7 +67,7 @@ final class LListShortcut extends ALink {
|
||||
|
||||
after = setter != null ? setter.arguments.get(1) : getter.rtn;
|
||||
} else {
|
||||
throw new IllegalArgumentException(error("Illegal list shortcut for type [" + before.name + "]."));
|
||||
throw createError(new IllegalArgumentException("Illegal list shortcut for type [" + before.name + "]."));
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -79,7 +80,7 @@ final class LListShortcut extends ALink {
|
||||
|
||||
@Override
|
||||
void load(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
if (java.lang.reflect.Modifier.isInterface(getter.owner.clazz.getModifiers())) {
|
||||
writer.invokeInterface(getter.owner.type, getter.method);
|
||||
} else {
|
||||
@ -93,7 +94,7 @@ final class LListShortcut extends ALink {
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
if (java.lang.reflect.Modifier.isInterface(setter.owner.clazz.getModifiers())) {
|
||||
writer.invokeInterface(setter.owner.type, setter.method);
|
||||
} else {
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Method;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
@ -34,8 +35,8 @@ final class LMapShortcut extends ALink {
|
||||
Method getter;
|
||||
Method setter;
|
||||
|
||||
LMapShortcut(int line, int offset, String location, AExpression index) {
|
||||
super(line, offset, location, 2);
|
||||
LMapShortcut(Location location, AExpression index) {
|
||||
super(location, 2);
|
||||
|
||||
this.index = index;
|
||||
}
|
||||
@ -46,16 +47,16 @@ final class LMapShortcut extends ALink {
|
||||
setter = before.struct.methods.get(new Definition.MethodKey("put", 2));
|
||||
|
||||
if (getter != null && (getter.rtn.sort == Sort.VOID || getter.arguments.size() != 1)) {
|
||||
throw new IllegalArgumentException(error("Illegal map get shortcut for type [" + before.name + "]."));
|
||||
throw createError(new IllegalArgumentException("Illegal map get shortcut for type [" + before.name + "]."));
|
||||
}
|
||||
|
||||
if (setter != null && setter.arguments.size() != 2) {
|
||||
throw new IllegalArgumentException(error("Illegal map set shortcut for type [" + before.name + "]."));
|
||||
throw createError(new IllegalArgumentException("Illegal map set shortcut for type [" + before.name + "]."));
|
||||
}
|
||||
|
||||
if (getter != null && setter != null &&
|
||||
(!getter.arguments.get(0).equals(setter.arguments.get(0)) || !getter.rtn.equals(setter.arguments.get(1)))) {
|
||||
throw new IllegalArgumentException(error("Shortcut argument types must match."));
|
||||
throw createError(new IllegalArgumentException("Shortcut argument types must match."));
|
||||
}
|
||||
|
||||
if ((load || store) && (!load || getter != null) && (!store || setter != null)) {
|
||||
@ -65,7 +66,7 @@ final class LMapShortcut extends ALink {
|
||||
|
||||
after = setter != null ? setter.arguments.get(1) : getter.rtn;
|
||||
} else {
|
||||
throw new IllegalArgumentException(error("Illegal map shortcut for type [" + before.name + "]."));
|
||||
throw createError(new IllegalArgumentException("Illegal map shortcut for type [" + before.name + "]."));
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -78,7 +79,7 @@ final class LMapShortcut extends ALink {
|
||||
|
||||
@Override
|
||||
void load(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
if (java.lang.reflect.Modifier.isInterface(getter.owner.clazz.getModifiers())) {
|
||||
writer.invokeInterface(getter.owner.type, getter.method);
|
||||
} else {
|
||||
@ -92,7 +93,7 @@ final class LMapShortcut extends ALink {
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
if (java.lang.reflect.Modifier.isInterface(setter.owner.clazz.getModifiers())) {
|
||||
writer.invokeInterface(setter.owner.type, setter.method);
|
||||
} else {
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
@ -34,8 +35,8 @@ public final class LNewArray extends ALink {
|
||||
final String type;
|
||||
final List<AExpression> arguments;
|
||||
|
||||
public LNewArray(int line, int offset, String location, String type, List<AExpression> arguments) {
|
||||
super(line, offset, location, -1);
|
||||
public LNewArray(Location location, String type, List<AExpression> arguments) {
|
||||
super(location, -1);
|
||||
|
||||
this.type = type;
|
||||
this.arguments = arguments;
|
||||
@ -44,11 +45,11 @@ public final class LNewArray extends ALink {
|
||||
@Override
|
||||
ALink analyze(Variables variables) {
|
||||
if (before != null) {
|
||||
throw new IllegalArgumentException(error("Cannot create a new array with a target already defined."));
|
||||
throw createError(new IllegalArgumentException("Cannot create a new array with a target already defined."));
|
||||
} else if (store) {
|
||||
throw new IllegalArgumentException(error("Cannot assign a value to a new array."));
|
||||
throw createError(new IllegalArgumentException("Cannot assign a value to a new array."));
|
||||
} else if (!load) {
|
||||
throw new IllegalArgumentException(error("A newly created array must be read."));
|
||||
throw createError(new IllegalArgumentException("A newly created array must be read."));
|
||||
}
|
||||
|
||||
final Type type;
|
||||
@ -56,7 +57,7 @@ public final class LNewArray extends ALink {
|
||||
try {
|
||||
type = Definition.getType(this.type);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
throw new IllegalArgumentException(error("Not a type [" + this.type + "]."));
|
||||
throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
|
||||
}
|
||||
|
||||
for (int argument = 0; argument < arguments.size(); ++argument) {
|
||||
@ -79,7 +80,7 @@ public final class LNewArray extends ALink {
|
||||
|
||||
@Override
|
||||
void load(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
for (AExpression argument : arguments) {
|
||||
argument.write(writer);
|
||||
}
|
||||
@ -93,6 +94,6 @@ public final class LNewArray extends ALink {
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Constructor;
|
||||
import org.elasticsearch.painless.Definition.Struct;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
@ -29,7 +30,7 @@ import org.elasticsearch.painless.MethodWriter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Respresents and object instantiation.
|
||||
* Represents and object instantiation.
|
||||
*/
|
||||
public final class LNewObj extends ALink {
|
||||
|
||||
@ -38,8 +39,8 @@ public final class LNewObj extends ALink {
|
||||
|
||||
Constructor constructor;
|
||||
|
||||
public LNewObj(int line, int offset, String location, String type, List<AExpression> arguments) {
|
||||
super(line, offset, location, -1);
|
||||
public LNewObj(Location location, String type, List<AExpression> arguments) {
|
||||
super(location, -1);
|
||||
|
||||
this.type = type;
|
||||
this.arguments = arguments;
|
||||
@ -48,9 +49,9 @@ public final class LNewObj extends ALink {
|
||||
@Override
|
||||
ALink analyze(Variables variables) {
|
||||
if (before != null) {
|
||||
throw new IllegalArgumentException(error("Illegal new call with a target already defined."));
|
||||
throw createError(new IllegalArgumentException("Illegal new call with a target already defined."));
|
||||
} else if (store) {
|
||||
throw new IllegalArgumentException(error("Cannot assign a value to a new call."));
|
||||
throw createError(new IllegalArgumentException("Cannot assign a value to a new call."));
|
||||
}
|
||||
|
||||
final Type type;
|
||||
@ -58,7 +59,7 @@ public final class LNewObj extends ALink {
|
||||
try {
|
||||
type = Definition.getType(this.type);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
throw new IllegalArgumentException(error("Not a type [" + this.type + "]."));
|
||||
throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
|
||||
}
|
||||
|
||||
Struct struct = type.struct;
|
||||
@ -69,7 +70,7 @@ public final class LNewObj extends ALink {
|
||||
constructor.arguments.toArray(types);
|
||||
|
||||
if (constructor.arguments.size() != arguments.size()) {
|
||||
throw new IllegalArgumentException(error("When calling constructor on type [" + struct.name + "]" +
|
||||
throw createError(new IllegalArgumentException("When calling constructor on type [" + struct.name + "]" +
|
||||
" expected [" + constructor.arguments.size() + "] arguments, but found [" + arguments.size() + "]."));
|
||||
}
|
||||
|
||||
@ -85,7 +86,7 @@ public final class LNewObj extends ALink {
|
||||
statement = true;
|
||||
after = type;
|
||||
} else {
|
||||
throw new IllegalArgumentException(error("Unknown new call on type [" + struct.name + "]."));
|
||||
throw createError(new IllegalArgumentException("Unknown new call on type [" + struct.name + "]."));
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -98,7 +99,7 @@ public final class LNewObj extends ALink {
|
||||
|
||||
@Override
|
||||
void load(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
writer.newInstance(after.type);
|
||||
|
||||
if (load) {
|
||||
@ -114,6 +115,6 @@ public final class LNewObj extends ALink {
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Method;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Definition.Struct;
|
||||
@ -36,8 +37,8 @@ final class LShortcut extends ALink {
|
||||
Method getter = null;
|
||||
Method setter = null;
|
||||
|
||||
LShortcut(int line, int offset, String location, String value) {
|
||||
super(line, offset, location, 1);
|
||||
LShortcut(Location location, String value) {
|
||||
super(location, 1);
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
@ -55,23 +56,23 @@ final class LShortcut extends ALink {
|
||||
setter = struct.methods.get(new Definition.MethodKey("set" + Character.toUpperCase(value.charAt(0)) + value.substring(1), 1));
|
||||
|
||||
if (getter != null && (getter.rtn.sort == Sort.VOID || !getter.arguments.isEmpty())) {
|
||||
throw new IllegalArgumentException(error(
|
||||
throw createError(new IllegalArgumentException(
|
||||
"Illegal get shortcut on field [" + value + "] for type [" + struct.name + "]."));
|
||||
}
|
||||
|
||||
if (setter != null && (setter.rtn.sort != Sort.VOID || setter.arguments.size() != 1)) {
|
||||
throw new IllegalArgumentException(error(
|
||||
throw createError(new IllegalArgumentException(
|
||||
"Illegal set shortcut on field [" + value + "] for type [" + struct.name + "]."));
|
||||
}
|
||||
|
||||
if (getter != null && setter != null && setter.arguments.get(0) != getter.rtn) {
|
||||
throw new IllegalArgumentException(error("Shortcut argument types must match."));
|
||||
throw createError(new IllegalArgumentException("Shortcut argument types must match."));
|
||||
}
|
||||
|
||||
if ((getter != null || setter != null) && (!load || getter != null) && (!store || setter != null)) {
|
||||
after = setter != null ? setter.arguments.get(0) : getter.rtn;
|
||||
} else {
|
||||
throw new IllegalArgumentException(error("Illegal shortcut on field [" + value + "] for type [" + struct.name + "]."));
|
||||
throw createError(new IllegalArgumentException("Illegal shortcut on field [" + value + "] for type [" + struct.name + "]."));
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -84,7 +85,7 @@ final class LShortcut extends ALink {
|
||||
|
||||
@Override
|
||||
void load(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
if (java.lang.reflect.Modifier.isInterface(getter.owner.clazz.getModifiers())) {
|
||||
writer.invokeInterface(getter.owner.type, getter.method);
|
||||
} else {
|
||||
@ -98,7 +99,7 @@ final class LShortcut extends ALink {
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
writer.writeDebugInfo(offset);
|
||||
writer.writeDebugInfo(location);
|
||||
if (java.lang.reflect.Modifier.isInterface(setter.owner.clazz.getModifiers())) {
|
||||
writer.invokeInterface(setter.owner.type, setter.method);
|
||||
} else {
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
|
||||
@ -30,8 +31,8 @@ public final class LStatic extends ALink {
|
||||
|
||||
final String type;
|
||||
|
||||
public LStatic(int line, int offset, String location, String type) {
|
||||
super(line, offset, location, 0);
|
||||
public LStatic(Location location, String type) {
|
||||
super(location, 0);
|
||||
|
||||
this.type = type;
|
||||
}
|
||||
@ -39,14 +40,14 @@ public final class LStatic extends ALink {
|
||||
@Override
|
||||
ALink analyze(Variables variables) {
|
||||
if (before != null) {
|
||||
throw new IllegalArgumentException(error("Illegal static type [" + type + "] after target already defined."));
|
||||
throw createError(new IllegalArgumentException("Illegal static type [" + type + "] after target already defined."));
|
||||
}
|
||||
|
||||
try {
|
||||
after = Definition.getType(type);
|
||||
statik = true;
|
||||
} catch (IllegalArgumentException exception) {
|
||||
throw new IllegalArgumentException(error("Not a type [" + type + "]."));
|
||||
throw createError(new IllegalArgumentException("Not a type [" + type + "]."));
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -54,16 +55,16 @@ public final class LStatic extends ALink {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
@Override
|
||||
void load(MethodWriter writer) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
@ -28,8 +29,8 @@ import org.elasticsearch.painless.MethodWriter;
|
||||
*/
|
||||
public final class LString extends ALink {
|
||||
|
||||
public LString(int line, int offset, String location, String string) {
|
||||
super(line, offset, location, -1);
|
||||
public LString(Location location, String string) {
|
||||
super(location, -1);
|
||||
|
||||
this.string = string;
|
||||
}
|
||||
@ -37,11 +38,11 @@ public final class LString extends ALink {
|
||||
@Override
|
||||
ALink analyze(Variables variables) {
|
||||
if (before != null) {
|
||||
throw new IllegalArgumentException(error("Illegal String constant [" + string + "]."));
|
||||
throw createError(new IllegalArgumentException("Illegal String constant [" + string + "]."));
|
||||
} else if (store) {
|
||||
throw new IllegalArgumentException(error("Cannot write to read-only String constant [" + string + "]."));
|
||||
throw createError(new IllegalArgumentException("Cannot write to read-only String constant [" + string + "]."));
|
||||
} else if (!load) {
|
||||
throw new IllegalArgumentException(error("Must read String constant [" + string + "]."));
|
||||
throw createError(new IllegalArgumentException("Must read String constant [" + string + "]."));
|
||||
}
|
||||
|
||||
after = Definition.STRING_TYPE;
|
||||
@ -61,6 +62,6 @@ public final class LString extends ALink {
|
||||
|
||||
@Override
|
||||
void store(MethodWriter writer) {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.Variables.Variable;
|
||||
@ -33,8 +34,8 @@ public final class LVariable extends ALink {
|
||||
|
||||
int slot;
|
||||
|
||||
public LVariable(int line, int offset, String location, String name) {
|
||||
super(line, offset, location, 0);
|
||||
public LVariable(Location location, String name) {
|
||||
super(location, 0);
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
@ -42,13 +43,13 @@ public final class LVariable extends ALink {
|
||||
@Override
|
||||
ALink analyze(Variables variables) {
|
||||
if (before != null) {
|
||||
throw new IllegalArgumentException(error("Illegal variable [" + name + "] access with target already defined."));
|
||||
throw createError(new IllegalArgumentException("Illegal variable [" + name + "] access with target already defined."));
|
||||
}
|
||||
|
||||
Variable variable = variables.getVariable(location, name);
|
||||
|
||||
if (store && variable.readonly) {
|
||||
throw new IllegalArgumentException(error("Variable [" + variable.name + "] is read-only."));
|
||||
throw createError(new IllegalArgumentException("Variable [" + variable.name + "] is read-only."));
|
||||
}
|
||||
|
||||
slot = variable.slot;
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
import java.util.Collections;
|
||||
@ -32,8 +33,8 @@ public final class SBlock extends AStatement {
|
||||
|
||||
final List<AStatement> statements;
|
||||
|
||||
public SBlock(int line, int offset, String location, List<AStatement> statements) {
|
||||
super(line, offset, location);
|
||||
public SBlock(Location location, List<AStatement> statements) {
|
||||
super(location);
|
||||
|
||||
this.statements = Collections.unmodifiableList(statements);
|
||||
}
|
||||
@ -41,14 +42,14 @@ public final class SBlock extends AStatement {
|
||||
@Override
|
||||
void analyze(Variables variables) {
|
||||
if (statements == null || statements.isEmpty()) {
|
||||
throw new IllegalArgumentException(error("A block must contain at least one statement."));
|
||||
throw createError(new IllegalArgumentException("A block must contain at least one statement."));
|
||||
}
|
||||
|
||||
final AStatement last = statements.get(statements.size() - 1);
|
||||
|
||||
for (AStatement statement : statements) {
|
||||
if (allEscape) {
|
||||
throw new IllegalArgumentException(error("Unreachable statement."));
|
||||
throw createError(new IllegalArgumentException("Unreachable statement."));
|
||||
}
|
||||
|
||||
statement.inLoop = inLoop;
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
/**
|
||||
@ -27,14 +28,14 @@ import org.elasticsearch.painless.MethodWriter;
|
||||
*/
|
||||
public final class SBreak extends AStatement {
|
||||
|
||||
public SBreak(int line, int offset, String location) {
|
||||
super(line, offset, location);
|
||||
public SBreak(Location location) {
|
||||
super(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
void analyze(Variables variables) {
|
||||
if (!inLoop) {
|
||||
throw new IllegalArgumentException(error("Break statement outside of a loop."));
|
||||
throw createError(new IllegalArgumentException("Break statement outside of a loop."));
|
||||
}
|
||||
|
||||
loopEscape = true;
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.Variables.Variable;
|
||||
@ -42,8 +43,8 @@ public final class SCatch extends AStatement {
|
||||
Label end;
|
||||
Label exception;
|
||||
|
||||
public SCatch(int line, int offset, String location, String type, String name, SBlock block) {
|
||||
super(line, offset, location);
|
||||
public SCatch(Location location, String type, String name, SBlock block) {
|
||||
super(location);
|
||||
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
@ -57,11 +58,11 @@ public final class SCatch extends AStatement {
|
||||
try {
|
||||
type = Definition.getType(this.type);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
throw new IllegalArgumentException(error("Not a type [" + this.type + "]."));
|
||||
throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
|
||||
}
|
||||
|
||||
if (!Exception.class.isAssignableFrom(type.clazz)) {
|
||||
throw new ClassCastException(error("Not an exception type [" + this.type + "]."));
|
||||
throw createError(new ClassCastException("Not an exception type [" + this.type + "]."));
|
||||
}
|
||||
|
||||
variable = variables.addVariable(location, type, name, true, false);
|
||||
@ -84,7 +85,7 @@ public final class SCatch extends AStatement {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeStatementOffset(offset);
|
||||
writer.writeStatementOffset(location);
|
||||
Label jump = new Label();
|
||||
|
||||
writer.mark(jump);
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
/**
|
||||
@ -27,18 +28,18 @@ import org.elasticsearch.painless.MethodWriter;
|
||||
*/
|
||||
public final class SContinue extends AStatement {
|
||||
|
||||
public SContinue(int line, int offset, String location) {
|
||||
super(line, offset, location);
|
||||
public SContinue(Location location) {
|
||||
super(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
void analyze(Variables variables) {
|
||||
if (!inLoop) {
|
||||
throw new IllegalArgumentException(error("Continue statement outside of a loop."));
|
||||
throw createError(new IllegalArgumentException("Continue statement outside of a loop."));
|
||||
}
|
||||
|
||||
if (lastLoop) {
|
||||
throw new IllegalArgumentException(error("Extraneous continue statement."));
|
||||
throw createError(new IllegalArgumentException("Extraneous continue statement."));
|
||||
}
|
||||
|
||||
allEscape = true;
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
import java.util.Collections;
|
||||
@ -32,8 +33,8 @@ public final class SDeclBlock extends AStatement {
|
||||
|
||||
final List<SDeclaration> declarations;
|
||||
|
||||
public SDeclBlock(int line, int offset, String location, List<SDeclaration> declarations) {
|
||||
super(line, offset, location);
|
||||
public SDeclBlock(Location location, List<SDeclaration> declarations) {
|
||||
super(location);
|
||||
|
||||
this.declarations = Collections.unmodifiableList(declarations);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.Variables.Variable;
|
||||
@ -37,8 +38,8 @@ public final class SDeclaration extends AStatement {
|
||||
|
||||
Variable variable;
|
||||
|
||||
public SDeclaration(int line, int offset, String location, String type, String name, AExpression expression) {
|
||||
super(line, offset, location);
|
||||
public SDeclaration(Location location, String type, String name, AExpression expression) {
|
||||
super(location);
|
||||
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
@ -52,7 +53,7 @@ public final class SDeclaration extends AStatement {
|
||||
try {
|
||||
type = Definition.getType(this.type);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
throw new IllegalArgumentException(error("Not a type [" + this.type + "]."));
|
||||
throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
|
||||
}
|
||||
|
||||
if (expression != null) {
|
||||
@ -66,10 +67,10 @@ public final class SDeclaration extends AStatement {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeStatementOffset(offset);
|
||||
writer.writeStatementOffset(location);
|
||||
if (expression == null) {
|
||||
switch (variable.type.sort) {
|
||||
case VOID: throw new IllegalStateException(error("Illegal tree structure."));
|
||||
case VOID: throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
case BOOL:
|
||||
case BYTE:
|
||||
case SHORT:
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
@ -33,8 +34,8 @@ public final class SDo extends AStatement {
|
||||
final SBlock block;
|
||||
AExpression condition;
|
||||
|
||||
public SDo(int line, int offset, String location, int maxLoopCounter, SBlock block, AExpression condition) {
|
||||
super(line, offset, location);
|
||||
public SDo(Location location, int maxLoopCounter, SBlock block, AExpression condition) {
|
||||
super(location);
|
||||
|
||||
this.condition = condition;
|
||||
this.block = block;
|
||||
@ -46,7 +47,7 @@ public final class SDo extends AStatement {
|
||||
variables.incrementScope();
|
||||
|
||||
if (block == null) {
|
||||
throw new IllegalArgumentException(error("Extraneous do while loop."));
|
||||
throw createError(new IllegalArgumentException("Extraneous do while loop."));
|
||||
}
|
||||
|
||||
block.beginLoop = true;
|
||||
@ -55,7 +56,7 @@ public final class SDo extends AStatement {
|
||||
block.analyze(variables);
|
||||
|
||||
if (block.loopEscape && !block.anyContinue) {
|
||||
throw new IllegalArgumentException(error("Extraneous do while loop."));
|
||||
throw createError(new IllegalArgumentException("Extraneous do while loop."));
|
||||
}
|
||||
|
||||
condition.expected = Definition.BOOLEAN_TYPE;
|
||||
@ -66,7 +67,7 @@ public final class SDo extends AStatement {
|
||||
final boolean continuous = (boolean)condition.constant;
|
||||
|
||||
if (!continuous) {
|
||||
throw new IllegalArgumentException(error("Extraneous do while loop."));
|
||||
throw createError(new IllegalArgumentException("Extraneous do while loop."));
|
||||
}
|
||||
|
||||
if (!block.anyBreak) {
|
||||
@ -86,7 +87,7 @@ public final class SDo extends AStatement {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeStatementOffset(offset);
|
||||
writer.writeStatementOffset(location);
|
||||
Label start = new Label();
|
||||
Label begin = new Label();
|
||||
Label end = new Label();
|
||||
@ -102,7 +103,7 @@ public final class SDo extends AStatement {
|
||||
condition.fals = end;
|
||||
condition.write(writer);
|
||||
|
||||
writer.writeLoopCounter(loopCounterSlot, Math.max(1, block.statementCount), offset);
|
||||
writer.writeLoopCounter(loopCounterSlot, Math.max(1, block.statementCount), location);
|
||||
|
||||
writer.goTo(start);
|
||||
writer.mark(end);
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Sort;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
@ -31,8 +32,8 @@ public final class SExpression extends AStatement {
|
||||
|
||||
AExpression expression;
|
||||
|
||||
public SExpression(int line, int offset, String location, AExpression expression) {
|
||||
super(line, offset, location);
|
||||
public SExpression(Location location, AExpression expression) {
|
||||
super(location);
|
||||
|
||||
this.expression = expression;
|
||||
}
|
||||
@ -43,7 +44,7 @@ public final class SExpression extends AStatement {
|
||||
expression.analyze(variables);
|
||||
|
||||
if (!lastSource && !expression.statement) {
|
||||
throw new IllegalArgumentException(error("Not a statement."));
|
||||
throw createError(new IllegalArgumentException("Not a statement."));
|
||||
}
|
||||
|
||||
final boolean rtn = lastSource && expression.actual.sort != Sort.VOID;
|
||||
@ -60,7 +61,7 @@ public final class SExpression extends AStatement {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeStatementOffset(offset);
|
||||
writer.writeStatementOffset(location);
|
||||
expression.write(writer);
|
||||
|
||||
if (methodEscape) {
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
@ -35,9 +36,9 @@ public final class SFor extends AStatement {
|
||||
AExpression afterthought;
|
||||
final SBlock block;
|
||||
|
||||
public SFor(int line, int offset, String location, int maxLoopCounter,
|
||||
public SFor(Location location, int maxLoopCounter,
|
||||
ANode initializer, AExpression condition, AExpression afterthought, SBlock block) {
|
||||
super(line, offset, location);
|
||||
super(location);
|
||||
|
||||
this.initializer = initializer;
|
||||
this.condition = condition;
|
||||
@ -62,10 +63,10 @@ public final class SFor extends AStatement {
|
||||
initializer.analyze(variables);
|
||||
|
||||
if (!initializer.statement) {
|
||||
throw new IllegalArgumentException(initializer.error("Not a statement."));
|
||||
throw createError(new IllegalArgumentException("Not a statement."));
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException(error("Illegal tree structure."));
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,11 +79,11 @@ public final class SFor extends AStatement {
|
||||
continuous = (boolean)condition.constant;
|
||||
|
||||
if (!continuous) {
|
||||
throw new IllegalArgumentException(error("Extraneous for loop."));
|
||||
throw createError(new IllegalArgumentException("Extraneous for loop."));
|
||||
}
|
||||
|
||||
if (block == null) {
|
||||
throw new IllegalArgumentException(error("For loop has no escape."));
|
||||
throw createError(new IllegalArgumentException("For loop has no escape."));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -94,7 +95,7 @@ public final class SFor extends AStatement {
|
||||
afterthought.analyze(variables);
|
||||
|
||||
if (!afterthought.statement) {
|
||||
throw new IllegalArgumentException(afterthought.error("Not a statement."));
|
||||
throw createError(new IllegalArgumentException("Not a statement."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,7 +106,7 @@ public final class SFor extends AStatement {
|
||||
block.analyze(variables);
|
||||
|
||||
if (block.loopEscape && !block.anyContinue) {
|
||||
throw new IllegalArgumentException(error("Extraneous for loop."));
|
||||
throw createError(new IllegalArgumentException("Extraneous for loop."));
|
||||
}
|
||||
|
||||
if (continuous && !block.anyBreak) {
|
||||
@ -127,7 +128,7 @@ public final class SFor extends AStatement {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeStatementOffset(offset);
|
||||
writer.writeStatementOffset(location);
|
||||
Label start = new Label();
|
||||
Label begin = afterthought == null ? start : new Label();
|
||||
Label end = new Label();
|
||||
@ -159,10 +160,10 @@ public final class SFor extends AStatement {
|
||||
++statementCount;
|
||||
}
|
||||
|
||||
writer.writeLoopCounter(loopCounterSlot, statementCount, offset);
|
||||
writer.writeLoopCounter(loopCounterSlot, statementCount, location);
|
||||
block.write(writer);
|
||||
} else {
|
||||
writer.writeLoopCounter(loopCounterSlot, 1, offset);
|
||||
writer.writeLoopCounter(loopCounterSlot, 1, location);
|
||||
}
|
||||
|
||||
if (afterthought != null) {
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
@ -32,8 +33,8 @@ public final class SIf extends AStatement {
|
||||
AExpression condition;
|
||||
final SBlock ifblock;
|
||||
|
||||
public SIf(int line, int offset, String location, AExpression condition, SBlock ifblock) {
|
||||
super(line, offset, location);
|
||||
public SIf(Location location, AExpression condition, SBlock ifblock) {
|
||||
super(location);
|
||||
|
||||
this.condition = condition;
|
||||
this.ifblock = ifblock;
|
||||
@ -46,11 +47,11 @@ public final class SIf extends AStatement {
|
||||
condition = condition.cast(variables);
|
||||
|
||||
if (condition.constant != null) {
|
||||
throw new IllegalArgumentException(error("Extraneous if statement."));
|
||||
throw createError(new IllegalArgumentException("Extraneous if statement."));
|
||||
}
|
||||
|
||||
if (ifblock == null) {
|
||||
throw new IllegalArgumentException(error("Extraneous if statement."));
|
||||
throw createError(new IllegalArgumentException("Extraneous if statement."));
|
||||
}
|
||||
|
||||
ifblock.lastSource = lastSource;
|
||||
@ -68,7 +69,7 @@ public final class SIf extends AStatement {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeStatementOffset(offset);
|
||||
writer.writeStatementOffset(location);
|
||||
Label fals = new Label();
|
||||
|
||||
condition.fals = fals;
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
@ -33,8 +34,8 @@ public final class SIfElse extends AStatement {
|
||||
final SBlock ifblock;
|
||||
final SBlock elseblock;
|
||||
|
||||
public SIfElse(int line, int offset, String location, AExpression condition, SBlock ifblock, SBlock elseblock) {
|
||||
super(line, offset, location);
|
||||
public SIfElse(Location location, AExpression condition, SBlock ifblock, SBlock elseblock) {
|
||||
super(location);
|
||||
|
||||
this.condition = condition;
|
||||
this.ifblock = ifblock;
|
||||
@ -48,11 +49,11 @@ public final class SIfElse extends AStatement {
|
||||
condition = condition.cast(variables);
|
||||
|
||||
if (condition.constant != null) {
|
||||
throw new IllegalArgumentException(error("Extraneous if statement."));
|
||||
throw createError(new IllegalArgumentException("Extraneous if statement."));
|
||||
}
|
||||
|
||||
if (ifblock == null) {
|
||||
throw new IllegalArgumentException(error("Extraneous if statement."));
|
||||
throw createError(new IllegalArgumentException("Extraneous if statement."));
|
||||
}
|
||||
|
||||
ifblock.lastSource = lastSource;
|
||||
@ -68,7 +69,7 @@ public final class SIfElse extends AStatement {
|
||||
statementCount = ifblock.statementCount;
|
||||
|
||||
if (elseblock == null) {
|
||||
throw new IllegalArgumentException(error("Extraneous else statement."));
|
||||
throw createError(new IllegalArgumentException("Extraneous else statement."));
|
||||
}
|
||||
|
||||
elseblock.lastSource = lastSource;
|
||||
@ -89,7 +90,7 @@ public final class SIfElse extends AStatement {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeStatementOffset(offset);
|
||||
writer.writeStatementOffset(location);
|
||||
Label end = new Label();
|
||||
Label fals = elseblock != null ? new Label() : end;
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
@ -30,8 +31,8 @@ public final class SReturn extends AStatement {
|
||||
|
||||
AExpression expression;
|
||||
|
||||
public SReturn(int line, int offset, String location, AExpression expression) {
|
||||
super(line, offset, location);
|
||||
public SReturn(Location location, AExpression expression) {
|
||||
super(location);
|
||||
|
||||
this.expression = expression;
|
||||
}
|
||||
@ -52,7 +53,7 @@ public final class SReturn extends AStatement {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeStatementOffset(offset);
|
||||
writer.writeStatementOffset(location);
|
||||
expression.write(writer);
|
||||
writer.returnValue();
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
import java.util.Collections;
|
||||
@ -33,8 +34,8 @@ public final class SSource extends AStatement {
|
||||
|
||||
final List<AStatement> statements;
|
||||
|
||||
public SSource(int line, int offset, String location, List<AStatement> statements) {
|
||||
super(line, offset, location);
|
||||
public SSource(Location location, List<AStatement> statements) {
|
||||
super(location);
|
||||
|
||||
this.statements = Collections.unmodifiableList(statements);
|
||||
}
|
||||
@ -42,7 +43,7 @@ public final class SSource extends AStatement {
|
||||
@Override
|
||||
public void analyze(Variables variables) {
|
||||
if (statements == null || statements.isEmpty()) {
|
||||
throw new IllegalArgumentException(error("Cannot generate an empty script."));
|
||||
throw createError(new IllegalArgumentException("Cannot generate an empty script."));
|
||||
}
|
||||
|
||||
variables.incrementScope();
|
||||
@ -50,8 +51,9 @@ public final class SSource extends AStatement {
|
||||
final AStatement last = statements.get(statements.size() - 1);
|
||||
|
||||
for (AStatement statement : statements) {
|
||||
// TODO: why are we checking only statements 0..n-1 (this effectively checks only the previous statement)
|
||||
if (allEscape) {
|
||||
throw new IllegalArgumentException(error("Unreachable statement."));
|
||||
throw createError(new IllegalArgumentException("Unreachable statement."));
|
||||
}
|
||||
|
||||
statement.lastSource = statement == last;
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
@ -30,8 +31,8 @@ public final class SThrow extends AStatement {
|
||||
|
||||
AExpression expression;
|
||||
|
||||
public SThrow(int line, int offset, String location, AExpression expression) {
|
||||
super(line, offset, location);
|
||||
public SThrow(Location location, AExpression expression) {
|
||||
super(location);
|
||||
|
||||
this.expression = expression;
|
||||
}
|
||||
@ -50,7 +51,7 @@ public final class SThrow extends AStatement {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeStatementOffset(offset);
|
||||
writer.writeStatementOffset(location);
|
||||
expression.write(writer);
|
||||
writer.throwException();
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
import java.util.Collections;
|
||||
@ -34,8 +35,8 @@ public final class STry extends AStatement {
|
||||
final SBlock block;
|
||||
final List<SCatch> catches;
|
||||
|
||||
public STry(int line, int offset, String location, SBlock block, List<SCatch> traps) {
|
||||
super(line, offset, location);
|
||||
public STry(Location location, SBlock block, List<SCatch> traps) {
|
||||
super(location);
|
||||
|
||||
this.block = block;
|
||||
this.catches = Collections.unmodifiableList(traps);
|
||||
@ -44,7 +45,7 @@ public final class STry extends AStatement {
|
||||
@Override
|
||||
void analyze(Variables variables) {
|
||||
if (block == null) {
|
||||
throw new IllegalArgumentException(error("Extraneous try statement."));
|
||||
throw createError(new IllegalArgumentException("Extraneous try statement."));
|
||||
}
|
||||
|
||||
block.lastSource = lastSource;
|
||||
@ -86,7 +87,7 @@ public final class STry extends AStatement {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeStatementOffset(offset);
|
||||
writer.writeStatementOffset(location);
|
||||
Label begin = new Label();
|
||||
Label end = new Label();
|
||||
Label exception = new Label();
|
||||
|
@ -20,6 +20,7 @@
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
@ -33,8 +34,8 @@ public final class SWhile extends AStatement {
|
||||
AExpression condition;
|
||||
final SBlock block;
|
||||
|
||||
public SWhile(int line, int offset, String location, int maxLoopCounter, AExpression condition, SBlock block) {
|
||||
super(line, offset, location);
|
||||
public SWhile(Location location, int maxLoopCounter, AExpression condition, SBlock block) {
|
||||
super(location);
|
||||
|
||||
this.maxLoopCounter = maxLoopCounter;
|
||||
this.condition = condition;
|
||||
@ -55,11 +56,11 @@ public final class SWhile extends AStatement {
|
||||
continuous = (boolean)condition.constant;
|
||||
|
||||
if (!continuous) {
|
||||
throw new IllegalArgumentException(error("Extraneous while loop."));
|
||||
throw createError(new IllegalArgumentException("Extraneous while loop."));
|
||||
}
|
||||
|
||||
if (block == null) {
|
||||
throw new IllegalArgumentException(error("While loop has no escape."));
|
||||
throw createError(new IllegalArgumentException("While loop has no escape."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,7 +71,7 @@ public final class SWhile extends AStatement {
|
||||
block.analyze(variables);
|
||||
|
||||
if (block.loopEscape && !block.anyContinue) {
|
||||
throw new IllegalArgumentException(error("Extraneous while loop."));
|
||||
throw createError(new IllegalArgumentException("Extraneous while loop."));
|
||||
}
|
||||
|
||||
if (continuous && !block.anyBreak) {
|
||||
@ -92,7 +93,7 @@ public final class SWhile extends AStatement {
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeStatementOffset(offset);
|
||||
writer.writeStatementOffset(location);
|
||||
Label begin = new Label();
|
||||
Label end = new Label();
|
||||
|
||||
@ -102,13 +103,13 @@ public final class SWhile extends AStatement {
|
||||
condition.write(writer);
|
||||
|
||||
if (block != null) {
|
||||
writer.writeLoopCounter(loopCounterSlot, Math.max(1, block.statementCount), offset);
|
||||
writer.writeLoopCounter(loopCounterSlot, Math.max(1, block.statementCount), location);
|
||||
|
||||
block.continu = begin;
|
||||
block.brake = end;
|
||||
block.write(writer);
|
||||
} else {
|
||||
writer.writeLoopCounter(loopCounterSlot, 1, offset);
|
||||
writer.writeLoopCounter(loopCounterSlot, 1, location);
|
||||
}
|
||||
|
||||
if (block == null || !block.allEscape) {
|
||||
|
@ -24,8 +24,8 @@
|
||||
* A* (abstract) - These are the abstract nodes that are the superclasses for the other types.
|
||||
* I* (interface) -- Thse are marker interfaces to denote a property of the node.
|
||||
* S* (statement) - These are nodes that represent a statement in Painless. These are the highest level nodes.
|
||||
* E* (expression) - These are nodess that represent an expression in Painless. These are the middle level nodes.
|
||||
* L* (link) - These are nodes that respresent a piece of a variable/method chain. The are the lowest level nodes.
|
||||
* E* (expression) - These are nodes that represent an expression in Painless. These are the middle level nodes.
|
||||
* L* (link) - These are nodes that represent a piece of a variable/method chain. The are the lowest level nodes.
|
||||
* <p>
|
||||
* The following is a brief description of each node:
|
||||
* {@link org.elasticsearch.painless.node.AExpression} - The superclass for all E* (expression) nodes.
|
||||
@ -38,18 +38,18 @@
|
||||
* {@link org.elasticsearch.painless.node.ECast} - Represents an implicit cast in most cases. (Internal only.)
|
||||
* {@link org.elasticsearch.painless.node.EChain} - Represents the entirety of a variable/method chain for read/write operations.
|
||||
* {@link org.elasticsearch.painless.node.EComp} - Represents a comparison expression.
|
||||
* {@link org.elasticsearch.painless.node.EConditional} - Respresents a conditional expression.
|
||||
* {@link org.elasticsearch.painless.node.EConstant} - Respresents a constant. (Internal only.)
|
||||
* {@link org.elasticsearch.painless.node.EDecimal} - Respresents a decimal constant.
|
||||
* {@link org.elasticsearch.painless.node.EConditional} - Represents a conditional expression.
|
||||
* {@link org.elasticsearch.painless.node.EConstant} - Represents a constant. (Internal only.)
|
||||
* {@link org.elasticsearch.painless.node.EDecimal} - Represents a decimal constant.
|
||||
* {@link org.elasticsearch.painless.node.EExplicit} - Represents an explicit cast.
|
||||
* {@link org.elasticsearch.painless.node.EFunctionRef} - Represents a function reference.
|
||||
* {@link org.elasticsearch.painless.node.ENull} - Represents a null constant.
|
||||
* {@link org.elasticsearch.painless.node.ENumeric} - Respresents a non-decimal numeric constant.
|
||||
* {@link org.elasticsearch.painless.node.ENumeric} - Represents a non-decimal numeric constant.
|
||||
* {@link org.elasticsearch.painless.node.EUnary} - Represents a unary math expression.
|
||||
* {@link org.elasticsearch.painless.node.IDefLink} - A marker interface for all LDef* (link) nodes.
|
||||
* {@link org.elasticsearch.painless.node.LArrayLength} - Represents an array length field load.
|
||||
* {@link org.elasticsearch.painless.node.LBrace} - Represents an array load/store or defers to possible shortcuts.
|
||||
* {@link org.elasticsearch.painless.node.LCall} - Represents a method call or deferes to a def call.
|
||||
* {@link org.elasticsearch.painless.node.LCall} - Represents a method call or defers to a def call.
|
||||
* {@link org.elasticsearch.painless.node.LCast} - Represents a cast made in a variable/method chain.
|
||||
* {@link org.elasticsearch.painless.node.LDefArray} - Represents an array load/store or shortcut on a def type. (Internal only.)
|
||||
* {@link org.elasticsearch.painless.node.LDefCall} - Represents a method call made on a def type. (Internal only.)
|
||||
@ -58,7 +58,7 @@
|
||||
* {@link org.elasticsearch.painless.node.LListShortcut} - Represents a list load/store shortcut. (Internal only.)
|
||||
* {@link org.elasticsearch.painless.node.LMapShortcut} - Represents a map load/store shortcut. (Internal only.)
|
||||
* {@link org.elasticsearch.painless.node.LNewArray} - Represents an array instantiation.
|
||||
* {@link org.elasticsearch.painless.node.LNewObj} - Respresents and object instantiation.
|
||||
* {@link org.elasticsearch.painless.node.LNewObj} - Represents and object instantiation.
|
||||
* {@link org.elasticsearch.painless.node.LShortcut} - Represents a field load/store shortcut. (Internal only.)
|
||||
* {@link org.elasticsearch.painless.node.LStatic} - Represents a static type target.
|
||||
* {@link org.elasticsearch.painless.node.LString} - Represents a string constant.
|
||||
|
@ -70,24 +70,20 @@ public class ConditionalTests extends ScriptTestCase {
|
||||
}
|
||||
|
||||
public void testIncompatibleAssignment() {
|
||||
try {
|
||||
expectScriptThrows(ClassCastException.class, () -> {
|
||||
exec("boolean x = false; byte z = x ? 2 : 4.0F; return z;");
|
||||
fail("expected class cast exception");
|
||||
} catch (ClassCastException expected) {}
|
||||
});
|
||||
|
||||
try {
|
||||
expectScriptThrows(ClassCastException.class, () -> {
|
||||
exec("boolean x = false; Map z = x ? 4 : (byte)7; return z;");
|
||||
fail("expected class cast exception");
|
||||
} catch (ClassCastException expected) {}
|
||||
});
|
||||
|
||||
try {
|
||||
expectScriptThrows(ClassCastException.class, () -> {
|
||||
exec("boolean x = false; Map z = x ? new HashMap() : new ArrayList(); return z;");
|
||||
fail("expected class cast exception");
|
||||
} catch (ClassCastException expected) {}
|
||||
});
|
||||
|
||||
try {
|
||||
expectScriptThrows(ClassCastException.class, () -> {
|
||||
exec("boolean x = false; int y = 2; byte z = x ? y : 7; return z;");
|
||||
fail("expected class cast exception");
|
||||
} catch (ClassCastException expected) {}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -124,11 +124,11 @@ public class DivisionTests extends ScriptTestCase {
|
||||
}
|
||||
|
||||
public void testDivideByZeroConst() throws Exception {
|
||||
expectThrows(ArithmeticException.class, () -> {
|
||||
expectScriptThrows(ArithmeticException.class, () -> {
|
||||
exec("return 1/0;");
|
||||
});
|
||||
|
||||
expectThrows(ArithmeticException.class, () -> {
|
||||
expectScriptThrows(ArithmeticException.class, () -> {
|
||||
exec("return 1L/0L;");
|
||||
});
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ package org.elasticsearch.painless;
|
||||
|
||||
public class FunctionRefTests extends ScriptTestCase {
|
||||
public void testUnsupported() {
|
||||
expectThrows(UnsupportedOperationException.class, () -> {
|
||||
expectScriptThrows(UnsupportedOperationException.class, () -> {
|
||||
exec("DoubleStream.Builder builder = DoubleStream.builder();" +
|
||||
"builder.add(2.0); builder.add(1.0); builder.add(3.0);" +
|
||||
"builder.build().reduce(Double::unsupported);");
|
||||
|
@ -25,7 +25,7 @@ public class OverloadTests extends ScriptTestCase {
|
||||
public void testMethod() {
|
||||
assertEquals(2, exec("return 'abc123abc'.indexOf('c');"));
|
||||
assertEquals(8, exec("return 'abc123abc'.indexOf('c', 3);"));
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
IllegalArgumentException expected = expectScriptThrows(IllegalArgumentException.class, () -> {
|
||||
exec("return 'abc123abc'.indexOf('c', 3, 'bogus');");
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("[indexOf] with [3] arguments"));
|
||||
|
@ -124,18 +124,12 @@ public class RemainderTests extends ScriptTestCase {
|
||||
}
|
||||
|
||||
public void testDivideByZeroConst() throws Exception {
|
||||
try {
|
||||
expectScriptThrows(ArithmeticException.class, () -> {
|
||||
exec("return 1%0;");
|
||||
fail("should have hit exception");
|
||||
} catch (ArithmeticException expected) {
|
||||
// divide by zero
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
expectScriptThrows(ArithmeticException.class, () -> {
|
||||
exec("return 1L%0L;");
|
||||
fail("should have hit exception");
|
||||
} catch (ArithmeticException expected) {
|
||||
// divide by zero
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class ReservedWordTests extends ScriptTestCase {
|
||||
|
||||
/** check that we can't declare a variable of _score, its really reserved! */
|
||||
public void testScoreVar() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
IllegalArgumentException expected = expectScriptThrows(IllegalArgumentException.class, () -> {
|
||||
exec("int _score = 5; return _score;");
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("Variable name [_score] is reserved"));
|
||||
@ -35,7 +35,7 @@ public class ReservedWordTests extends ScriptTestCase {
|
||||
|
||||
/** check that we can't write to _score, its read-only! */
|
||||
public void testScoreStore() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
IllegalArgumentException expected = expectScriptThrows(IllegalArgumentException.class, () -> {
|
||||
exec("_score = 5; return _score;");
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("Variable [_score] is read-only"));
|
||||
@ -43,7 +43,7 @@ public class ReservedWordTests extends ScriptTestCase {
|
||||
|
||||
/** check that we can't declare a variable of doc, its really reserved! */
|
||||
public void testDocVar() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
IllegalArgumentException expected = expectScriptThrows(IllegalArgumentException.class, () -> {
|
||||
exec("int doc = 5; return doc;");
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("Variable name [doc] is reserved"));
|
||||
@ -51,7 +51,7 @@ public class ReservedWordTests extends ScriptTestCase {
|
||||
|
||||
/** check that we can't write to doc, its read-only! */
|
||||
public void testDocStore() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
IllegalArgumentException expected = expectScriptThrows(IllegalArgumentException.class, () -> {
|
||||
exec("doc = 5; return doc;");
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("Variable [doc] is read-only"));
|
||||
@ -59,7 +59,7 @@ public class ReservedWordTests extends ScriptTestCase {
|
||||
|
||||
/** check that we can't declare a variable of ctx, its really reserved! */
|
||||
public void testCtxVar() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
IllegalArgumentException expected = expectScriptThrows(IllegalArgumentException.class, () -> {
|
||||
exec("int ctx = 5; return ctx;");
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("Variable name [ctx] is reserved"));
|
||||
@ -67,7 +67,7 @@ public class ReservedWordTests extends ScriptTestCase {
|
||||
|
||||
/** check that we can't write to ctx, its read-only! */
|
||||
public void testCtxStore() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
IllegalArgumentException expected = expectScriptThrows(IllegalArgumentException.class, () -> {
|
||||
exec("ctx = 5; return ctx;");
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("Variable [ctx] is read-only"));
|
||||
@ -80,7 +80,7 @@ public class ReservedWordTests extends ScriptTestCase {
|
||||
|
||||
/** check that we can't declare a variable of _value, its really reserved! */
|
||||
public void testAggregationValueVar() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
IllegalArgumentException expected = expectScriptThrows(IllegalArgumentException.class, () -> {
|
||||
exec("int _value = 5; return _value;");
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("Variable name [_value] is reserved"));
|
||||
@ -88,7 +88,7 @@ public class ReservedWordTests extends ScriptTestCase {
|
||||
|
||||
/** check that we can't write to _value, its read-only! */
|
||||
public void testAggregationValueStore() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
IllegalArgumentException expected = expectScriptThrows(IllegalArgumentException.class, () -> {
|
||||
exec("_value = 5; return _value;");
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("Variable [_value] is read-only"));
|
||||
|
@ -71,11 +71,11 @@ public class WhenThingsGoWrongTests extends ScriptTestCase {
|
||||
}
|
||||
|
||||
public void testInvalidShift() {
|
||||
expectThrows(ClassCastException.class, () -> {
|
||||
expectScriptThrows(ClassCastException.class, () -> {
|
||||
exec("float x = 15F; x <<= 2; return x;");
|
||||
});
|
||||
|
||||
expectThrows(ClassCastException.class, () -> {
|
||||
expectScriptThrows(ClassCastException.class, () -> {
|
||||
exec("double x = 15F; x <<= 2; return x;");
|
||||
});
|
||||
}
|
||||
@ -134,7 +134,7 @@ public class WhenThingsGoWrongTests extends ScriptTestCase {
|
||||
assertTrue(expected.getMessage().contains(
|
||||
"The maximum number of statements that can be executed in a loop has been reached."));
|
||||
|
||||
RuntimeException parseException = expectThrows(RuntimeException.class, () -> {
|
||||
RuntimeException parseException = expectScriptThrows(RuntimeException.class, () -> {
|
||||
exec("try { int x; } catch (PainlessError error) {}");
|
||||
fail("should have hit ParseException");
|
||||
});
|
||||
@ -156,7 +156,7 @@ public class WhenThingsGoWrongTests extends ScriptTestCase {
|
||||
final char[] tooManyChars = new char[Compiler.MAXIMUM_SOURCE_LENGTH + 1];
|
||||
Arrays.fill(tooManyChars, '0');
|
||||
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
IllegalArgumentException expected = expectScriptThrows(IllegalArgumentException.class, () -> {
|
||||
exec(new String(tooManyChars));
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("Scripts may be no longer than"));
|
||||
|
@ -40,9 +40,9 @@ public class ParserTests extends ScriptTestCase {
|
||||
|
||||
private SourceContext buildAntlrTree(String source) {
|
||||
ANTLRInputStream stream = new ANTLRInputStream(source);
|
||||
PainlessLexer lexer = new ErrorHandlingLexer(stream);
|
||||
PainlessLexer lexer = new ErrorHandlingLexer(stream, "testing");
|
||||
PainlessParser parser = new PainlessParser(new CommonTokenStream(lexer));
|
||||
ParserErrorStrategy strategy = new ParserErrorStrategy();
|
||||
ParserErrorStrategy strategy = new ParserErrorStrategy("testing");
|
||||
|
||||
lexer.removeErrorListeners();
|
||||
parser.removeErrorListeners();
|
||||
|
@ -47,7 +47,7 @@
|
||||
body: { "script": "_score * foo bar + doc['myParent.weight'].value" }
|
||||
|
||||
- do:
|
||||
catch: /Unable.to.parse.*/
|
||||
catch: /compile error/
|
||||
put_script:
|
||||
id: "1"
|
||||
lang: "painless"
|
||||
|
Loading…
x
Reference in New Issue
Block a user