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 index 9803cd36ef8..eb9ac2979c7 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Analyzer.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Analyzer.java @@ -102,7 +102,7 @@ class Analyzer extends PainlessParserBaseVisitor { metadata.scorerValueSlot = utility.addVariable(null, "#scorer", definition.objectType).slot; // doc parameter passed to the script. // TODO: currently working as a def type, should be smapType... - metadata.docValueSlot = utility.addVariable(null, "doc", definition.defType).slot; + metadata.docValueSlot = utility.addVariable(null, "doc", definition.smapType).slot; // // reserved words implemented as local variables // diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/AnalyzerExternal.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/AnalyzerExternal.java index 176a19d7dc2..f907138f752 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/AnalyzerExternal.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/AnalyzerExternal.java @@ -238,14 +238,6 @@ class AnalyzerExternal { definition.getType(parentemd.current.struct, parentemd.current.type.getDimensions() - 1); analyzeLoadStoreExternal(ctx); parentemd.current = braceenmd.type; - - if (dotctx != null) { - metadata.createExtNodeMetadata(parent, dotctx); - analyzer.visit(dotctx); - } else if (bracectx != null) { - metadata.createExtNodeMetadata(parent, bracectx); - analyzer.visit(bracectx); - } } else { final boolean store = braceenmd.last && parentemd.storeExpr != null; final boolean get = parentemd.read || parentemd.token > 0 || !braceenmd.last; @@ -319,6 +311,14 @@ class AnalyzerExternal { throw new IllegalArgumentException(AnalyzerUtility.error(ctx) + "Attempting to address a non-array type [" + parentemd.current.name + "] as an array."); } + + if (dotctx != null) { + metadata.createExtNodeMetadata(parent, dotctx); + analyzer.visit(dotctx); + } else if (bracectx != null) { + metadata.createExtNodeMetadata(parent, bracectx); + analyzer.visit(bracectx); + } } void processExtdot(final ExtdotContext ctx) { @@ -449,7 +449,7 @@ class AnalyzerExternal { } // special cases: reserved words - if ("_score".equals(id) || "doc".equals(id)) { + if (varenmd.last && ("_score".equals(id) || "doc".equals(id))) { // read-only: don't allow stores if (parentemd.storeExpr != null) { throw new IllegalArgumentException(AnalyzerUtility.error(ctx) + "Variable [" + id + "] is read-only."); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterExternal.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterExternal.java index cd10a5ac3a6..f25780ab496 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterExternal.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterExternal.java @@ -306,18 +306,14 @@ class WriterExternal { final boolean cat = utility.containsStrings(parentemd.storeExpr); if (cat) { - if (field || name || shortcut) { - execute.dupX1(); - } else if (array) { - execute.dup2X1(); + if (maplist && constant != null) { + utility.writeConstant(source, constant); } - if (maplist) { - if (constant != null) { - utility.writeConstant(source, constant); - } - - execute.dupX2(); + if (field || name || (shortcut && !maplist)) { + execute.dupX1(); + } else if (array || maplist) { + execute.dup2X1(); } writeLoadStoreInstruction(source, false, variable, field, name, array, shortcut); @@ -340,18 +336,14 @@ class WriterExternal { } else if (parentemd.token > 0) { final int token = parentemd.token; - if (field || name || shortcut) { - execute.dup(); - } else if (array) { - execute.dup2(); + if (maplist && constant != null) { + utility.writeConstant(source, constant); } - if (maplist) { - if (constant != null) { - utility.writeConstant(source, constant); - } - - execute.dupX1(); + if (field || name || (shortcut && !maplist)) { + execute.dup(); + } else if (array || maplist) { + execute.dup2(); } writeLoadStoreInstruction(source, false, variable, field, name, array, shortcut); @@ -467,10 +459,10 @@ class WriterExternal { private void writeLoadStoreField(final ParserRuleContext source, final boolean store, final String name) { if (store) { - execute.visitInvokeDynamicInsn(name, WriterConstants.DEF_DYNAMIC_STORE_FIELD_DESC, + execute.visitInvokeDynamicInsn(name, WriterConstants.DEF_DYNAMIC_STORE_FIELD_DESC, WriterConstants.DEF_BOOTSTRAP_HANDLE, new Object[] { DynamicCallSite.STORE }); } else { - execute.visitInvokeDynamicInsn(name, WriterConstants.DEF_DYNAMIC_LOAD_FIELD_DESC, + execute.visitInvokeDynamicInsn(name, WriterConstants.DEF_DYNAMIC_LOAD_FIELD_DESC, WriterConstants.DEF_BOOTSTRAP_HANDLE, new Object[] { DynamicCallSite.LOAD }); } } @@ -482,10 +474,10 @@ class WriterExternal { if (type.sort == Sort.DEF) { if (store) { - execute.visitInvokeDynamicInsn("arrayStore", WriterConstants.DEF_DYNAMIC_ARRAY_STORE_DESC, + execute.visitInvokeDynamicInsn("arrayStore", WriterConstants.DEF_DYNAMIC_ARRAY_STORE_DESC, WriterConstants.DEF_BOOTSTRAP_HANDLE, new Object[] { DynamicCallSite.ARRAY_STORE }); } else { - execute.visitInvokeDynamicInsn("arrayLoad", WriterConstants.DEF_DYNAMIC_ARRAY_LOAD_DESC, + execute.visitInvokeDynamicInsn("arrayLoad", WriterConstants.DEF_DYNAMIC_ARRAY_LOAD_DESC, WriterConstants.DEF_BOOTSTRAP_HANDLE, new Object[] { DynamicCallSite.ARRAY_LOAD }); } } else { @@ -705,11 +697,11 @@ class WriterExternal { writeDynamicCallExternal(source); } } - + private void writeDynamicCallExternal(final ExtcallContext source) { final ExtNodeMetadata sourceenmd = metadata.getExtNodeMetadata(source); final List arguments = source.arguments().expression(); - + StringBuilder signature = new StringBuilder(); signature.append('('); // first parameter is the receiver, we never know its type: always Object @@ -726,7 +718,7 @@ class WriterExternal { signature.append(')'); // return value: currently always Object. making this better may be tricky... signature.append(WriterConstants.OBJECT_TYPE.getDescriptor()); - execute.visitInvokeDynamicInsn((String)sourceenmd.target, signature.toString(), + execute.visitInvokeDynamicInsn((String)sourceenmd.target, signature.toString(), WriterConstants.DEF_BOOTSTRAP_HANDLE, new Object[] { DynamicCallSite.METHOD_CALL }); } } diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java index e3aefda4766..2a0dfc17242 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/NeedsScoreTests.java @@ -42,22 +42,22 @@ public class NeedsScoreTests extends ESSingleNodeTestCase { SearchLookup lookup = new SearchLookup(index.mapperService(), index.fieldData(), null); Object compiled = service.compile("1.2", Collections.emptyMap()); - SearchScript ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "painless", compiled), + SearchScript ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "painless", compiled), lookup, Collections.emptyMap()); assertFalse(ss.needsScores()); compiled = service.compile("doc['d'].value", Collections.emptyMap()); - ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "painless", compiled), + ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "painless", compiled), lookup, Collections.emptyMap()); assertFalse(ss.needsScores()); compiled = service.compile("1/_score", Collections.emptyMap()); - ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "painless", compiled), + ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "painless", compiled), lookup, Collections.emptyMap()); assertTrue(ss.needsScores()); compiled = service.compile("doc['d'].value * _score", Collections.emptyMap()); - ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "painless", compiled), + ss = service.search(new CompiledScript(ScriptType.INLINE, "randomName", "painless", compiled), lookup, Collections.emptyMap()); assertTrue(ss.needsScores()); }