From f98be6fa062795a5421102d90f3dd4cff58bb3a1 Mon Sep 17 00:00:00 2001
From: Jack Conradson
Date: Fri, 10 Jun 2016 13:59:59 -0700
Subject: [PATCH] Add functions to Painless.
Closes #18810
---
.../src/main/antlr/PainlessParser.g4 | 11 +-
.../org/elasticsearch/painless/Analyzer.java | 37 -
.../org/elasticsearch/painless/Compiler.java | 26 +-
.../elasticsearch/painless/Definition.java | 30 +-
.../painless/{Variables.java => Locals.java} | 175 ++-
.../elasticsearch/painless/MethodWriter.java | 8 +-
.../org/elasticsearch/painless/Writer.java | 144 ---
.../painless/WriterConstants.java | 8 +-
.../painless/antlr/PainlessParser.java | 1072 ++++++++++-------
.../antlr/PainlessParserBaseVisitor.java | 21 +
.../painless/antlr/PainlessParserVisitor.java | 19 +
.../elasticsearch/painless/antlr/Walker.java | 111 +-
.../painless/node/AExpression.java | 12 +-
.../elasticsearch/painless/node/ALink.java | 4 +-
.../painless/node/AStatement.java | 4 +-
.../elasticsearch/painless/node/EBinary.java | 48 +-
.../elasticsearch/painless/node/EBool.java | 12 +-
.../elasticsearch/painless/node/EBoolean.java | 4 +-
.../elasticsearch/painless/node/ECast.java | 4 +-
.../elasticsearch/painless/node/EChain.java | 16 +-
.../elasticsearch/painless/node/EComp.java | 36 +-
.../painless/node/EConditional.java | 16 +-
.../painless/node/EConstant.java | 4 +-
.../elasticsearch/painless/node/EDecimal.java | 4 +-
.../painless/node/EExplicit.java | 12 +-
.../painless/node/EFunctionRef.java | 34 +-
.../elasticsearch/painless/node/ENull.java | 4 +-
.../elasticsearch/painless/node/ENumeric.java | 4 +-
.../elasticsearch/painless/node/EUnary.java | 20 +-
.../painless/node/LArrayLength.java | 4 +-
.../elasticsearch/painless/node/LBrace.java | 14 +-
.../node/{LCall.java => LCallInvoke.java} | 26 +-
.../painless/node/LCallLocal.java | 99 ++
.../elasticsearch/painless/node/LCast.java | 4 +-
.../painless/node/LDefArray.java | 8 +-
.../elasticsearch/painless/node/LDefCall.java | 10 +-
.../painless/node/LDefField.java | 4 +-
.../elasticsearch/painless/node/LField.java | 16 +-
.../painless/node/LListShortcut.java | 8 +-
.../painless/node/LMapShortcut.java | 8 +-
.../painless/node/LNewArray.java | 8 +-
.../elasticsearch/painless/node/LNewObj.java | 8 +-
.../painless/node/LShortcut.java | 4 +-
.../elasticsearch/painless/node/LStatic.java | 4 +-
.../elasticsearch/painless/node/LString.java | 4 +-
.../painless/node/LVariable.java | 8 +-
.../elasticsearch/painless/node/SBlock.java | 6 +-
.../elasticsearch/painless/node/SBreak.java | 4 +-
.../elasticsearch/painless/node/SCatch.java | 10 +-
.../painless/node/SContinue.java | 4 +-
.../painless/node/SDeclBlock.java | 6 +-
.../painless/node/SDeclaration.java | 12 +-
.../org/elasticsearch/painless/node/SDo.java | 22 +-
.../elasticsearch/painless/node/SEach.java | 44 +-
.../painless/node/SExpression.java | 18 +-
.../org/elasticsearch/painless/node/SFor.java | 29 +-
.../painless/node/SFunction.java | 163 +++
.../org/elasticsearch/painless/node/SIf.java | 14 +-
.../elasticsearch/painless/node/SIfElse.java | 20 +-
.../elasticsearch/painless/node/SReturn.java | 11 +-
.../elasticsearch/painless/node/SSource.java | 151 ++-
.../elasticsearch/painless/node/SThrow.java | 8 +-
.../org/elasticsearch/painless/node/STry.java | 16 +-
.../elasticsearch/painless/node/SWhile.java | 22 +-
.../painless/node/package-info.java | 4 +-
.../elasticsearch/painless/FunctionTests.java | 69 ++
.../painless/ReservedWordTests.java | 8 +-
67 files changed, 1723 insertions(+), 1055 deletions(-)
delete mode 100644 modules/lang-painless/src/main/java/org/elasticsearch/painless/Analyzer.java
rename modules/lang-painless/src/main/java/org/elasticsearch/painless/{Variables.java => Locals.java} (52%)
delete mode 100644 modules/lang-painless/src/main/java/org/elasticsearch/painless/Writer.java
rename modules/lang-painless/src/main/java/org/elasticsearch/painless/node/{LCall.java => LCallInvoke.java} (79%)
create mode 100644 modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LCallLocal.java
create mode 100644 modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFunction.java
create mode 100644 modules/lang-painless/src/test/java/org/elasticsearch/painless/FunctionTests.java
diff --git a/modules/lang-painless/src/main/antlr/PainlessParser.g4 b/modules/lang-painless/src/main/antlr/PainlessParser.g4
index 141ff25e318..31b6a9445ea 100644
--- a/modules/lang-painless/src/main/antlr/PainlessParser.g4
+++ b/modules/lang-painless/src/main/antlr/PainlessParser.g4
@@ -22,7 +22,15 @@ parser grammar PainlessParser;
options { tokenVocab=PainlessLexer; }
source
- : statement* EOF
+ : function* statement* EOF
+ ;
+
+function
+ : decltype ID parameters block
+ ;
+
+parameters
+ : LP ( decltype ID ( COMMA decltype ID )* )? RP
;
// Note we use a predicate on the if/else case here to prevent the
@@ -143,6 +151,7 @@ primary[boolean c] returns [boolean s = true]
| { $c }? LP unary[true] RP # chainprec
| STRING # string
| ID # variable
+ | ID arguments # calllocal
| NEW TYPE arguments # newobject
;
diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Analyzer.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Analyzer.java
deleted file mode 100644
index a06bcdf9840..00000000000
--- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Analyzer.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.painless;
-
-import org.elasticsearch.painless.Variables.Reserved;
-import org.elasticsearch.painless.node.SSource;
-
-/**
- * Runs the analysis phase of compilation using the Painless AST.
- */
-final class Analyzer {
- static Variables analyze(Reserved shortcut, SSource root) {
- Variables variables = new Variables(shortcut);
- root.analyze(variables);
-
- return variables;
- }
-
- private Analyzer() {}
-}
diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java
index d0a17f64a48..8fa9f5d583e 100644
--- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java
+++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Compiler.java
@@ -20,7 +20,6 @@
package org.elasticsearch.painless;
import org.elasticsearch.bootstrap.BootstrapInfo;
-import org.elasticsearch.painless.Variables.Reserved;
import org.elasticsearch.painless.antlr.Walker;
import org.elasticsearch.painless.node.SSource;
@@ -36,8 +35,7 @@ import static org.elasticsearch.painless.WriterConstants.CLASS_NAME;
/**
* The Compiler is the entry point for generating a Painless script. The compiler will receive a Painless
* tree based on the type of input passed in (currently only ANTLR). Two passes will then be run over the tree,
- * one for analysis using the {@link Analyzer} and another to generate the actual byte code using ASM in
- * the {@link Writer}.
+ * one for analysis and another to generate the actual byte code using ASM using the root of the tree {@link SSource}.
*/
final class Compiler {
@@ -100,18 +98,17 @@ final class Compiler {
" plugin if a script longer than this length is a requirement.");
}
- Reserved reserved = new Reserved();
- SSource root = Walker.buildPainlessTree(name, source, reserved, settings);
- Variables variables = Analyzer.analyze(reserved, root);
- BitSet expressions = new BitSet(source.length());
- byte[] bytes = Writer.write(settings, name, source, variables, root, expressions);
+ SSource root = Walker.buildPainlessTree(name, source, settings);
+
+ root.analyze();
+ root.write();
try {
- Class extends Executable> clazz = loader.define(CLASS_NAME, bytes);
+ Class extends Executable> clazz = loader.define(CLASS_NAME, root.getBytes());
java.lang.reflect.Constructor extends Executable> constructor =
clazz.getConstructor(String.class, String.class, BitSet.class);
- return constructor.newInstance(name, source, expressions);
+ return constructor.newInstance(name, source, root.getExpressions());
} catch (Exception exception) { // Catch everything to let the user know this is something caused internally.
throw new IllegalStateException("An internal error occurred attempting to define the script [" + name + "].", exception);
}
@@ -130,11 +127,12 @@ final class Compiler {
" plugin if a script longer than this length is a requirement.");
}
- Reserved reserved = new Reserved();
- SSource root = Walker.buildPainlessTree(name, source, reserved, settings);
- Variables variables = Analyzer.analyze(reserved, root);
+ SSource root = Walker.buildPainlessTree(name, source, settings);
- return Writer.write(settings, name, source, variables, root, new BitSet(source.length()));
+ root.analyze();
+ root.write();
+
+ return root.getBytes();
}
/**
diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java
index dbfc9993c31..a8d4a803361 100644
--- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java
+++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Definition.java
@@ -45,9 +45,9 @@ import java.util.Spliterator;
* methods and fields during at both compile-time and runtime.
*/
public final class Definition {
-
+
private static final List DEFINITION_FILES = Collections.unmodifiableList(
- Arrays.asList("org.elasticsearch.txt",
+ Arrays.asList("org.elasticsearch.txt",
"java.lang.txt",
"java.math.txt",
"java.text.txt",
@@ -188,8 +188,8 @@ public final class Definition {
public final int modifiers;
public final MethodHandle handle;
- private Method(String name, Struct owner, Type rtn, List arguments,
- org.objectweb.asm.commons.Method method, int modifiers, MethodHandle handle) {
+ public Method(String name, Struct owner, Type rtn, List arguments,
+ org.objectweb.asm.commons.Method method, int modifiers, MethodHandle handle) {
this.name = name;
this.owner = owner;
this.rtn = rtn;
@@ -286,7 +286,7 @@ public final class Definition {
public final Map staticMembers;
public final Map members;
-
+
private final SetOnce functionalMethod;
private Struct(final String name, final Class> clazz, final org.objectweb.asm.Type type) {
@@ -300,8 +300,8 @@ public final class Definition {
staticMembers = new HashMap<>();
members = new HashMap<>();
-
- functionalMethod = new SetOnce();
+
+ functionalMethod = new SetOnce<>();
}
private Struct(final Struct struct) {
@@ -315,7 +315,7 @@ public final class Definition {
staticMembers = Collections.unmodifiableMap(struct.staticMembers);
members = Collections.unmodifiableMap(struct.members);
-
+
functionalMethod = struct.functionalMethod;
}
@@ -342,8 +342,8 @@ public final class Definition {
public int hashCode() {
return name.hashCode();
}
-
- /**
+
+ /**
* If this class is a functional interface according to JLS, returns its method.
* Otherwise returns null.
*/
@@ -637,7 +637,7 @@ public final class Definition {
final org.objectweb.asm.commons.Method asm = org.objectweb.asm.commons.Method.getMethod(reflect);
final Type returnType = getTypeInternal("void");
final MethodHandle handle;
-
+
try {
handle = MethodHandles.publicLookup().in(owner.clazz).unreflectConstructor(reflect);
} catch (final IllegalAccessException exception) {
@@ -645,7 +645,7 @@ public final class Definition {
" not found for class [" + owner.clazz.getName() + "]" +
" with arguments " + Arrays.toString(classes) + ".");
}
-
+
final Method constructor = new Method(name, owner, returnType, Arrays.asList(args), asm, reflect.getModifiers(), handle);
owner.constructors.put(methodKey, constructor);
@@ -755,7 +755,7 @@ public final class Definition {
" method [" + name + "]" +
" within the struct [" + owner.name + "].");
}
-
+
final org.objectweb.asm.commons.Method asm = org.objectweb.asm.commons.Method.getMethod(reflect);
MethodHandle handle;
@@ -856,7 +856,7 @@ public final class Definition {
throw new ClassCastException("Child struct [" + child.name + "]" +
" is not a super type of owner struct [" + owner.name + "] in copy.");
}
-
+
for (Map.Entry kvPair : child.methods.entrySet()) {
MethodKey methodKey = kvPair.getKey();
Method method = kvPair.getValue();
@@ -954,7 +954,7 @@ public final class Definition {
runtimeMap.put(struct.clazz, new RuntimeClass(methods, getters, setters));
}
-
+
/** computes the functional interface method for a class, or returns null */
private Method computeFunctionalInterfaceMethod(Struct clazz) {
if (!clazz.clazz.isInterface()) {
diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Variables.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Locals.java
similarity index 52%
rename from modules/lang-painless/src/main/java/org/elasticsearch/painless/Variables.java
rename to modules/lang-painless/src/main/java/org/elasticsearch/painless/Locals.java
index 4905011520a..d102114bdeb 100644
--- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Variables.java
+++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Locals.java
@@ -19,16 +19,21 @@
package org.elasticsearch.painless;
+import org.elasticsearch.painless.Definition.Method;
+import org.elasticsearch.painless.Definition.MethodKey;
import org.elasticsearch.painless.Definition.Type;
import java.util.ArrayDeque;
+import java.util.Collections;
import java.util.Deque;
import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
/**
- * Tracks variables across compilation phases.
+ * Tracks user defined methods and variables across compilation phases.
*/
-public final class Variables {
+public final class Locals {
/**
* Tracks reserved variables. Must be given to any source of input
@@ -36,7 +41,15 @@ public final class Variables {
* are known ahead of time to assign appropriate slots without
* being wasteful.
*/
- public static final class Reserved {
+ public interface Reserved {
+ void markReserved(String name);
+ boolean isReserved(String name);
+
+ void setMaxLoopCounter(int max);
+ int getMaxLoopCounter();
+ }
+
+ public static final class ExecuteReserved implements Reserved {
public static final String THIS = "#this";
public static final String PARAMS = "params";
public static final String SCORER = "#scorer";
@@ -46,10 +59,11 @@ public final class Variables {
public static final String CTX = "ctx";
public static final String LOOP = "#loop";
- boolean score = false;
- boolean ctx = false;
- boolean loop = false;
+ private boolean score = false;
+ private boolean ctx = false;
+ private int maxLoopCounter = 0;
+ @Override
public void markReserved(String name) {
if (SCORE.equals(name)) {
score = true;
@@ -58,13 +72,53 @@ public final class Variables {
}
}
+ @Override
public boolean isReserved(String name) {
return name.equals(THIS) || name.equals(PARAMS) || name.equals(SCORER) || name.equals(DOC) ||
name.equals(VALUE) || name.equals(SCORE) || name.equals(CTX) || name.equals(LOOP);
- }
+ }
- public void usesLoop() {
- loop = true;
+ public boolean usesScore() {
+ return score;
+ }
+
+ public boolean usesCtx() {
+ return ctx;
+ }
+
+ @Override
+ public void setMaxLoopCounter(int max) {
+ maxLoopCounter = max;
+ }
+
+ @Override
+ public int getMaxLoopCounter() {
+ return maxLoopCounter;
+ }
+ }
+
+ public static final class FunctionReserved implements Reserved {
+ public static final String THIS = "#this";
+ public static final String LOOP = "#loop";
+
+ private int maxLoopCounter = 0;
+
+ public void markReserved(String name) {
+ // Do nothing.
+ }
+
+ public boolean isReserved(String name) {
+ return name.equals(THIS) || name.equals(LOOP);
+ }
+
+ @Override
+ public void setMaxLoopCounter(int max) {
+ maxLoopCounter = max;
+ }
+
+ @Override
+ public int getMaxLoopCounter() {
+ return maxLoopCounter;
}
}
@@ -86,52 +140,97 @@ public final class Variables {
}
}
- final Reserved reserved;
+ public static final class Parameter {
+ public final Location location;
+ public final String name;
+ public final Type type;
+
+ public Parameter(Location location, String name, Type type) {
+ this.location = location;
+ this.name = name;
+ this.type = type;
+ }
+ }
+
+ private final Reserved reserved;
+ private final Map methods;
+ private final Type rtnType;
// TODO: this datastructure runs in linear time for nearly all operations. use linkedhashset instead?
private final Deque scopes = new ArrayDeque<>();
private final Deque variables = new ArrayDeque<>();
- public Variables(Reserved reserved) {
+ public Locals(ExecuteReserved reserved, Map methods) {
this.reserved = reserved;
+ this.methods = Collections.unmodifiableMap(methods);
+ this.rtnType = Definition.OBJECT_TYPE;
incrementScope();
// Method variables.
// This reference. Internal use only.
- addVariable(null, Definition.getType("Object"), Reserved.THIS, true, true);
+ addVariable(null, Definition.getType("Object"), ExecuteReserved.THIS, true, true);
// Input map of variables passed to the script.
- addVariable(null, Definition.getType("Map"), Reserved.PARAMS, true, true);
+ addVariable(null, Definition.getType("Map"), ExecuteReserved.PARAMS, true, true);
// Scorer parameter passed to the script. Internal use only.
- addVariable(null, Definition.DEF_TYPE, Reserved.SCORER, true, true);
+ addVariable(null, Definition.DEF_TYPE, ExecuteReserved.SCORER, true, true);
// Doc parameter passed to the script. TODO: Currently working as a Map, we can do better?
- addVariable(null, Definition.getType("Map"), Reserved.DOC, true, true);
+ addVariable(null, Definition.getType("Map"), ExecuteReserved.DOC, true, true);
// Aggregation _value parameter passed to the script.
- addVariable(null, Definition.DEF_TYPE, Reserved.VALUE, true, true);
+ addVariable(null, Definition.DEF_TYPE, ExecuteReserved.VALUE, true, true);
// Shortcut variables.
// Document's score as a read-only double.
- if (reserved.score) {
- addVariable(null, Definition.DOUBLE_TYPE, Reserved.SCORE, true, true);
+ if (reserved.usesScore()) {
+ addVariable(null, Definition.DOUBLE_TYPE, ExecuteReserved.SCORE, true, true);
}
// The ctx map set by executable scripts as a read-only map.
- if (reserved.ctx) {
- addVariable(null, Definition.getType("Map"), Reserved.CTX, true, true);
+ if (reserved.usesCtx()) {
+ addVariable(null, Definition.getType("Map"), ExecuteReserved.CTX, true, true);
}
// Loop counter to catch infinite loops. Internal use only.
- if (reserved.loop) {
- addVariable(null, Definition.INT_TYPE, Reserved.LOOP, true, true);
+ if (reserved.getMaxLoopCounter() > 0) {
+ addVariable(null, Definition.INT_TYPE, ExecuteReserved.LOOP, true, true);
}
}
+ public Locals(FunctionReserved reserved, Locals locals, Type rtnType, List parameters) {
+ this.reserved = reserved;
+ this.methods = locals.methods;
+ this.rtnType = rtnType;
+
+ incrementScope();
+
+ for (Parameter parameter : parameters) {
+ addVariable(parameter.location, parameter.type, parameter.name, false, false);
+ }
+
+ // Loop counter to catch infinite loops. Internal use only.
+ if (reserved.getMaxLoopCounter() > 0) {
+ addVariable(null, Definition.INT_TYPE, ExecuteReserved.LOOP, true, true);
+ }
+ }
+
+ public int getMaxLoopCounter() {
+ return reserved.getMaxLoopCounter();
+ }
+
+ public Method getMethod(MethodKey key) {
+ return methods.get(key);
+ }
+
+ public Type getReturnType() {
+ return rtnType;
+ }
+
public void incrementScope() {
scopes.push(0);
}
@@ -142,9 +241,9 @@ public final class Variables {
while (remove > 0) {
Variable variable = variables.pop();
- // TODO: is this working? the code reads backwards...
+ // This checks whether or not a variable is used when exiting a local scope.
if (variable.read) {
- throw variable.location.createError(new IllegalArgumentException("Variable [" + variable.name + "] never used."));
+ throw variable.location.createError(new IllegalArgumentException("Variable [" + variable.name + "] is never used."));
}
--remove;
@@ -162,26 +261,30 @@ public final class Variables {
}
}
- throw location.createError(new IllegalArgumentException("Variable [" + name + "] not defined."));
+ throw location.createError(new IllegalArgumentException("Variable [" + name + "] is not defined."));
}
- private boolean variableExists(String name) {
- return variables.contains(name);
+ public boolean isVariable(String name) {
+ Iterator itr = variables.iterator();
+
+ while (itr.hasNext()) {
+ Variable variable = itr.next();
+
+ if (variable.name.equals(name)) {
+ return true;
+ }
+ }
+
+ return false;
}
public Variable addVariable(Location location, Type type, String name, boolean readonly, boolean reserved) {
if (!reserved && this.reserved.isReserved(name)) {
- throw location.createError(new IllegalArgumentException("Variable name [" + name + "] is reserved."));
+ throw location.createError(new IllegalArgumentException("Variable [" + name + "] is reserved."));
}
- if (variableExists(name)) {
- throw new IllegalArgumentException("Variable name [" + name + "] already defined.");
- }
-
- try {
- Definition.getType(name);
- } catch (IllegalArgumentException exception) {
- // Do nothing.
+ if (isVariable(name)) {
+ throw location.createError(new IllegalArgumentException("Variable [" + name + "] is already defined."));
}
Variable previous = variables.peekFirst();
diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/MethodWriter.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/MethodWriter.java
index 7b7caec320e..923c2e3f1e8 100644
--- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/MethodWriter.java
+++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/MethodWriter.java
@@ -91,10 +91,10 @@ public final class MethodWriter extends GeneratorAdapter {
private final ClassWriter parent;
private final BitSet statements;
- private final Deque> stringConcatArgs = (INDY_STRING_CONCAT_BOOTSTRAP_HANDLE == null) ?
- null : new ArrayDeque<>();
+ private final Deque> stringConcatArgs =
+ (INDY_STRING_CONCAT_BOOTSTRAP_HANDLE == null) ? null : new ArrayDeque<>();
- MethodWriter(int access, Method method, ClassWriter cw, BitSet statements) {
+ public MethodWriter(int access, Method method, ClassWriter cw, BitSet statements) {
super(Opcodes.ASM5, cw.visitMethod(access, method.getName(), method.getDescriptor(), null, null),
access, method.getName(), method.getDescriptor());
@@ -105,7 +105,7 @@ public final class MethodWriter extends GeneratorAdapter {
/**
* @return A new {@link MethodWriter} with the specified access and signature.
*/
- MethodWriter newMethodWriter(int access, Method method) {
+ public MethodWriter newMethodWriter(int access, Method method) {
return new MethodWriter(access, method, parent, statements);
}
diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Writer.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Writer.java
deleted file mode 100644
index 4d4a778d558..00000000000
--- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Writer.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.painless;
-
-import org.elasticsearch.painless.Variables.Reserved;
-import org.elasticsearch.painless.Variables.Variable;
-import org.elasticsearch.painless.node.SSource;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.commons.GeneratorAdapter;
-
-import static org.elasticsearch.painless.WriterConstants.BASE_CLASS_TYPE;
-import static org.elasticsearch.painless.WriterConstants.CLASS_TYPE;
-import static org.elasticsearch.painless.WriterConstants.CONSTRUCTOR;
-import static org.elasticsearch.painless.WriterConstants.EXECUTE;
-import static org.elasticsearch.painless.WriterConstants.MAP_GET;
-import static org.elasticsearch.painless.WriterConstants.MAP_TYPE;
-
-import java.util.BitSet;
-
-/**
- * Runs the writing phase of compilation using the Painless AST.
- */
-final class Writer {
-
- static byte[] write(CompilerSettings settings, String name, String source, Variables variables, SSource root, BitSet expressions) {
- return new Writer(settings, name, source, variables, root, expressions).getBytes();
- }
-
- private final CompilerSettings settings;
- private final String scriptName;
- private final String source;
- private final Variables variables;
- private final SSource root;
-
- private final ClassWriter writer;
- private final MethodWriter adapter;
-
- private Writer(CompilerSettings settings, String name, String source, Variables variables, SSource root, BitSet expressions) {
- this.settings = settings;
- this.scriptName = name;
- this.source = source;
- this.variables = variables;
- this.root = root;
-
- writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
-
- writeBegin();
- writeConstructor();
-
- adapter = new MethodWriter(Opcodes.ACC_PUBLIC, EXECUTE, writer, expressions);
-
- writeExecute();
- writeEnd();
- }
-
- private void writeBegin() {
- final int version = Opcodes.V1_8;
- final int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_FINAL;
- final String base = BASE_CLASS_TYPE.getInternalName();
- final String name = CLASS_TYPE.getInternalName();
-
- // apply marker interface NeedsScore if we use the score!
- final String interfaces[] = variables.reserved.score ?
- new String[] { WriterConstants.NEEDS_SCORE_TYPE.getInternalName() } : null;
-
- writer.visit(version, access, name, null, base, interfaces);
- writer.visitSource(Location.computeSourceName(scriptName,source), null);
- }
-
- private void writeConstructor() {
- final GeneratorAdapter constructor = new GeneratorAdapter(Opcodes.ACC_PUBLIC, CONSTRUCTOR, null, null, writer);
- constructor.loadThis();
- constructor.loadArgs();
- constructor.invokeConstructor(org.objectweb.asm.Type.getType(Executable.class), CONSTRUCTOR);
- constructor.returnValue();
- constructor.endMethod();
- }
-
- private void writeExecute() {
- if (variables.reserved.score) {
- // if the _score value is used, we do this once:
- // final double _score = scorer.score();
- final Variable scorer = variables.getVariable(null, Reserved.SCORER);
- final Variable score = variables.getVariable(null, Reserved.SCORE);
-
- adapter.visitVarInsn(Opcodes.ALOAD, scorer.slot);
- adapter.invokeVirtual(WriterConstants.SCORER_TYPE, WriterConstants.SCORER_SCORE);
- adapter.visitInsn(Opcodes.F2D);
- adapter.visitVarInsn(Opcodes.DSTORE, score.slot);
- }
-
- if (variables.reserved.ctx) {
- // if the _ctx value is used, we do this once:
- // final Map ctx = input.get("ctx");
-
- final Variable input = variables.getVariable(null, Reserved.PARAMS);
- final Variable ctx = variables.getVariable(null, Reserved.CTX);
-
- adapter.visitVarInsn(Opcodes.ALOAD, input.slot);
- adapter.push(Reserved.CTX);
- adapter.invokeInterface(MAP_TYPE, MAP_GET);
- adapter.visitVarInsn(Opcodes.ASTORE, ctx.slot);
- }
-
- if (variables.reserved.loop) {
- // if there is infinite loop protection, we do this once:
- // int #loop = settings.getMaxLoopCounter()
-
- final Variable loop = variables.getVariable(null, Reserved.LOOP);
-
- adapter.push(settings.getMaxLoopCounter());
- adapter.visitVarInsn(Opcodes.ISTORE, loop.slot);
- }
-
- root.write(adapter);
- adapter.endMethod();
- }
-
- private void writeEnd() {
- writer.visitEnd();
- }
-
- private byte[] getBytes() {
- return writer.toByteArray();
- }
-}
diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterConstants.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterConstants.java
index 80082c4487b..03879a0a3a0 100644
--- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterConstants.java
+++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterConstants.java
@@ -107,15 +107,15 @@ public final class WriterConstants {
public final static Method DEF_LTE_CALL = getAsmMethod(boolean.class, "lte", Object.class, Object.class);
public final static Method DEF_GT_CALL = getAsmMethod(boolean.class, "gt" , Object.class, Object.class);
public final static Method DEF_GTE_CALL = getAsmMethod(boolean.class, "gte", Object.class, Object.class);
-
+
/** invokedynamic bootstrap for lambda expression/method references */
public final static MethodType LAMBDA_BOOTSTRAP_TYPE =
- MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
+ MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
MethodType.class, Object[].class);
public final static Handle LAMBDA_BOOTSTRAP_HANDLE =
new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(LambdaMetafactory.class),
"altMetafactory", LAMBDA_BOOTSTRAP_TYPE.toMethodDescriptorString());
-
+
/** dynamic invokedynamic bootstrap for indy string concats (Java 9+) */
public final static Handle INDY_STRING_CONCAT_BOOTSTRAP_HANDLE;
static {
@@ -152,7 +152,7 @@ public final class WriterConstants {
public final static Method CHECKEQUALS = getAsmMethod(boolean.class, "checkEquals", Object.class, Object.class);
- public static Method getAsmMethod(final Class> rtype, final String name, final Class>... ptypes) {
+ private static Method getAsmMethod(final Class> rtype, final String name, final Class>... ptypes) {
return new Method(name, MethodType.methodType(rtype, ptypes).toMethodDescriptorString());
}
diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/PainlessParser.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/PainlessParser.java
index 540773fbf70..acaf00a5765 100644
--- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/PainlessParser.java
+++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/PainlessParser.java
@@ -28,17 +28,17 @@ class PainlessParser extends Parser {
STRING=68, TRUE=69, FALSE=70, NULL=71, TYPE=72, ID=73, DOTINTEGER=74,
DOTID=75;
public static final int
- RULE_source = 0, RULE_statement = 1, RULE_trailer = 2, RULE_block = 3,
- RULE_empty = 4, RULE_initializer = 5, RULE_afterthought = 6, RULE_declaration = 7,
- RULE_decltype = 8, RULE_funcref = 9, RULE_declvar = 10, RULE_trap = 11,
- RULE_delimiter = 12, RULE_expression = 13, RULE_unary = 14, RULE_chain = 15,
- RULE_primary = 16, RULE_secondary = 17, RULE_dot = 18, RULE_brace = 19,
- RULE_arguments = 20, RULE_argument = 21;
+ RULE_source = 0, RULE_function = 1, RULE_parameters = 2, RULE_statement = 3,
+ RULE_trailer = 4, RULE_block = 5, RULE_empty = 6, RULE_initializer = 7,
+ RULE_afterthought = 8, RULE_declaration = 9, RULE_decltype = 10, RULE_funcref = 11,
+ RULE_declvar = 12, RULE_trap = 13, RULE_delimiter = 14, RULE_expression = 15,
+ RULE_unary = 16, RULE_chain = 17, RULE_primary = 18, RULE_secondary = 19,
+ RULE_dot = 20, RULE_brace = 21, RULE_arguments = 22, RULE_argument = 23;
public static final String[] ruleNames = {
- "source", "statement", "trailer", "block", "empty", "initializer", "afterthought",
- "declaration", "decltype", "funcref", "declvar", "trap", "delimiter",
- "expression", "unary", "chain", "primary", "secondary", "dot", "brace",
- "arguments", "argument"
+ "source", "function", "parameters", "statement", "trailer", "block", "empty",
+ "initializer", "afterthought", "declaration", "decltype", "funcref", "declvar",
+ "trap", "delimiter", "expression", "unary", "chain", "primary", "secondary",
+ "dot", "brace", "arguments", "argument"
};
private static final String[] _LITERAL_NAMES = {
@@ -113,6 +113,12 @@ class PainlessParser extends Parser {
}
public static class SourceContext extends ParserRuleContext {
public TerminalNode EOF() { return getToken(PainlessParser.EOF, 0); }
+ public List function() {
+ return getRuleContexts(FunctionContext.class);
+ }
+ public FunctionContext function(int i) {
+ return getRuleContext(FunctionContext.class,i);
+ }
public List statement() {
return getRuleContexts(StatementContext.class);
}
@@ -137,23 +143,39 @@ class PainlessParser extends Parser {
int _alt;
enterOuterAlt(_localctx, 1);
{
- setState(47);
+ setState(51);
_errHandler.sync(this);
_alt = getInterpreter().adaptivePredict(_input,0,_ctx);
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
if ( _alt==1 ) {
{
{
- setState(44);
+ setState(48);
+ function();
+ }
+ }
+ }
+ setState(53);
+ _errHandler.sync(this);
+ _alt = getInterpreter().adaptivePredict(_input,0,_ctx);
+ }
+ setState(57);
+ _errHandler.sync(this);
+ _alt = getInterpreter().adaptivePredict(_input,1,_ctx);
+ while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
+ if ( _alt==1 ) {
+ {
+ {
+ setState(54);
statement();
}
}
}
- setState(49);
+ setState(59);
_errHandler.sync(this);
- _alt = getInterpreter().adaptivePredict(_input,0,_ctx);
+ _alt = getInterpreter().adaptivePredict(_input,1,_ctx);
}
- setState(50);
+ setState(60);
match(EOF);
}
}
@@ -168,6 +190,136 @@ class PainlessParser extends Parser {
return _localctx;
}
+ public static class FunctionContext extends ParserRuleContext {
+ public DecltypeContext decltype() {
+ return getRuleContext(DecltypeContext.class,0);
+ }
+ public TerminalNode ID() { return getToken(PainlessParser.ID, 0); }
+ public ParametersContext parameters() {
+ return getRuleContext(ParametersContext.class,0);
+ }
+ public BlockContext block() {
+ return getRuleContext(BlockContext.class,0);
+ }
+ public FunctionContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_function; }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof PainlessParserVisitor ) return ((PainlessParserVisitor extends T>)visitor).visitFunction(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+
+ public final FunctionContext function() throws RecognitionException {
+ FunctionContext _localctx = new FunctionContext(_ctx, getState());
+ enterRule(_localctx, 2, RULE_function);
+ try {
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(62);
+ decltype();
+ setState(63);
+ match(ID);
+ setState(64);
+ parameters();
+ setState(65);
+ block();
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
+ public static class ParametersContext extends ParserRuleContext {
+ public TerminalNode LP() { return getToken(PainlessParser.LP, 0); }
+ public TerminalNode RP() { return getToken(PainlessParser.RP, 0); }
+ public List decltype() {
+ return getRuleContexts(DecltypeContext.class);
+ }
+ public DecltypeContext decltype(int i) {
+ return getRuleContext(DecltypeContext.class,i);
+ }
+ public List ID() { return getTokens(PainlessParser.ID); }
+ public TerminalNode ID(int i) {
+ return getToken(PainlessParser.ID, i);
+ }
+ public List COMMA() { return getTokens(PainlessParser.COMMA); }
+ public TerminalNode COMMA(int i) {
+ return getToken(PainlessParser.COMMA, i);
+ }
+ public ParametersContext(ParserRuleContext parent, int invokingState) {
+ super(parent, invokingState);
+ }
+ @Override public int getRuleIndex() { return RULE_parameters; }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof PainlessParserVisitor ) return ((PainlessParserVisitor extends T>)visitor).visitParameters(this);
+ else return visitor.visitChildren(this);
+ }
+ }
+
+ public final ParametersContext parameters() throws RecognitionException {
+ ParametersContext _localctx = new ParametersContext(_ctx, getState());
+ enterRule(_localctx, 4, RULE_parameters);
+ int _la;
+ try {
+ enterOuterAlt(_localctx, 1);
+ {
+ setState(67);
+ match(LP);
+ setState(79);
+ _la = _input.LA(1);
+ if (_la==TYPE) {
+ {
+ setState(68);
+ decltype();
+ setState(69);
+ match(ID);
+ setState(76);
+ _errHandler.sync(this);
+ _la = _input.LA(1);
+ while (_la==COMMA) {
+ {
+ {
+ setState(70);
+ match(COMMA);
+ setState(71);
+ decltype();
+ setState(72);
+ match(ID);
+ }
+ }
+ setState(78);
+ _errHandler.sync(this);
+ _la = _input.LA(1);
+ }
+ }
+ }
+
+ setState(81);
+ match(RP);
+ }
+ }
+ catch (RecognitionException re) {
+ _localctx.exception = re;
+ _errHandler.reportError(this, re);
+ _errHandler.recover(this, re);
+ }
+ finally {
+ exitRule();
+ }
+ return _localctx;
+ }
+
public static class StatementContext extends ParserRuleContext {
public StatementContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
@@ -396,38 +548,38 @@ class PainlessParser extends Parser {
public final StatementContext statement() throws RecognitionException {
StatementContext _localctx = new StatementContext(_ctx, getState());
- enterRule(_localctx, 2, RULE_statement);
+ enterRule(_localctx, 6, RULE_statement);
try {
int _alt;
- setState(130);
- switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) {
+ setState(161);
+ switch ( getInterpreter().adaptivePredict(_input,11,_ctx) ) {
case 1:
_localctx = new IfContext(_localctx);
enterOuterAlt(_localctx, 1);
{
- setState(52);
+ setState(83);
match(IF);
- setState(53);
+ setState(84);
match(LP);
- setState(54);
+ setState(85);
expression(0);
- setState(55);
+ setState(86);
match(RP);
- setState(56);
+ setState(87);
trailer();
- setState(60);
- switch ( getInterpreter().adaptivePredict(_input,1,_ctx) ) {
+ setState(91);
+ switch ( getInterpreter().adaptivePredict(_input,4,_ctx) ) {
case 1:
{
- setState(57);
+ setState(88);
match(ELSE);
- setState(58);
+ setState(89);
trailer();
}
break;
case 2:
{
- setState(59);
+ setState(90);
if (!( _input.LA(1) != ELSE )) throw new FailedPredicateException(this, " _input.LA(1) != ELSE ");
}
break;
@@ -438,25 +590,25 @@ class PainlessParser extends Parser {
_localctx = new WhileContext(_localctx);
enterOuterAlt(_localctx, 2);
{
- setState(62);
+ setState(93);
match(WHILE);
- setState(63);
+ setState(94);
match(LP);
- setState(64);
+ setState(95);
expression(0);
- setState(65);
+ setState(96);
match(RP);
- setState(68);
- switch ( getInterpreter().adaptivePredict(_input,2,_ctx) ) {
+ setState(99);
+ switch ( getInterpreter().adaptivePredict(_input,5,_ctx) ) {
case 1:
{
- setState(66);
+ setState(97);
trailer();
}
break;
case 2:
{
- setState(67);
+ setState(98);
empty();
}
break;
@@ -467,19 +619,19 @@ class PainlessParser extends Parser {
_localctx = new DoContext(_localctx);
enterOuterAlt(_localctx, 3);
{
- setState(70);
+ setState(101);
match(DO);
- setState(71);
+ setState(102);
block();
- setState(72);
+ setState(103);
match(WHILE);
- setState(73);
+ setState(104);
match(LP);
- setState(74);
+ setState(105);
expression(0);
- setState(75);
+ setState(106);
match(RP);
- setState(76);
+ setState(107);
delimiter();
}
break;
@@ -487,54 +639,54 @@ class PainlessParser extends Parser {
_localctx = new ForContext(_localctx);
enterOuterAlt(_localctx, 4);
{
- setState(78);
+ setState(109);
match(FOR);
- setState(79);
+ setState(110);
match(LP);
- setState(81);
- switch ( getInterpreter().adaptivePredict(_input,3,_ctx) ) {
+ setState(112);
+ switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) {
case 1:
{
- setState(80);
+ setState(111);
initializer();
}
break;
}
- setState(83);
+ setState(114);
match(SEMICOLON);
- setState(85);
- switch ( getInterpreter().adaptivePredict(_input,4,_ctx) ) {
+ setState(116);
+ switch ( getInterpreter().adaptivePredict(_input,7,_ctx) ) {
case 1:
{
- setState(84);
+ setState(115);
expression(0);
}
break;
}
- setState(87);
+ setState(118);
match(SEMICOLON);
- setState(89);
- switch ( getInterpreter().adaptivePredict(_input,5,_ctx) ) {
+ setState(120);
+ switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) {
case 1:
{
- setState(88);
+ setState(119);
afterthought();
}
break;
}
- setState(91);
+ setState(122);
match(RP);
- setState(94);
- switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) {
+ setState(125);
+ switch ( getInterpreter().adaptivePredict(_input,9,_ctx) ) {
case 1:
{
- setState(92);
+ setState(123);
trailer();
}
break;
case 2:
{
- setState(93);
+ setState(124);
empty();
}
break;
@@ -545,21 +697,21 @@ class PainlessParser extends Parser {
_localctx = new EachContext(_localctx);
enterOuterAlt(_localctx, 5);
{
- setState(96);
+ setState(127);
match(FOR);
- setState(97);
+ setState(128);
match(LP);
- setState(98);
+ setState(129);
decltype();
- setState(99);
+ setState(130);
match(ID);
- setState(100);
+ setState(131);
match(COLON);
- setState(101);
+ setState(132);
expression(0);
- setState(102);
+ setState(133);
match(RP);
- setState(103);
+ setState(134);
trailer();
}
break;
@@ -567,9 +719,9 @@ class PainlessParser extends Parser {
_localctx = new DeclContext(_localctx);
enterOuterAlt(_localctx, 6);
{
- setState(105);
+ setState(136);
declaration();
- setState(106);
+ setState(137);
delimiter();
}
break;
@@ -577,9 +729,9 @@ class PainlessParser extends Parser {
_localctx = new ContinueContext(_localctx);
enterOuterAlt(_localctx, 7);
{
- setState(108);
+ setState(139);
match(CONTINUE);
- setState(109);
+ setState(140);
delimiter();
}
break;
@@ -587,9 +739,9 @@ class PainlessParser extends Parser {
_localctx = new BreakContext(_localctx);
enterOuterAlt(_localctx, 8);
{
- setState(110);
+ setState(141);
match(BREAK);
- setState(111);
+ setState(142);
delimiter();
}
break;
@@ -597,11 +749,11 @@ class PainlessParser extends Parser {
_localctx = new ReturnContext(_localctx);
enterOuterAlt(_localctx, 9);
{
- setState(112);
+ setState(143);
match(RETURN);
- setState(113);
+ setState(144);
expression(0);
- setState(114);
+ setState(145);
delimiter();
}
break;
@@ -609,11 +761,11 @@ class PainlessParser extends Parser {
_localctx = new TryContext(_localctx);
enterOuterAlt(_localctx, 10);
{
- setState(116);
+ setState(147);
match(TRY);
- setState(117);
+ setState(148);
block();
- setState(119);
+ setState(150);
_errHandler.sync(this);
_alt = 1;
do {
@@ -621,7 +773,7 @@ class PainlessParser extends Parser {
case 1:
{
{
- setState(118);
+ setState(149);
trap();
}
}
@@ -629,9 +781,9 @@ class PainlessParser extends Parser {
default:
throw new NoViableAltException(this);
}
- setState(121);
+ setState(152);
_errHandler.sync(this);
- _alt = getInterpreter().adaptivePredict(_input,7,_ctx);
+ _alt = getInterpreter().adaptivePredict(_input,10,_ctx);
} while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER );
}
break;
@@ -639,11 +791,11 @@ class PainlessParser extends Parser {
_localctx = new ThrowContext(_localctx);
enterOuterAlt(_localctx, 11);
{
- setState(123);
+ setState(154);
match(THROW);
- setState(124);
+ setState(155);
expression(0);
- setState(125);
+ setState(156);
delimiter();
}
break;
@@ -651,9 +803,9 @@ class PainlessParser extends Parser {
_localctx = new ExprContext(_localctx);
enterOuterAlt(_localctx, 12);
{
- setState(127);
+ setState(158);
expression(0);
- setState(128);
+ setState(159);
delimiter();
}
break;
@@ -690,21 +842,21 @@ class PainlessParser extends Parser {
public final TrailerContext trailer() throws RecognitionException {
TrailerContext _localctx = new TrailerContext(_ctx, getState());
- enterRule(_localctx, 4, RULE_trailer);
+ enterRule(_localctx, 8, RULE_trailer);
try {
- setState(134);
- switch ( getInterpreter().adaptivePredict(_input,9,_ctx) ) {
+ setState(165);
+ switch ( getInterpreter().adaptivePredict(_input,12,_ctx) ) {
case 1:
enterOuterAlt(_localctx, 1);
{
- setState(132);
+ setState(163);
block();
}
break;
case 2:
enterOuterAlt(_localctx, 2);
{
- setState(133);
+ setState(164);
statement();
}
break;
@@ -743,30 +895,30 @@ class PainlessParser extends Parser {
public final BlockContext block() throws RecognitionException {
BlockContext _localctx = new BlockContext(_ctx, getState());
- enterRule(_localctx, 6, RULE_block);
+ enterRule(_localctx, 10, RULE_block);
try {
int _alt;
enterOuterAlt(_localctx, 1);
{
- setState(136);
+ setState(167);
match(LBRACK);
- setState(140);
+ setState(171);
_errHandler.sync(this);
- _alt = getInterpreter().adaptivePredict(_input,10,_ctx);
+ _alt = getInterpreter().adaptivePredict(_input,13,_ctx);
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
if ( _alt==1 ) {
{
{
- setState(137);
+ setState(168);
statement();
}
}
}
- setState(142);
+ setState(173);
_errHandler.sync(this);
- _alt = getInterpreter().adaptivePredict(_input,10,_ctx);
+ _alt = getInterpreter().adaptivePredict(_input,13,_ctx);
}
- setState(143);
+ setState(174);
match(RBRACK);
}
}
@@ -796,11 +948,11 @@ class PainlessParser extends Parser {
public final EmptyContext empty() throws RecognitionException {
EmptyContext _localctx = new EmptyContext(_ctx, getState());
- enterRule(_localctx, 8, RULE_empty);
+ enterRule(_localctx, 12, RULE_empty);
try {
enterOuterAlt(_localctx, 1);
{
- setState(145);
+ setState(176);
match(SEMICOLON);
}
}
@@ -835,21 +987,21 @@ class PainlessParser extends Parser {
public final InitializerContext initializer() throws RecognitionException {
InitializerContext _localctx = new InitializerContext(_ctx, getState());
- enterRule(_localctx, 10, RULE_initializer);
+ enterRule(_localctx, 14, RULE_initializer);
try {
- setState(149);
- switch ( getInterpreter().adaptivePredict(_input,11,_ctx) ) {
+ setState(180);
+ switch ( getInterpreter().adaptivePredict(_input,14,_ctx) ) {
case 1:
enterOuterAlt(_localctx, 1);
{
- setState(147);
+ setState(178);
declaration();
}
break;
case 2:
enterOuterAlt(_localctx, 2);
{
- setState(148);
+ setState(179);
expression(0);
}
break;
@@ -883,11 +1035,11 @@ class PainlessParser extends Parser {
public final AfterthoughtContext afterthought() throws RecognitionException {
AfterthoughtContext _localctx = new AfterthoughtContext(_ctx, getState());
- enterRule(_localctx, 12, RULE_afterthought);
+ enterRule(_localctx, 16, RULE_afterthought);
try {
enterOuterAlt(_localctx, 1);
{
- setState(151);
+ setState(182);
expression(0);
}
}
@@ -929,28 +1081,28 @@ class PainlessParser extends Parser {
public final DeclarationContext declaration() throws RecognitionException {
DeclarationContext _localctx = new DeclarationContext(_ctx, getState());
- enterRule(_localctx, 14, RULE_declaration);
+ enterRule(_localctx, 18, RULE_declaration);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
- setState(153);
+ setState(184);
decltype();
- setState(154);
+ setState(185);
declvar();
- setState(159);
+ setState(190);
_errHandler.sync(this);
_la = _input.LA(1);
while (_la==COMMA) {
{
{
- setState(155);
+ setState(186);
match(COMMA);
- setState(156);
+ setState(187);
declvar();
}
}
- setState(161);
+ setState(192);
_errHandler.sync(this);
_la = _input.LA(1);
}
@@ -990,26 +1142,26 @@ class PainlessParser extends Parser {
public final DecltypeContext decltype() throws RecognitionException {
DecltypeContext _localctx = new DecltypeContext(_ctx, getState());
- enterRule(_localctx, 16, RULE_decltype);
+ enterRule(_localctx, 20, RULE_decltype);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
- setState(162);
+ setState(193);
match(TYPE);
- setState(167);
+ setState(198);
_errHandler.sync(this);
_la = _input.LA(1);
while (_la==LBRACE) {
{
{
- setState(163);
+ setState(194);
match(LBRACE);
- setState(164);
+ setState(195);
match(RBRACE);
}
}
- setState(169);
+ setState(200);
_errHandler.sync(this);
_la = _input.LA(1);
}
@@ -1044,16 +1196,16 @@ class PainlessParser extends Parser {
public final FuncrefContext funcref() throws RecognitionException {
FuncrefContext _localctx = new FuncrefContext(_ctx, getState());
- enterRule(_localctx, 18, RULE_funcref);
+ enterRule(_localctx, 22, RULE_funcref);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
- setState(170);
+ setState(201);
match(TYPE);
- setState(171);
+ setState(202);
match(REF);
- setState(172);
+ setState(203);
_la = _input.LA(1);
if ( !(_la==NEW || _la==ID) ) {
_errHandler.recoverInline(this);
@@ -1092,20 +1244,20 @@ class PainlessParser extends Parser {
public final DeclvarContext declvar() throws RecognitionException {
DeclvarContext _localctx = new DeclvarContext(_ctx, getState());
- enterRule(_localctx, 20, RULE_declvar);
+ enterRule(_localctx, 24, RULE_declvar);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
- setState(174);
+ setState(205);
match(ID);
- setState(177);
+ setState(208);
_la = _input.LA(1);
if (_la==ASSIGN) {
{
- setState(175);
+ setState(206);
match(ASSIGN);
- setState(176);
+ setState(207);
expression(0);
}
}
@@ -1145,21 +1297,21 @@ class PainlessParser extends Parser {
public final TrapContext trap() throws RecognitionException {
TrapContext _localctx = new TrapContext(_ctx, getState());
- enterRule(_localctx, 22, RULE_trap);
+ enterRule(_localctx, 26, RULE_trap);
try {
enterOuterAlt(_localctx, 1);
{
- setState(179);
+ setState(210);
match(CATCH);
- setState(180);
+ setState(211);
match(LP);
- setState(181);
+ setState(212);
match(TYPE);
- setState(182);
+ setState(213);
match(ID);
- setState(183);
+ setState(214);
match(RP);
- setState(184);
+ setState(215);
block();
}
}
@@ -1190,12 +1342,12 @@ class PainlessParser extends Parser {
public final DelimiterContext delimiter() throws RecognitionException {
DelimiterContext _localctx = new DelimiterContext(_ctx, getState());
- enterRule(_localctx, 24, RULE_delimiter);
+ enterRule(_localctx, 28, RULE_delimiter);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
- setState(186);
+ setState(217);
_la = _input.LA(1);
if ( !(_la==EOF || _la==SEMICOLON) ) {
_errHandler.recoverInline(this);
@@ -1357,31 +1509,31 @@ class PainlessParser extends Parser {
int _parentState = getState();
ExpressionContext _localctx = new ExpressionContext(_ctx, _parentState);
ExpressionContext _prevctx = _localctx;
- int _startState = 26;
- enterRecursionRule(_localctx, 26, RULE_expression, _p);
+ int _startState = 30;
+ enterRecursionRule(_localctx, 30, RULE_expression, _p);
int _la;
try {
int _alt;
enterOuterAlt(_localctx, 1);
{
- setState(197);
- switch ( getInterpreter().adaptivePredict(_input,15,_ctx) ) {
+ setState(228);
+ switch ( getInterpreter().adaptivePredict(_input,18,_ctx) ) {
case 1:
{
_localctx = new AssignmentContext(_localctx);
_ctx = _localctx;
_prevctx = _localctx;
- setState(189);
+ setState(220);
chain(true);
- setState(190);
+ setState(221);
_la = _input.LA(1);
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ASSIGN) | (1L << AADD) | (1L << ASUB) | (1L << AMUL) | (1L << ADIV) | (1L << AREM) | (1L << AAND) | (1L << AXOR) | (1L << AOR) | (1L << ALSH) | (1L << ARSH) | (1L << AUSH))) != 0)) ) {
_errHandler.recoverInline(this);
} else {
consume();
}
- setState(191);
+ setState(222);
expression(1);
((AssignmentContext)_localctx).s = false;
}
@@ -1391,37 +1543,37 @@ class PainlessParser extends Parser {
_localctx = new SingleContext(_localctx);
_ctx = _localctx;
_prevctx = _localctx;
- setState(194);
+ setState(225);
((SingleContext)_localctx).u = unary(false);
((SingleContext)_localctx).s = ((SingleContext)_localctx).u.s;
}
break;
}
_ctx.stop = _input.LT(-1);
- setState(258);
+ setState(289);
_errHandler.sync(this);
- _alt = getInterpreter().adaptivePredict(_input,17,_ctx);
+ _alt = getInterpreter().adaptivePredict(_input,20,_ctx);
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
if ( _alt==1 ) {
if ( _parseListeners!=null ) triggerExitRuleEvent();
_prevctx = _localctx;
{
- setState(256);
- switch ( getInterpreter().adaptivePredict(_input,16,_ctx) ) {
+ setState(287);
+ switch ( getInterpreter().adaptivePredict(_input,19,_ctx) ) {
case 1:
{
_localctx = new BinaryContext(new ExpressionContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_expression);
- setState(199);
+ setState(230);
if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)");
- setState(200);
+ setState(231);
_la = _input.LA(1);
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << MUL) | (1L << DIV) | (1L << REM))) != 0)) ) {
_errHandler.recoverInline(this);
} else {
consume();
}
- setState(201);
+ setState(232);
expression(13);
((BinaryContext)_localctx).s = false;
}
@@ -1430,16 +1582,16 @@ class PainlessParser extends Parser {
{
_localctx = new BinaryContext(new ExpressionContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_expression);
- setState(204);
+ setState(235);
if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)");
- setState(205);
+ setState(236);
_la = _input.LA(1);
if ( !(_la==ADD || _la==SUB) ) {
_errHandler.recoverInline(this);
} else {
consume();
}
- setState(206);
+ setState(237);
expression(12);
((BinaryContext)_localctx).s = false;
}
@@ -1448,16 +1600,16 @@ class PainlessParser extends Parser {
{
_localctx = new BinaryContext(new ExpressionContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_expression);
- setState(209);
+ setState(240);
if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)");
- setState(210);
+ setState(241);
_la = _input.LA(1);
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << LSH) | (1L << RSH) | (1L << USH))) != 0)) ) {
_errHandler.recoverInline(this);
} else {
consume();
}
- setState(211);
+ setState(242);
expression(11);
((BinaryContext)_localctx).s = false;
}
@@ -1466,16 +1618,16 @@ class PainlessParser extends Parser {
{
_localctx = new CompContext(new ExpressionContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_expression);
- setState(214);
+ setState(245);
if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
- setState(215);
+ setState(246);
_la = _input.LA(1);
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << LT) | (1L << LTE) | (1L << GT) | (1L << GTE))) != 0)) ) {
_errHandler.recoverInline(this);
} else {
consume();
}
- setState(216);
+ setState(247);
expression(10);
((CompContext)_localctx).s = false;
}
@@ -1484,16 +1636,16 @@ class PainlessParser extends Parser {
{
_localctx = new CompContext(new ExpressionContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_expression);
- setState(219);
+ setState(250);
if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)");
- setState(220);
+ setState(251);
_la = _input.LA(1);
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << EQ) | (1L << EQR) | (1L << NE) | (1L << NER))) != 0)) ) {
_errHandler.recoverInline(this);
} else {
consume();
}
- setState(221);
+ setState(252);
expression(9);
((CompContext)_localctx).s = false;
}
@@ -1502,11 +1654,11 @@ class PainlessParser extends Parser {
{
_localctx = new BinaryContext(new ExpressionContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_expression);
- setState(224);
+ setState(255);
if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
- setState(225);
+ setState(256);
match(BWAND);
- setState(226);
+ setState(257);
expression(8);
((BinaryContext)_localctx).s = false;
}
@@ -1515,11 +1667,11 @@ class PainlessParser extends Parser {
{
_localctx = new BinaryContext(new ExpressionContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_expression);
- setState(229);
+ setState(260);
if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)");
- setState(230);
+ setState(261);
match(XOR);
- setState(231);
+ setState(262);
expression(7);
((BinaryContext)_localctx).s = false;
}
@@ -1528,11 +1680,11 @@ class PainlessParser extends Parser {
{
_localctx = new BinaryContext(new ExpressionContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_expression);
- setState(234);
+ setState(265);
if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)");
- setState(235);
+ setState(266);
match(BWOR);
- setState(236);
+ setState(267);
expression(6);
((BinaryContext)_localctx).s = false;
}
@@ -1541,11 +1693,11 @@ class PainlessParser extends Parser {
{
_localctx = new BoolContext(new ExpressionContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_expression);
- setState(239);
+ setState(270);
if (!(precpred(_ctx, 4))) throw new FailedPredicateException(this, "precpred(_ctx, 4)");
- setState(240);
+ setState(271);
match(BOOLAND);
- setState(241);
+ setState(272);
expression(5);
((BoolContext)_localctx).s = false;
}
@@ -1554,11 +1706,11 @@ class PainlessParser extends Parser {
{
_localctx = new BoolContext(new ExpressionContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_expression);
- setState(244);
+ setState(275);
if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)");
- setState(245);
+ setState(276);
match(BOOLOR);
- setState(246);
+ setState(277);
expression(4);
((BoolContext)_localctx).s = false;
}
@@ -1567,15 +1719,15 @@ class PainlessParser extends Parser {
{
_localctx = new ConditionalContext(new ExpressionContext(_parentctx, _parentState));
pushNewRecursionContext(_localctx, _startState, RULE_expression);
- setState(249);
+ setState(280);
if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)");
- setState(250);
+ setState(281);
match(COND);
- setState(251);
+ setState(282);
((ConditionalContext)_localctx).e0 = expression(0);
- setState(252);
+ setState(283);
match(COLON);
- setState(253);
+ setState(284);
((ConditionalContext)_localctx).e1 = expression(2);
((ConditionalContext)_localctx).s = ((ConditionalContext)_localctx).e0.s && ((ConditionalContext)_localctx).e1.s;
}
@@ -1583,9 +1735,9 @@ class PainlessParser extends Parser {
}
}
}
- setState(260);
+ setState(291);
_errHandler.sync(this);
- _alt = getInterpreter().adaptivePredict(_input,17,_ctx);
+ _alt = getInterpreter().adaptivePredict(_input,20,_ctx);
}
}
}
@@ -1727,25 +1879,25 @@ class PainlessParser extends Parser {
public final UnaryContext unary(boolean c) throws RecognitionException {
UnaryContext _localctx = new UnaryContext(_ctx, getState(), c);
- enterRule(_localctx, 28, RULE_unary);
+ enterRule(_localctx, 32, RULE_unary);
int _la;
try {
- setState(290);
- switch ( getInterpreter().adaptivePredict(_input,18,_ctx) ) {
+ setState(321);
+ switch ( getInterpreter().adaptivePredict(_input,21,_ctx) ) {
case 1:
_localctx = new PreContext(_localctx);
enterOuterAlt(_localctx, 1);
{
- setState(261);
+ setState(292);
if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
- setState(262);
+ setState(293);
_la = _input.LA(1);
if ( !(_la==INCR || _la==DECR) ) {
_errHandler.recoverInline(this);
} else {
consume();
}
- setState(263);
+ setState(294);
chain(true);
}
break;
@@ -1753,11 +1905,11 @@ class PainlessParser extends Parser {
_localctx = new PostContext(_localctx);
enterOuterAlt(_localctx, 2);
{
- setState(264);
+ setState(295);
if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
- setState(265);
+ setState(296);
chain(true);
- setState(266);
+ setState(297);
_la = _input.LA(1);
if ( !(_la==INCR || _la==DECR) ) {
_errHandler.recoverInline(this);
@@ -1770,9 +1922,9 @@ class PainlessParser extends Parser {
_localctx = new ReadContext(_localctx);
enterOuterAlt(_localctx, 3);
{
- setState(268);
+ setState(299);
if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
- setState(269);
+ setState(300);
chain(false);
}
break;
@@ -1780,9 +1932,9 @@ class PainlessParser extends Parser {
_localctx = new NumericContext(_localctx);
enterOuterAlt(_localctx, 4);
{
- setState(270);
+ setState(301);
if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
- setState(271);
+ setState(302);
_la = _input.LA(1);
if ( !(((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (OCTAL - 64)) | (1L << (HEX - 64)) | (1L << (INTEGER - 64)) | (1L << (DECIMAL - 64)))) != 0)) ) {
_errHandler.recoverInline(this);
@@ -1796,9 +1948,9 @@ class PainlessParser extends Parser {
_localctx = new TrueContext(_localctx);
enterOuterAlt(_localctx, 5);
{
- setState(273);
+ setState(304);
if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
- setState(274);
+ setState(305);
match(TRUE);
((TrueContext)_localctx).s = false;
}
@@ -1807,9 +1959,9 @@ class PainlessParser extends Parser {
_localctx = new FalseContext(_localctx);
enterOuterAlt(_localctx, 6);
{
- setState(276);
+ setState(307);
if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
- setState(277);
+ setState(308);
match(FALSE);
((FalseContext)_localctx).s = false;
}
@@ -1818,9 +1970,9 @@ class PainlessParser extends Parser {
_localctx = new NullContext(_localctx);
enterOuterAlt(_localctx, 7);
{
- setState(279);
+ setState(310);
if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
- setState(280);
+ setState(311);
match(NULL);
((NullContext)_localctx).s = false;
}
@@ -1829,16 +1981,16 @@ class PainlessParser extends Parser {
_localctx = new OperatorContext(_localctx);
enterOuterAlt(_localctx, 8);
{
- setState(282);
+ setState(313);
if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
- setState(283);
+ setState(314);
_la = _input.LA(1);
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << BOOLNOT) | (1L << BWNOT) | (1L << ADD) | (1L << SUB))) != 0)) ) {
_errHandler.recoverInline(this);
} else {
consume();
}
- setState(284);
+ setState(315);
unary(false);
}
break;
@@ -1846,13 +1998,13 @@ class PainlessParser extends Parser {
_localctx = new CastContext(_localctx);
enterOuterAlt(_localctx, 9);
{
- setState(285);
+ setState(316);
match(LP);
- setState(286);
+ setState(317);
decltype();
- setState(287);
+ setState(318);
match(RP);
- setState(288);
+ setState(319);
unary(_localctx.c);
}
break;
@@ -1958,32 +2110,32 @@ class PainlessParser extends Parser {
public final ChainContext chain(boolean c) throws RecognitionException {
ChainContext _localctx = new ChainContext(_ctx, getState(), c);
- enterRule(_localctx, 30, RULE_chain);
+ enterRule(_localctx, 34, RULE_chain);
try {
int _alt;
- setState(326);
- switch ( getInterpreter().adaptivePredict(_input,24,_ctx) ) {
+ setState(357);
+ switch ( getInterpreter().adaptivePredict(_input,27,_ctx) ) {
case 1:
_localctx = new DynamicContext(_localctx);
enterOuterAlt(_localctx, 1);
{
- setState(292);
+ setState(323);
((DynamicContext)_localctx).p = primary(_localctx.c);
- setState(296);
+ setState(327);
_errHandler.sync(this);
- _alt = getInterpreter().adaptivePredict(_input,19,_ctx);
+ _alt = getInterpreter().adaptivePredict(_input,22,_ctx);
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
if ( _alt==1 ) {
{
{
- setState(293);
+ setState(324);
secondary(((DynamicContext)_localctx).p.s);
}
}
}
- setState(298);
+ setState(329);
_errHandler.sync(this);
- _alt = getInterpreter().adaptivePredict(_input,19,_ctx);
+ _alt = getInterpreter().adaptivePredict(_input,22,_ctx);
}
}
break;
@@ -1991,25 +2143,25 @@ class PainlessParser extends Parser {
_localctx = new StaticContext(_localctx);
enterOuterAlt(_localctx, 2);
{
- setState(299);
+ setState(330);
decltype();
- setState(300);
+ setState(331);
dot();
- setState(304);
+ setState(335);
_errHandler.sync(this);
- _alt = getInterpreter().adaptivePredict(_input,20,_ctx);
+ _alt = getInterpreter().adaptivePredict(_input,23,_ctx);
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
if ( _alt==1 ) {
{
{
- setState(301);
+ setState(332);
secondary(true);
}
}
}
- setState(306);
+ setState(337);
_errHandler.sync(this);
- _alt = getInterpreter().adaptivePredict(_input,20,_ctx);
+ _alt = getInterpreter().adaptivePredict(_input,23,_ctx);
}
}
break;
@@ -2017,11 +2169,11 @@ class PainlessParser extends Parser {
_localctx = new NewarrayContext(_localctx);
enterOuterAlt(_localctx, 3);
{
- setState(307);
+ setState(338);
match(NEW);
- setState(308);
+ setState(339);
match(TYPE);
- setState(313);
+ setState(344);
_errHandler.sync(this);
_alt = 1;
do {
@@ -2029,11 +2181,11 @@ class PainlessParser extends Parser {
case 1:
{
{
- setState(309);
+ setState(340);
match(LBRACE);
- setState(310);
+ setState(341);
expression(0);
- setState(311);
+ setState(342);
match(RBRACE);
}
}
@@ -2041,31 +2193,31 @@ class PainlessParser extends Parser {
default:
throw new NoViableAltException(this);
}
- setState(315);
+ setState(346);
_errHandler.sync(this);
- _alt = getInterpreter().adaptivePredict(_input,21,_ctx);
+ _alt = getInterpreter().adaptivePredict(_input,24,_ctx);
} while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER );
- setState(324);
- switch ( getInterpreter().adaptivePredict(_input,23,_ctx) ) {
+ setState(355);
+ switch ( getInterpreter().adaptivePredict(_input,26,_ctx) ) {
case 1:
{
- setState(317);
+ setState(348);
dot();
- setState(321);
+ setState(352);
_errHandler.sync(this);
- _alt = getInterpreter().adaptivePredict(_input,22,_ctx);
+ _alt = getInterpreter().adaptivePredict(_input,25,_ctx);
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
if ( _alt==1 ) {
{
{
- setState(318);
+ setState(349);
secondary(true);
}
}
}
- setState(323);
+ setState(354);
_errHandler.sync(this);
- _alt = getInterpreter().adaptivePredict(_input,22,_ctx);
+ _alt = getInterpreter().adaptivePredict(_input,25,_ctx);
}
}
break;
@@ -2111,6 +2263,18 @@ class PainlessParser extends Parser {
else return visitor.visitChildren(this);
}
}
+ public static class CalllocalContext extends PrimaryContext {
+ public TerminalNode ID() { return getToken(PainlessParser.ID, 0); }
+ public ArgumentsContext arguments() {
+ return getRuleContext(ArgumentsContext.class,0);
+ }
+ public CalllocalContext(PrimaryContext ctx) { copyFrom(ctx); }
+ @Override
+ public T accept(ParseTreeVisitor extends T> visitor) {
+ if ( visitor instanceof PainlessParserVisitor ) return ((PainlessParserVisitor extends T>)visitor).visitCalllocal(this);
+ else return visitor.visitChildren(this);
+ }
+ }
public static class VariableContext extends PrimaryContext {
public TerminalNode ID() { return getToken(PainlessParser.ID, 0); }
public VariableContext(PrimaryContext ctx) { copyFrom(ctx); }
@@ -2163,21 +2327,21 @@ class PainlessParser extends Parser {
public final PrimaryContext primary(boolean c) throws RecognitionException {
PrimaryContext _localctx = new PrimaryContext(_ctx, getState(), c);
- enterRule(_localctx, 32, RULE_primary);
+ enterRule(_localctx, 36, RULE_primary);
try {
- setState(344);
- switch ( getInterpreter().adaptivePredict(_input,25,_ctx) ) {
+ setState(377);
+ switch ( getInterpreter().adaptivePredict(_input,28,_ctx) ) {
case 1:
_localctx = new ExprprecContext(_localctx);
enterOuterAlt(_localctx, 1);
{
- setState(328);
+ setState(359);
if (!( !_localctx.c )) throw new FailedPredicateException(this, " !$c ");
- setState(329);
+ setState(360);
match(LP);
- setState(330);
+ setState(361);
((ExprprecContext)_localctx).e = expression(0);
- setState(331);
+ setState(362);
match(RP);
((ExprprecContext)_localctx).s = ((ExprprecContext)_localctx).e.s;
}
@@ -2186,13 +2350,13 @@ class PainlessParser extends Parser {
_localctx = new ChainprecContext(_localctx);
enterOuterAlt(_localctx, 2);
{
- setState(334);
+ setState(365);
if (!( _localctx.c )) throw new FailedPredicateException(this, " $c ");
- setState(335);
+ setState(366);
match(LP);
- setState(336);
+ setState(367);
unary(true);
- setState(337);
+ setState(368);
match(RP);
}
break;
@@ -2200,7 +2364,7 @@ class PainlessParser extends Parser {
_localctx = new StringContext(_localctx);
enterOuterAlt(_localctx, 3);
{
- setState(339);
+ setState(370);
match(STRING);
}
break;
@@ -2208,19 +2372,29 @@ class PainlessParser extends Parser {
_localctx = new VariableContext(_localctx);
enterOuterAlt(_localctx, 4);
{
- setState(340);
+ setState(371);
match(ID);
}
break;
case 5:
- _localctx = new NewobjectContext(_localctx);
+ _localctx = new CalllocalContext(_localctx);
enterOuterAlt(_localctx, 5);
{
- setState(341);
+ setState(372);
+ match(ID);
+ setState(373);
+ arguments();
+ }
+ break;
+ case 6:
+ _localctx = new NewobjectContext(_localctx);
+ enterOuterAlt(_localctx, 6);
+ {
+ setState(374);
match(NEW);
- setState(342);
+ setState(375);
match(TYPE);
- setState(343);
+ setState(376);
arguments();
}
break;
@@ -2260,25 +2434,25 @@ class PainlessParser extends Parser {
public final SecondaryContext secondary(boolean s) throws RecognitionException {
SecondaryContext _localctx = new SecondaryContext(_ctx, getState(), s);
- enterRule(_localctx, 34, RULE_secondary);
+ enterRule(_localctx, 38, RULE_secondary);
try {
- setState(350);
- switch ( getInterpreter().adaptivePredict(_input,26,_ctx) ) {
+ setState(383);
+ switch ( getInterpreter().adaptivePredict(_input,29,_ctx) ) {
case 1:
enterOuterAlt(_localctx, 1);
{
- setState(346);
+ setState(379);
if (!( _localctx.s )) throw new FailedPredicateException(this, " $s ");
- setState(347);
+ setState(380);
dot();
}
break;
case 2:
enterOuterAlt(_localctx, 2);
{
- setState(348);
+ setState(381);
if (!( _localctx.s )) throw new FailedPredicateException(this, " $s ");
- setState(349);
+ setState(382);
brace();
}
break;
@@ -2333,20 +2507,20 @@ class PainlessParser extends Parser {
public final DotContext dot() throws RecognitionException {
DotContext _localctx = new DotContext(_ctx, getState());
- enterRule(_localctx, 36, RULE_dot);
+ enterRule(_localctx, 40, RULE_dot);
int _la;
try {
- setState(357);
- switch ( getInterpreter().adaptivePredict(_input,27,_ctx) ) {
+ setState(390);
+ switch ( getInterpreter().adaptivePredict(_input,30,_ctx) ) {
case 1:
_localctx = new CallinvokeContext(_localctx);
enterOuterAlt(_localctx, 1);
{
- setState(352);
+ setState(385);
match(DOT);
- setState(353);
+ setState(386);
match(DOTID);
- setState(354);
+ setState(387);
arguments();
}
break;
@@ -2354,9 +2528,9 @@ class PainlessParser extends Parser {
_localctx = new FieldaccessContext(_localctx);
enterOuterAlt(_localctx, 2);
{
- setState(355);
+ setState(388);
match(DOT);
- setState(356);
+ setState(389);
_la = _input.LA(1);
if ( !(_la==DOTINTEGER || _la==DOTID) ) {
_errHandler.recoverInline(this);
@@ -2405,16 +2579,16 @@ class PainlessParser extends Parser {
public final BraceContext brace() throws RecognitionException {
BraceContext _localctx = new BraceContext(_ctx, getState());
- enterRule(_localctx, 38, RULE_brace);
+ enterRule(_localctx, 42, RULE_brace);
try {
_localctx = new BraceaccessContext(_localctx);
enterOuterAlt(_localctx, 1);
{
- setState(359);
+ setState(392);
match(LBRACE);
- setState(360);
+ setState(393);
expression(0);
- setState(361);
+ setState(394);
match(RBRACE);
}
}
@@ -2455,40 +2629,40 @@ class PainlessParser extends Parser {
public final ArgumentsContext arguments() throws RecognitionException {
ArgumentsContext _localctx = new ArgumentsContext(_ctx, getState());
- enterRule(_localctx, 40, RULE_arguments);
+ enterRule(_localctx, 44, RULE_arguments);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
{
- setState(363);
+ setState(396);
match(LP);
- setState(372);
- switch ( getInterpreter().adaptivePredict(_input,29,_ctx) ) {
+ setState(405);
+ switch ( getInterpreter().adaptivePredict(_input,32,_ctx) ) {
case 1:
{
- setState(364);
+ setState(397);
argument();
- setState(369);
+ setState(402);
_errHandler.sync(this);
_la = _input.LA(1);
while (_la==COMMA) {
{
{
- setState(365);
+ setState(398);
match(COMMA);
- setState(366);
+ setState(399);
argument();
}
}
- setState(371);
+ setState(404);
_errHandler.sync(this);
_la = _input.LA(1);
}
}
break;
}
- setState(374);
+ setState(407);
match(RP);
}
}
@@ -2524,21 +2698,21 @@ class PainlessParser extends Parser {
public final ArgumentContext argument() throws RecognitionException {
ArgumentContext _localctx = new ArgumentContext(_ctx, getState());
- enterRule(_localctx, 42, RULE_argument);
+ enterRule(_localctx, 46, RULE_argument);
try {
- setState(378);
- switch ( getInterpreter().adaptivePredict(_input,30,_ctx) ) {
+ setState(411);
+ switch ( getInterpreter().adaptivePredict(_input,33,_ctx) ) {
case 1:
enterOuterAlt(_localctx, 1);
{
- setState(376);
+ setState(409);
expression(0);
}
break;
case 2:
enterOuterAlt(_localctx, 2);
{
- setState(377);
+ setState(410);
funcref();
}
break;
@@ -2557,15 +2731,15 @@ class PainlessParser extends Parser {
public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) {
switch (ruleIndex) {
- case 1:
+ case 3:
return statement_sempred((StatementContext)_localctx, predIndex);
- case 13:
+ case 15:
return expression_sempred((ExpressionContext)_localctx, predIndex);
- case 14:
- return unary_sempred((UnaryContext)_localctx, predIndex);
case 16:
+ return unary_sempred((UnaryContext)_localctx, predIndex);
+ case 18:
return primary_sempred((PrimaryContext)_localctx, predIndex);
- case 17:
+ case 19:
return secondary_sempred((SecondaryContext)_localctx, predIndex);
}
return true;
@@ -2645,146 +2819,158 @@ class PainlessParser extends Parser {
}
public static final String _serializedATN =
- "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3M\u017f\4\2\t\2\4"+
+ "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3M\u01a0\4\2\t\2\4"+
"\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+
"\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
- "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\3\2\7\2\60\n\2\f\2"+
- "\16\2\63\13\2\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\5\3?\n\3\3\3\3\3"+
- "\3\3\3\3\3\3\3\3\5\3G\n\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3"+
- "\5\3T\n\3\3\3\3\3\5\3X\n\3\3\3\3\3\5\3\\\n\3\3\3\3\3\3\3\5\3a\n\3\3\3"+
- "\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3"+
- "\3\3\3\3\3\3\3\3\3\6\3z\n\3\r\3\16\3{\3\3\3\3\3\3\3\3\3\3\3\3\3\3\5\3"+
- "\u0085\n\3\3\4\3\4\5\4\u0089\n\4\3\5\3\5\7\5\u008d\n\5\f\5\16\5\u0090"+
- "\13\5\3\5\3\5\3\6\3\6\3\7\3\7\5\7\u0098\n\7\3\b\3\b\3\t\3\t\3\t\3\t\7"+
- "\t\u00a0\n\t\f\t\16\t\u00a3\13\t\3\n\3\n\3\n\7\n\u00a8\n\n\f\n\16\n\u00ab"+
- "\13\n\3\13\3\13\3\13\3\13\3\f\3\f\3\f\5\f\u00b4\n\f\3\r\3\r\3\r\3\r\3"+
- "\r\3\r\3\r\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\5\17"+
- "\u00c8\n\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17"+
- "\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17"+
- "\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17"+
- "\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17"+
- "\3\17\3\17\3\17\7\17\u0103\n\17\f\17\16\17\u0106\13\17\3\20\3\20\3\20"+
- "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+
- "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\5\20\u0125"+
- "\n\20\3\21\3\21\7\21\u0129\n\21\f\21\16\21\u012c\13\21\3\21\3\21\3\21"+
- "\7\21\u0131\n\21\f\21\16\21\u0134\13\21\3\21\3\21\3\21\3\21\3\21\3\21"+
- "\6\21\u013c\n\21\r\21\16\21\u013d\3\21\3\21\7\21\u0142\n\21\f\21\16\21"+
- "\u0145\13\21\5\21\u0147\n\21\5\21\u0149\n\21\3\22\3\22\3\22\3\22\3\22"+
- "\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\5\22\u015b\n\22"+
- "\3\23\3\23\3\23\3\23\5\23\u0161\n\23\3\24\3\24\3\24\3\24\3\24\5\24\u0168"+
- "\n\24\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\7\26\u0172\n\26\f\26\16"+
- "\26\u0175\13\26\5\26\u0177\n\26\3\26\3\26\3\27\3\27\5\27\u017d\n\27\3"+
- "\27\2\3\34\30\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,\2\16\4\2"+
- "\26\26KK\3\3\r\r\3\2\66A\3\2\34\36\3\2\37 \3\2!#\3\2$\'\3\2(+\3\2\64\65"+
- "\3\2BE\4\2\32\33\37 \3\2LM\u01a5\2\61\3\2\2\2\4\u0084\3\2\2\2\6\u0088"+
- "\3\2\2\2\b\u008a\3\2\2\2\n\u0093\3\2\2\2\f\u0097\3\2\2\2\16\u0099\3\2"+
- "\2\2\20\u009b\3\2\2\2\22\u00a4\3\2\2\2\24\u00ac\3\2\2\2\26\u00b0\3\2\2"+
- "\2\30\u00b5\3\2\2\2\32\u00bc\3\2\2\2\34\u00c7\3\2\2\2\36\u0124\3\2\2\2"+
- " \u0148\3\2\2\2\"\u015a\3\2\2\2$\u0160\3\2\2\2&\u0167\3\2\2\2(\u0169\3"+
- "\2\2\2*\u016d\3\2\2\2,\u017c\3\2\2\2.\60\5\4\3\2/.\3\2\2\2\60\63\3\2\2"+
- "\2\61/\3\2\2\2\61\62\3\2\2\2\62\64\3\2\2\2\63\61\3\2\2\2\64\65\7\2\2\3"+
- "\65\3\3\2\2\2\66\67\7\16\2\2\678\7\t\2\289\5\34\17\29:\7\n\2\2:>\5\6\4"+
- "\2;<\7\17\2\2\5\6\4\2=?\6\3\2\2>;\3\2\2\2>=\3\2\2\2?\u0085\3\2\2\2@"+
- "A\7\20\2\2AB\7\t\2\2BC\5\34\17\2CF\7\n\2\2DG\5\6\4\2EG\5\n\6\2FD\3\2\2"+
- "\2FE\3\2\2\2G\u0085\3\2\2\2HI\7\21\2\2IJ\5\b\5\2JK\7\20\2\2KL\7\t\2\2"+
- "LM\5\34\17\2MN\7\n\2\2NO\5\32\16\2O\u0085\3\2\2\2PQ\7\22\2\2QS\7\t\2\2"+
- "RT\5\f\7\2SR\3\2\2\2ST\3\2\2\2TU\3\2\2\2UW\7\r\2\2VX\5\34\17\2WV\3\2\2"+
- "\2WX\3\2\2\2XY\3\2\2\2Y[\7\r\2\2Z\\\5\16\b\2[Z\3\2\2\2[\\\3\2\2\2\\]\3"+
- "\2\2\2]`\7\n\2\2^a\5\6\4\2_a\5\n\6\2`^\3\2\2\2`_\3\2\2\2a\u0085\3\2\2"+
- "\2bc\7\22\2\2cd\7\t\2\2de\5\22\n\2ef\7K\2\2fg\7\62\2\2gh\5\34\17\2hi\7"+
- "\n\2\2ij\5\6\4\2j\u0085\3\2\2\2kl\5\20\t\2lm\5\32\16\2m\u0085\3\2\2\2"+
- "no\7\23\2\2o\u0085\5\32\16\2pq\7\24\2\2q\u0085\5\32\16\2rs\7\25\2\2st"+
- "\5\34\17\2tu\5\32\16\2u\u0085\3\2\2\2vw\7\27\2\2wy\5\b\5\2xz\5\30\r\2"+
- "yx\3\2\2\2z{\3\2\2\2{y\3\2\2\2{|\3\2\2\2|\u0085\3\2\2\2}~\7\31\2\2~\177"+
- "\5\34\17\2\177\u0080\5\32\16\2\u0080\u0085\3\2\2\2\u0081\u0082\5\34\17"+
- "\2\u0082\u0083\5\32\16\2\u0083\u0085\3\2\2\2\u0084\66\3\2\2\2\u0084@\3"+
- "\2\2\2\u0084H\3\2\2\2\u0084P\3\2\2\2\u0084b\3\2\2\2\u0084k\3\2\2\2\u0084"+
- "n\3\2\2\2\u0084p\3\2\2\2\u0084r\3\2\2\2\u0084v\3\2\2\2\u0084}\3\2\2\2"+
- "\u0084\u0081\3\2\2\2\u0085\5\3\2\2\2\u0086\u0089\5\b\5\2\u0087\u0089\5"+
- "\4\3\2\u0088\u0086\3\2\2\2\u0088\u0087\3\2\2\2\u0089\7\3\2\2\2\u008a\u008e"+
- "\7\5\2\2\u008b\u008d\5\4\3\2\u008c\u008b\3\2\2\2\u008d\u0090\3\2\2\2\u008e"+
- "\u008c\3\2\2\2\u008e\u008f\3\2\2\2\u008f\u0091\3\2\2\2\u0090\u008e\3\2"+
- "\2\2\u0091\u0092\7\6\2\2\u0092\t\3\2\2\2\u0093\u0094\7\r\2\2\u0094\13"+
- "\3\2\2\2\u0095\u0098\5\20\t\2\u0096\u0098\5\34\17\2\u0097\u0095\3\2\2"+
- "\2\u0097\u0096\3\2\2\2\u0098\r\3\2\2\2\u0099\u009a\5\34\17\2\u009a\17"+
- "\3\2\2\2\u009b\u009c\5\22\n\2\u009c\u00a1\5\26\f\2\u009d\u009e\7\f\2\2"+
- "\u009e\u00a0\5\26\f\2\u009f\u009d\3\2\2\2\u00a0\u00a3\3\2\2\2\u00a1\u009f"+
- "\3\2\2\2\u00a1\u00a2\3\2\2\2\u00a2\21\3\2\2\2\u00a3\u00a1\3\2\2\2\u00a4"+
- "\u00a9\7J\2\2\u00a5\u00a6\7\7\2\2\u00a6\u00a8\7\b\2\2\u00a7\u00a5\3\2"+
- "\2\2\u00a8\u00ab\3\2\2\2\u00a9\u00a7\3\2\2\2\u00a9\u00aa\3\2\2\2\u00aa"+
- "\23\3\2\2\2\u00ab\u00a9\3\2\2\2\u00ac\u00ad\7J\2\2\u00ad\u00ae\7\63\2"+
- "\2\u00ae\u00af\t\2\2\2\u00af\25\3\2\2\2\u00b0\u00b3\7K\2\2\u00b1\u00b2"+
- "\7\66\2\2\u00b2\u00b4\5\34\17\2\u00b3\u00b1\3\2\2\2\u00b3\u00b4\3\2\2"+
- "\2\u00b4\27\3\2\2\2\u00b5\u00b6\7\30\2\2\u00b6\u00b7\7\t\2\2\u00b7\u00b8"+
- "\7J\2\2\u00b8\u00b9\7K\2\2\u00b9\u00ba\7\n\2\2\u00ba\u00bb\5\b\5\2\u00bb"+
- "\31\3\2\2\2\u00bc\u00bd\t\3\2\2\u00bd\33\3\2\2\2\u00be\u00bf\b\17\1\2"+
- "\u00bf\u00c0\5 \21\2\u00c0\u00c1\t\4\2\2\u00c1\u00c2\5\34\17\3\u00c2\u00c3"+
- "\b\17\1\2\u00c3\u00c8\3\2\2\2\u00c4\u00c5\5\36\20\2\u00c5\u00c6\b\17\1"+
- "\2\u00c6\u00c8\3\2\2\2\u00c7\u00be\3\2\2\2\u00c7\u00c4\3\2\2\2\u00c8\u0104"+
- "\3\2\2\2\u00c9\u00ca\f\16\2\2\u00ca\u00cb\t\5\2\2\u00cb\u00cc\5\34\17"+
- "\17\u00cc\u00cd\b\17\1\2\u00cd\u0103\3\2\2\2\u00ce\u00cf\f\r\2\2\u00cf"+
- "\u00d0\t\6\2\2\u00d0\u00d1\5\34\17\16\u00d1\u00d2\b\17\1\2\u00d2\u0103"+
- "\3\2\2\2\u00d3\u00d4\f\f\2\2\u00d4\u00d5\t\7\2\2\u00d5\u00d6\5\34\17\r"+
- "\u00d6\u00d7\b\17\1\2\u00d7\u0103\3\2\2\2\u00d8\u00d9\f\13\2\2\u00d9\u00da"+
- "\t\b\2\2\u00da\u00db\5\34\17\f\u00db\u00dc\b\17\1\2\u00dc\u0103\3\2\2"+
- "\2\u00dd\u00de\f\n\2\2\u00de\u00df\t\t\2\2\u00df\u00e0\5\34\17\13\u00e0"+
- "\u00e1\b\17\1\2\u00e1\u0103\3\2\2\2\u00e2\u00e3\f\t\2\2\u00e3\u00e4\7"+
- ",\2\2\u00e4\u00e5\5\34\17\n\u00e5\u00e6\b\17\1\2\u00e6\u0103\3\2\2\2\u00e7"+
- "\u00e8\f\b\2\2\u00e8\u00e9\7-\2\2\u00e9\u00ea\5\34\17\t\u00ea\u00eb\b"+
- "\17\1\2\u00eb\u0103\3\2\2\2\u00ec\u00ed\f\7\2\2\u00ed\u00ee\7.\2\2\u00ee"+
- "\u00ef\5\34\17\b\u00ef\u00f0\b\17\1\2\u00f0\u0103\3\2\2\2\u00f1\u00f2"+
- "\f\6\2\2\u00f2\u00f3\7/\2\2\u00f3\u00f4\5\34\17\7\u00f4\u00f5\b\17\1\2"+
- "\u00f5\u0103\3\2\2\2\u00f6\u00f7\f\5\2\2\u00f7\u00f8\7\60\2\2\u00f8\u00f9"+
- "\5\34\17\6\u00f9\u00fa\b\17\1\2\u00fa\u0103\3\2\2\2\u00fb\u00fc\f\4\2"+
- "\2\u00fc\u00fd\7\61\2\2\u00fd\u00fe\5\34\17\2\u00fe\u00ff\7\62\2\2\u00ff"+
- "\u0100\5\34\17\4\u0100\u0101\b\17\1\2\u0101\u0103\3\2\2\2\u0102\u00c9"+
- "\3\2\2\2\u0102\u00ce\3\2\2\2\u0102\u00d3\3\2\2\2\u0102\u00d8\3\2\2\2\u0102"+
- "\u00dd\3\2\2\2\u0102\u00e2\3\2\2\2\u0102\u00e7\3\2\2\2\u0102\u00ec\3\2"+
- "\2\2\u0102\u00f1\3\2\2\2\u0102\u00f6\3\2\2\2\u0102\u00fb\3\2\2\2\u0103"+
- "\u0106\3\2\2\2\u0104\u0102\3\2\2\2\u0104\u0105\3\2\2\2\u0105\35\3\2\2"+
- "\2\u0106\u0104\3\2\2\2\u0107\u0108\6\20\16\3\u0108\u0109\t\n\2\2\u0109"+
- "\u0125\5 \21\2\u010a\u010b\6\20\17\3\u010b\u010c\5 \21\2\u010c\u010d\t"+
- "\n\2\2\u010d\u0125\3\2\2\2\u010e\u010f\6\20\20\3\u010f\u0125\5 \21\2\u0110"+
- "\u0111\6\20\21\3\u0111\u0112\t\13\2\2\u0112\u0125\b\20\1\2\u0113\u0114"+
- "\6\20\22\3\u0114\u0115\7G\2\2\u0115\u0125\b\20\1\2\u0116\u0117\6\20\23"+
- "\3\u0117\u0118\7H\2\2\u0118\u0125\b\20\1\2\u0119\u011a\6\20\24\3\u011a"+
- "\u011b\7I\2\2\u011b\u0125\b\20\1\2\u011c\u011d\6\20\25\3\u011d\u011e\t"+
- "\f\2\2\u011e\u0125\5\36\20\2\u011f\u0120\7\t\2\2\u0120\u0121\5\22\n\2"+
- "\u0121\u0122\7\n\2\2\u0122\u0123\5\36\20\2\u0123\u0125\3\2\2\2\u0124\u0107"+
- "\3\2\2\2\u0124\u010a\3\2\2\2\u0124\u010e\3\2\2\2\u0124\u0110\3\2\2\2\u0124"+
- "\u0113\3\2\2\2\u0124\u0116\3\2\2\2\u0124\u0119\3\2\2\2\u0124\u011c\3\2"+
- "\2\2\u0124\u011f\3\2\2\2\u0125\37\3\2\2\2\u0126\u012a\5\"\22\2\u0127\u0129"+
- "\5$\23\2\u0128\u0127\3\2\2\2\u0129\u012c\3\2\2\2\u012a\u0128\3\2\2\2\u012a"+
- "\u012b\3\2\2\2\u012b\u0149\3\2\2\2\u012c\u012a\3\2\2\2\u012d\u012e\5\22"+
- "\n\2\u012e\u0132\5&\24\2\u012f\u0131\5$\23\2\u0130\u012f\3\2\2\2\u0131"+
- "\u0134\3\2\2\2\u0132\u0130\3\2\2\2\u0132\u0133\3\2\2\2\u0133\u0149\3\2"+
- "\2\2\u0134\u0132\3\2\2\2\u0135\u0136\7\26\2\2\u0136\u013b\7J\2\2\u0137"+
- "\u0138\7\7\2\2\u0138\u0139\5\34\17\2\u0139\u013a\7\b\2\2\u013a\u013c\3"+
- "\2\2\2\u013b\u0137\3\2\2\2\u013c\u013d\3\2\2\2\u013d\u013b\3\2\2\2\u013d"+
- "\u013e\3\2\2\2\u013e\u0146\3\2\2\2\u013f\u0143\5&\24\2\u0140\u0142\5$"+
- "\23\2\u0141\u0140\3\2\2\2\u0142\u0145\3\2\2\2\u0143\u0141\3\2\2\2\u0143"+
- "\u0144\3\2\2\2\u0144\u0147\3\2\2\2\u0145\u0143\3\2\2\2\u0146\u013f\3\2"+
- "\2\2\u0146\u0147\3\2\2\2\u0147\u0149\3\2\2\2\u0148\u0126\3\2\2\2\u0148"+
- "\u012d\3\2\2\2\u0148\u0135\3\2\2\2\u0149!\3\2\2\2\u014a\u014b\6\22\26"+
- "\3\u014b\u014c\7\t\2\2\u014c\u014d\5\34\17\2\u014d\u014e\7\n\2\2\u014e"+
- "\u014f\b\22\1\2\u014f\u015b\3\2\2\2\u0150\u0151\6\22\27\3\u0151\u0152"+
- "\7\t\2\2\u0152\u0153\5\36\20\2\u0153\u0154\7\n\2\2\u0154\u015b\3\2\2\2"+
- "\u0155\u015b\7F\2\2\u0156\u015b\7K\2\2\u0157\u0158\7\26\2\2\u0158\u0159"+
- "\7J\2\2\u0159\u015b\5*\26\2\u015a\u014a\3\2\2\2\u015a\u0150\3\2\2\2\u015a"+
- "\u0155\3\2\2\2\u015a\u0156\3\2\2\2\u015a\u0157\3\2\2\2\u015b#\3\2\2\2"+
- "\u015c\u015d\6\23\30\3\u015d\u0161\5&\24\2\u015e\u015f\6\23\31\3\u015f"+
- "\u0161\5(\25\2\u0160\u015c\3\2\2\2\u0160\u015e\3\2\2\2\u0161%\3\2\2\2"+
- "\u0162\u0163\7\13\2\2\u0163\u0164\7M\2\2\u0164\u0168\5*\26\2\u0165\u0166"+
- "\7\13\2\2\u0166\u0168\t\r\2\2\u0167\u0162\3\2\2\2\u0167\u0165\3\2\2\2"+
- "\u0168\'\3\2\2\2\u0169\u016a\7\7\2\2\u016a\u016b\5\34\17\2\u016b\u016c"+
- "\7\b\2\2\u016c)\3\2\2\2\u016d\u0176\7\t\2\2\u016e\u0173\5,\27\2\u016f"+
- "\u0170\7\f\2\2\u0170\u0172\5,\27\2\u0171\u016f\3\2\2\2\u0172\u0175\3\2"+
- "\2\2\u0173\u0171\3\2\2\2\u0173\u0174\3\2\2\2\u0174\u0177\3\2\2\2\u0175"+
- "\u0173\3\2\2\2\u0176\u016e\3\2\2\2\u0176\u0177\3\2\2\2\u0177\u0178\3\2"+
- "\2\2\u0178\u0179\7\n\2\2\u0179+\3\2\2\2\u017a\u017d\5\34\17\2\u017b\u017d"+
- "\5\24\13\2\u017c\u017a\3\2\2\2\u017c\u017b\3\2\2\2\u017d-\3\2\2\2!\61"+
- ">FSW[`{\u0084\u0088\u008e\u0097\u00a1\u00a9\u00b3\u00c7\u0102\u0104\u0124"+
- "\u012a\u0132\u013d\u0143\u0146\u0148\u015a\u0160\u0167\u0173\u0176\u017c";
+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
+ "\3\2\7\2\64\n\2\f\2\16\2\67\13\2\3\2\7\2:\n\2\f\2\16\2=\13\2\3\2\3\2\3"+
+ "\3\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\4\3\4\7\4M\n\4\f\4\16\4P\13\4"+
+ "\5\4R\n\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\5\5^\n\5\3\5\3\5\3\5"+
+ "\3\5\3\5\3\5\5\5f\n\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\5\5"+
+ "s\n\5\3\5\3\5\5\5w\n\5\3\5\3\5\5\5{\n\5\3\5\3\5\3\5\5\5\u0080\n\5\3\5"+
+ "\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3"+
+ "\5\3\5\3\5\3\5\3\5\6\5\u0099\n\5\r\5\16\5\u009a\3\5\3\5\3\5\3\5\3\5\3"+
+ "\5\3\5\5\5\u00a4\n\5\3\6\3\6\5\6\u00a8\n\6\3\7\3\7\7\7\u00ac\n\7\f\7\16"+
+ "\7\u00af\13\7\3\7\3\7\3\b\3\b\3\t\3\t\5\t\u00b7\n\t\3\n\3\n\3\13\3\13"+
+ "\3\13\3\13\7\13\u00bf\n\13\f\13\16\13\u00c2\13\13\3\f\3\f\3\f\7\f\u00c7"+
+ "\n\f\f\f\16\f\u00ca\13\f\3\r\3\r\3\r\3\r\3\16\3\16\3\16\5\16\u00d3\n\16"+
+ "\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\21\3\21\3\21\3\21\3\21"+
+ "\3\21\3\21\3\21\3\21\5\21\u00e7\n\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21"+
+ "\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21"+
+ "\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21"+
+ "\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21"+
+ "\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\7\21\u0122\n\21\f\21\16\21\u0125"+
+ "\13\21\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22"+
+ "\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22"+
+ "\3\22\3\22\5\22\u0144\n\22\3\23\3\23\7\23\u0148\n\23\f\23\16\23\u014b"+
+ "\13\23\3\23\3\23\3\23\7\23\u0150\n\23\f\23\16\23\u0153\13\23\3\23\3\23"+
+ "\3\23\3\23\3\23\3\23\6\23\u015b\n\23\r\23\16\23\u015c\3\23\3\23\7\23\u0161"+
+ "\n\23\f\23\16\23\u0164\13\23\5\23\u0166\n\23\5\23\u0168\n\23\3\24\3\24"+
+ "\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24"+
+ "\3\24\3\24\5\24\u017c\n\24\3\25\3\25\3\25\3\25\5\25\u0182\n\25\3\26\3"+
+ "\26\3\26\3\26\3\26\5\26\u0189\n\26\3\27\3\27\3\27\3\27\3\30\3\30\3\30"+
+ "\3\30\7\30\u0193\n\30\f\30\16\30\u0196\13\30\5\30\u0198\n\30\3\30\3\30"+
+ "\3\31\3\31\5\31\u019e\n\31\3\31\2\3 \32\2\4\6\b\n\f\16\20\22\24\26\30"+
+ "\32\34\36 \"$&(*,.\60\2\16\4\2\26\26KK\3\3\r\r\3\2\66A\3\2\34\36\3\2\37"+
+ " \3\2!#\3\2$\'\3\2(+\3\2\64\65\3\2BE\4\2\32\33\37 \3\2LM\u01c8\2\65\3"+
+ "\2\2\2\4@\3\2\2\2\6E\3\2\2\2\b\u00a3\3\2\2\2\n\u00a7\3\2\2\2\f\u00a9\3"+
+ "\2\2\2\16\u00b2\3\2\2\2\20\u00b6\3\2\2\2\22\u00b8\3\2\2\2\24\u00ba\3\2"+
+ "\2\2\26\u00c3\3\2\2\2\30\u00cb\3\2\2\2\32\u00cf\3\2\2\2\34\u00d4\3\2\2"+
+ "\2\36\u00db\3\2\2\2 \u00e6\3\2\2\2\"\u0143\3\2\2\2$\u0167\3\2\2\2&\u017b"+
+ "\3\2\2\2(\u0181\3\2\2\2*\u0188\3\2\2\2,\u018a\3\2\2\2.\u018e\3\2\2\2\60"+
+ "\u019d\3\2\2\2\62\64\5\4\3\2\63\62\3\2\2\2\64\67\3\2\2\2\65\63\3\2\2\2"+
+ "\65\66\3\2\2\2\66;\3\2\2\2\67\65\3\2\2\28:\5\b\5\298\3\2\2\2:=\3\2\2\2"+
+ ";9\3\2\2\2;<\3\2\2\2<>\3\2\2\2=;\3\2\2\2>?\7\2\2\3?\3\3\2\2\2@A\5\26\f"+
+ "\2AB\7K\2\2BC\5\6\4\2CD\5\f\7\2D\5\3\2\2\2EQ\7\t\2\2FG\5\26\f\2GN\7K\2"+
+ "\2HI\7\f\2\2IJ\5\26\f\2JK\7K\2\2KM\3\2\2\2LH\3\2\2\2MP\3\2\2\2NL\3\2\2"+
+ "\2NO\3\2\2\2OR\3\2\2\2PN\3\2\2\2QF\3\2\2\2QR\3\2\2\2RS\3\2\2\2ST\7\n\2"+
+ "\2T\7\3\2\2\2UV\7\16\2\2VW\7\t\2\2WX\5 \21\2XY\7\n\2\2Y]\5\n\6\2Z[\7\17"+
+ "\2\2[^\5\n\6\2\\^\6\5\2\2]Z\3\2\2\2]\\\3\2\2\2^\u00a4\3\2\2\2_`\7\20\2"+
+ "\2`a\7\t\2\2ab\5 \21\2be\7\n\2\2cf\5\n\6\2df\5\16\b\2ec\3\2\2\2ed\3\2"+
+ "\2\2f\u00a4\3\2\2\2gh\7\21\2\2hi\5\f\7\2ij\7\20\2\2jk\7\t\2\2kl\5 \21"+
+ "\2lm\7\n\2\2mn\5\36\20\2n\u00a4\3\2\2\2op\7\22\2\2pr\7\t\2\2qs\5\20\t"+
+ "\2rq\3\2\2\2rs\3\2\2\2st\3\2\2\2tv\7\r\2\2uw\5 \21\2vu\3\2\2\2vw\3\2\2"+
+ "\2wx\3\2\2\2xz\7\r\2\2y{\5\22\n\2zy\3\2\2\2z{\3\2\2\2{|\3\2\2\2|\177\7"+
+ "\n\2\2}\u0080\5\n\6\2~\u0080\5\16\b\2\177}\3\2\2\2\177~\3\2\2\2\u0080"+
+ "\u00a4\3\2\2\2\u0081\u0082\7\22\2\2\u0082\u0083\7\t\2\2\u0083\u0084\5"+
+ "\26\f\2\u0084\u0085\7K\2\2\u0085\u0086\7\62\2\2\u0086\u0087\5 \21\2\u0087"+
+ "\u0088\7\n\2\2\u0088\u0089\5\n\6\2\u0089\u00a4\3\2\2\2\u008a\u008b\5\24"+
+ "\13\2\u008b\u008c\5\36\20\2\u008c\u00a4\3\2\2\2\u008d\u008e\7\23\2\2\u008e"+
+ "\u00a4\5\36\20\2\u008f\u0090\7\24\2\2\u0090\u00a4\5\36\20\2\u0091\u0092"+
+ "\7\25\2\2\u0092\u0093\5 \21\2\u0093\u0094\5\36\20\2\u0094\u00a4\3\2\2"+
+ "\2\u0095\u0096\7\27\2\2\u0096\u0098\5\f\7\2\u0097\u0099\5\34\17\2\u0098"+
+ "\u0097\3\2\2\2\u0099\u009a\3\2\2\2\u009a\u0098\3\2\2\2\u009a\u009b\3\2"+
+ "\2\2\u009b\u00a4\3\2\2\2\u009c\u009d\7\31\2\2\u009d\u009e\5 \21\2\u009e"+
+ "\u009f\5\36\20\2\u009f\u00a4\3\2\2\2\u00a0\u00a1\5 \21\2\u00a1\u00a2\5"+
+ "\36\20\2\u00a2\u00a4\3\2\2\2\u00a3U\3\2\2\2\u00a3_\3\2\2\2\u00a3g\3\2"+
+ "\2\2\u00a3o\3\2\2\2\u00a3\u0081\3\2\2\2\u00a3\u008a\3\2\2\2\u00a3\u008d"+
+ "\3\2\2\2\u00a3\u008f\3\2\2\2\u00a3\u0091\3\2\2\2\u00a3\u0095\3\2\2\2\u00a3"+
+ "\u009c\3\2\2\2\u00a3\u00a0\3\2\2\2\u00a4\t\3\2\2\2\u00a5\u00a8\5\f\7\2"+
+ "\u00a6\u00a8\5\b\5\2\u00a7\u00a5\3\2\2\2\u00a7\u00a6\3\2\2\2\u00a8\13"+
+ "\3\2\2\2\u00a9\u00ad\7\5\2\2\u00aa\u00ac\5\b\5\2\u00ab\u00aa\3\2\2\2\u00ac"+
+ "\u00af\3\2\2\2\u00ad\u00ab\3\2\2\2\u00ad\u00ae\3\2\2\2\u00ae\u00b0\3\2"+
+ "\2\2\u00af\u00ad\3\2\2\2\u00b0\u00b1\7\6\2\2\u00b1\r\3\2\2\2\u00b2\u00b3"+
+ "\7\r\2\2\u00b3\17\3\2\2\2\u00b4\u00b7\5\24\13\2\u00b5\u00b7\5 \21\2\u00b6"+
+ "\u00b4\3\2\2\2\u00b6\u00b5\3\2\2\2\u00b7\21\3\2\2\2\u00b8\u00b9\5 \21"+
+ "\2\u00b9\23\3\2\2\2\u00ba\u00bb\5\26\f\2\u00bb\u00c0\5\32\16\2\u00bc\u00bd"+
+ "\7\f\2\2\u00bd\u00bf\5\32\16\2\u00be\u00bc\3\2\2\2\u00bf\u00c2\3\2\2\2"+
+ "\u00c0\u00be\3\2\2\2\u00c0\u00c1\3\2\2\2\u00c1\25\3\2\2\2\u00c2\u00c0"+
+ "\3\2\2\2\u00c3\u00c8\7J\2\2\u00c4\u00c5\7\7\2\2\u00c5\u00c7\7\b\2\2\u00c6"+
+ "\u00c4\3\2\2\2\u00c7\u00ca\3\2\2\2\u00c8\u00c6\3\2\2\2\u00c8\u00c9\3\2"+
+ "\2\2\u00c9\27\3\2\2\2\u00ca\u00c8\3\2\2\2\u00cb\u00cc\7J\2\2\u00cc\u00cd"+
+ "\7\63\2\2\u00cd\u00ce\t\2\2\2\u00ce\31\3\2\2\2\u00cf\u00d2\7K\2\2\u00d0"+
+ "\u00d1\7\66\2\2\u00d1\u00d3\5 \21\2\u00d2\u00d0\3\2\2\2\u00d2\u00d3\3"+
+ "\2\2\2\u00d3\33\3\2\2\2\u00d4\u00d5\7\30\2\2\u00d5\u00d6\7\t\2\2\u00d6"+
+ "\u00d7\7J\2\2\u00d7\u00d8\7K\2\2\u00d8\u00d9\7\n\2\2\u00d9\u00da\5\f\7"+
+ "\2\u00da\35\3\2\2\2\u00db\u00dc\t\3\2\2\u00dc\37\3\2\2\2\u00dd\u00de\b"+
+ "\21\1\2\u00de\u00df\5$\23\2\u00df\u00e0\t\4\2\2\u00e0\u00e1\5 \21\3\u00e1"+
+ "\u00e2\b\21\1\2\u00e2\u00e7\3\2\2\2\u00e3\u00e4\5\"\22\2\u00e4\u00e5\b"+
+ "\21\1\2\u00e5\u00e7\3\2\2\2\u00e6\u00dd\3\2\2\2\u00e6\u00e3\3\2\2\2\u00e7"+
+ "\u0123\3\2\2\2\u00e8\u00e9\f\16\2\2\u00e9\u00ea\t\5\2\2\u00ea\u00eb\5"+
+ " \21\17\u00eb\u00ec\b\21\1\2\u00ec\u0122\3\2\2\2\u00ed\u00ee\f\r\2\2\u00ee"+
+ "\u00ef\t\6\2\2\u00ef\u00f0\5 \21\16\u00f0\u00f1\b\21\1\2\u00f1\u0122\3"+
+ "\2\2\2\u00f2\u00f3\f\f\2\2\u00f3\u00f4\t\7\2\2\u00f4\u00f5\5 \21\r\u00f5"+
+ "\u00f6\b\21\1\2\u00f6\u0122\3\2\2\2\u00f7\u00f8\f\13\2\2\u00f8\u00f9\t"+
+ "\b\2\2\u00f9\u00fa\5 \21\f\u00fa\u00fb\b\21\1\2\u00fb\u0122\3\2\2\2\u00fc"+
+ "\u00fd\f\n\2\2\u00fd\u00fe\t\t\2\2\u00fe\u00ff\5 \21\13\u00ff\u0100\b"+
+ "\21\1\2\u0100\u0122\3\2\2\2\u0101\u0102\f\t\2\2\u0102\u0103\7,\2\2\u0103"+
+ "\u0104\5 \21\n\u0104\u0105\b\21\1\2\u0105\u0122\3\2\2\2\u0106\u0107\f"+
+ "\b\2\2\u0107\u0108\7-\2\2\u0108\u0109\5 \21\t\u0109\u010a\b\21\1\2\u010a"+
+ "\u0122\3\2\2\2\u010b\u010c\f\7\2\2\u010c\u010d\7.\2\2\u010d\u010e\5 \21"+
+ "\b\u010e\u010f\b\21\1\2\u010f\u0122\3\2\2\2\u0110\u0111\f\6\2\2\u0111"+
+ "\u0112\7/\2\2\u0112\u0113\5 \21\7\u0113\u0114\b\21\1\2\u0114\u0122\3\2"+
+ "\2\2\u0115\u0116\f\5\2\2\u0116\u0117\7\60\2\2\u0117\u0118\5 \21\6\u0118"+
+ "\u0119\b\21\1\2\u0119\u0122\3\2\2\2\u011a\u011b\f\4\2\2\u011b\u011c\7"+
+ "\61\2\2\u011c\u011d\5 \21\2\u011d\u011e\7\62\2\2\u011e\u011f\5 \21\4\u011f"+
+ "\u0120\b\21\1\2\u0120\u0122\3\2\2\2\u0121\u00e8\3\2\2\2\u0121\u00ed\3"+
+ "\2\2\2\u0121\u00f2\3\2\2\2\u0121\u00f7\3\2\2\2\u0121\u00fc\3\2\2\2\u0121"+
+ "\u0101\3\2\2\2\u0121\u0106\3\2\2\2\u0121\u010b\3\2\2\2\u0121\u0110\3\2"+
+ "\2\2\u0121\u0115\3\2\2\2\u0121\u011a\3\2\2\2\u0122\u0125\3\2\2\2\u0123"+
+ "\u0121\3\2\2\2\u0123\u0124\3\2\2\2\u0124!\3\2\2\2\u0125\u0123\3\2\2\2"+
+ "\u0126\u0127\6\22\16\3\u0127\u0128\t\n\2\2\u0128\u0144\5$\23\2\u0129\u012a"+
+ "\6\22\17\3\u012a\u012b\5$\23\2\u012b\u012c\t\n\2\2\u012c\u0144\3\2\2\2"+
+ "\u012d\u012e\6\22\20\3\u012e\u0144\5$\23\2\u012f\u0130\6\22\21\3\u0130"+
+ "\u0131\t\13\2\2\u0131\u0144\b\22\1\2\u0132\u0133\6\22\22\3\u0133\u0134"+
+ "\7G\2\2\u0134\u0144\b\22\1\2\u0135\u0136\6\22\23\3\u0136\u0137\7H\2\2"+
+ "\u0137\u0144\b\22\1\2\u0138\u0139\6\22\24\3\u0139\u013a\7I\2\2\u013a\u0144"+
+ "\b\22\1\2\u013b\u013c\6\22\25\3\u013c\u013d\t\f\2\2\u013d\u0144\5\"\22"+
+ "\2\u013e\u013f\7\t\2\2\u013f\u0140\5\26\f\2\u0140\u0141\7\n\2\2\u0141"+
+ "\u0142\5\"\22\2\u0142\u0144\3\2\2\2\u0143\u0126\3\2\2\2\u0143\u0129\3"+
+ "\2\2\2\u0143\u012d\3\2\2\2\u0143\u012f\3\2\2\2\u0143\u0132\3\2\2\2\u0143"+
+ "\u0135\3\2\2\2\u0143\u0138\3\2\2\2\u0143\u013b\3\2\2\2\u0143\u013e\3\2"+
+ "\2\2\u0144#\3\2\2\2\u0145\u0149\5&\24\2\u0146\u0148\5(\25\2\u0147\u0146"+
+ "\3\2\2\2\u0148\u014b\3\2\2\2\u0149\u0147\3\2\2\2\u0149\u014a\3\2\2\2\u014a"+
+ "\u0168\3\2\2\2\u014b\u0149\3\2\2\2\u014c\u014d\5\26\f\2\u014d\u0151\5"+
+ "*\26\2\u014e\u0150\5(\25\2\u014f\u014e\3\2\2\2\u0150\u0153\3\2\2\2\u0151"+
+ "\u014f\3\2\2\2\u0151\u0152\3\2\2\2\u0152\u0168\3\2\2\2\u0153\u0151\3\2"+
+ "\2\2\u0154\u0155\7\26\2\2\u0155\u015a\7J\2\2\u0156\u0157\7\7\2\2\u0157"+
+ "\u0158\5 \21\2\u0158\u0159\7\b\2\2\u0159\u015b\3\2\2\2\u015a\u0156\3\2"+
+ "\2\2\u015b\u015c\3\2\2\2\u015c\u015a\3\2\2\2\u015c\u015d\3\2\2\2\u015d"+
+ "\u0165\3\2\2\2\u015e\u0162\5*\26\2\u015f\u0161\5(\25\2\u0160\u015f\3\2"+
+ "\2\2\u0161\u0164\3\2\2\2\u0162\u0160\3\2\2\2\u0162\u0163\3\2\2\2\u0163"+
+ "\u0166\3\2\2\2\u0164\u0162\3\2\2\2\u0165\u015e\3\2\2\2\u0165\u0166\3\2"+
+ "\2\2\u0166\u0168\3\2\2\2\u0167\u0145\3\2\2\2\u0167\u014c\3\2\2\2\u0167"+
+ "\u0154\3\2\2\2\u0168%\3\2\2\2\u0169\u016a\6\24\26\3\u016a\u016b\7\t\2"+
+ "\2\u016b\u016c\5 \21\2\u016c\u016d\7\n\2\2\u016d\u016e\b\24\1\2\u016e"+
+ "\u017c\3\2\2\2\u016f\u0170\6\24\27\3\u0170\u0171\7\t\2\2\u0171\u0172\5"+
+ "\"\22\2\u0172\u0173\7\n\2\2\u0173\u017c\3\2\2\2\u0174\u017c\7F\2\2\u0175"+
+ "\u017c\7K\2\2\u0176\u0177\7K\2\2\u0177\u017c\5.\30\2\u0178\u0179\7\26"+
+ "\2\2\u0179\u017a\7J\2\2\u017a\u017c\5.\30\2\u017b\u0169\3\2\2\2\u017b"+
+ "\u016f\3\2\2\2\u017b\u0174\3\2\2\2\u017b\u0175\3\2\2\2\u017b\u0176\3\2"+
+ "\2\2\u017b\u0178\3\2\2\2\u017c\'\3\2\2\2\u017d\u017e\6\25\30\3\u017e\u0182"+
+ "\5*\26\2\u017f\u0180\6\25\31\3\u0180\u0182\5,\27\2\u0181\u017d\3\2\2\2"+
+ "\u0181\u017f\3\2\2\2\u0182)\3\2\2\2\u0183\u0184\7\13\2\2\u0184\u0185\7"+
+ "M\2\2\u0185\u0189\5.\30\2\u0186\u0187\7\13\2\2\u0187\u0189\t\r\2\2\u0188"+
+ "\u0183\3\2\2\2\u0188\u0186\3\2\2\2\u0189+\3\2\2\2\u018a\u018b\7\7\2\2"+
+ "\u018b\u018c\5 \21\2\u018c\u018d\7\b\2\2\u018d-\3\2\2\2\u018e\u0197\7"+
+ "\t\2\2\u018f\u0194\5\60\31\2\u0190\u0191\7\f\2\2\u0191\u0193\5\60\31\2"+
+ "\u0192\u0190\3\2\2\2\u0193\u0196\3\2\2\2\u0194\u0192\3\2\2\2\u0194\u0195"+
+ "\3\2\2\2\u0195\u0198\3\2\2\2\u0196\u0194\3\2\2\2\u0197\u018f\3\2\2\2\u0197"+
+ "\u0198\3\2\2\2\u0198\u0199\3\2\2\2\u0199\u019a\7\n\2\2\u019a/\3\2\2\2"+
+ "\u019b\u019e\5 \21\2\u019c\u019e\5\30\r\2\u019d\u019b\3\2\2\2\u019d\u019c"+
+ "\3\2\2\2\u019e\61\3\2\2\2$\65;NQ]ervz\177\u009a\u00a3\u00a7\u00ad\u00b6"+
+ "\u00c0\u00c8\u00d2\u00e6\u0121\u0123\u0143\u0149\u0151\u015c\u0162\u0165"+
+ "\u0167\u017b\u0181\u0188\u0194\u0197\u019d";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {
diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/PainlessParserBaseVisitor.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/PainlessParserBaseVisitor.java
index f116f087c5c..08358384fca 100644
--- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/PainlessParserBaseVisitor.java
+++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/PainlessParserBaseVisitor.java
@@ -18,6 +18,20 @@ class PainlessParserBaseVisitor extends AbstractParseTreeVisitor implement
* {@link #visitChildren} on {@code ctx}.
*/
@Override public T visitSource(PainlessParser.SourceContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitFunction(PainlessParser.FunctionContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitParameters(PainlessParser.ParametersContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
@@ -333,6 +347,13 @@ class PainlessParserBaseVisitor extends AbstractParseTreeVisitor implement
* {@link #visitChildren} on {@code ctx}.
*/
@Override public T visitVariable(PainlessParser.VariableContext ctx) { return visitChildren(ctx); }
+ /**
+ * {@inheritDoc}
+ *
+ * The default implementation returns the result of calling
+ * {@link #visitChildren} on {@code ctx}.
+ */
+ @Override public T visitCalllocal(PainlessParser.CalllocalContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/PainlessParserVisitor.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/PainlessParserVisitor.java
index f0943743ef8..5c0adb5076a 100644
--- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/PainlessParserVisitor.java
+++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/PainlessParserVisitor.java
@@ -16,6 +16,18 @@ interface PainlessParserVisitor extends ParseTreeVisitor {
* @return the visitor result
*/
T visitSource(PainlessParser.SourceContext ctx);
+ /**
+ * Visit a parse tree produced by {@link PainlessParser#function}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitFunction(PainlessParser.FunctionContext ctx);
+ /**
+ * Visit a parse tree produced by {@link PainlessParser#parameters}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitParameters(PainlessParser.ParametersContext ctx);
/**
* Visit a parse tree produced by the {@code if}
* labeled alternative in {@link PainlessParser#statement}.
@@ -320,6 +332,13 @@ interface PainlessParserVisitor extends ParseTreeVisitor {
* @return the visitor result
*/
T visitVariable(PainlessParser.VariableContext ctx);
+ /**
+ * Visit a parse tree produced by the {@code calllocal}
+ * labeled alternative in {@link PainlessParser#primary}.
+ * @param ctx the parse tree
+ * @return the visitor result
+ */
+ T visitCalllocal(PainlessParser.CalllocalContext ctx);
/**
* Visit a parse tree produced by the {@code newobject}
* labeled alternative in {@link PainlessParser#primary}.
diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java
index 471cb7d64ea..c1fe02f9388 100644
--- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java
+++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java
@@ -27,10 +27,13 @@ import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.atn.PredictionMode;
+import org.antlr.v4.runtime.tree.TerminalNode;
import org.elasticsearch.painless.CompilerSettings;
+import org.elasticsearch.painless.Locals.ExecuteReserved;
+import org.elasticsearch.painless.Locals.FunctionReserved;
import org.elasticsearch.painless.Location;
import org.elasticsearch.painless.Operation;
-import org.elasticsearch.painless.Variables.Reserved;
+import org.elasticsearch.painless.Locals.Reserved;
import org.elasticsearch.painless.antlr.PainlessParser.AfterthoughtContext;
import org.elasticsearch.painless.antlr.PainlessParser.ArgumentContext;
import org.elasticsearch.painless.antlr.PainlessParser.ArgumentsContext;
@@ -41,6 +44,7 @@ import org.elasticsearch.painless.antlr.PainlessParser.BoolContext;
import org.elasticsearch.painless.antlr.PainlessParser.BraceaccessContext;
import org.elasticsearch.painless.antlr.PainlessParser.BreakContext;
import org.elasticsearch.painless.antlr.PainlessParser.CallinvokeContext;
+import org.elasticsearch.painless.antlr.PainlessParser.CalllocalContext;
import org.elasticsearch.painless.antlr.PainlessParser.CastContext;
import org.elasticsearch.painless.antlr.PainlessParser.ChainprecContext;
import org.elasticsearch.painless.antlr.PainlessParser.CompContext;
@@ -62,6 +66,7 @@ import org.elasticsearch.painless.antlr.PainlessParser.FalseContext;
import org.elasticsearch.painless.antlr.PainlessParser.FieldaccessContext;
import org.elasticsearch.painless.antlr.PainlessParser.ForContext;
import org.elasticsearch.painless.antlr.PainlessParser.FuncrefContext;
+import org.elasticsearch.painless.antlr.PainlessParser.FunctionContext;
import org.elasticsearch.painless.antlr.PainlessParser.IfContext;
import org.elasticsearch.painless.antlr.PainlessParser.InitializerContext;
import org.elasticsearch.painless.antlr.PainlessParser.NewarrayContext;
@@ -69,6 +74,7 @@ import org.elasticsearch.painless.antlr.PainlessParser.NewobjectContext;
import org.elasticsearch.painless.antlr.PainlessParser.NullContext;
import org.elasticsearch.painless.antlr.PainlessParser.NumericContext;
import org.elasticsearch.painless.antlr.PainlessParser.OperatorContext;
+import org.elasticsearch.painless.antlr.PainlessParser.ParametersContext;
import org.elasticsearch.painless.antlr.PainlessParser.PostContext;
import org.elasticsearch.painless.antlr.PainlessParser.PreContext;
import org.elasticsearch.painless.antlr.PainlessParser.ReadContext;
@@ -104,7 +110,8 @@ import org.elasticsearch.painless.node.ENull;
import org.elasticsearch.painless.node.ENumeric;
import org.elasticsearch.painless.node.EUnary;
import org.elasticsearch.painless.node.LBrace;
-import org.elasticsearch.painless.node.LCall;
+import org.elasticsearch.painless.node.LCallInvoke;
+import org.elasticsearch.painless.node.LCallLocal;
import org.elasticsearch.painless.node.LCast;
import org.elasticsearch.painless.node.LField;
import org.elasticsearch.painless.node.LNewArray;
@@ -122,6 +129,7 @@ import org.elasticsearch.painless.node.SDo;
import org.elasticsearch.painless.node.SEach;
import org.elasticsearch.painless.node.SExpression;
import org.elasticsearch.painless.node.SFor;
+import org.elasticsearch.painless.node.SFunction;
import org.elasticsearch.painless.node.SIf;
import org.elasticsearch.painless.node.SIfElse;
import org.elasticsearch.painless.node.SReturn;
@@ -130,7 +138,9 @@ import org.elasticsearch.painless.node.SThrow;
import org.elasticsearch.painless.node.STry;
import org.elasticsearch.painless.node.SWhile;
+import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Deque;
import java.util.List;
/**
@@ -138,19 +148,21 @@ import java.util.List;
*/
public final class Walker extends PainlessParserBaseVisitor