|
@@ -19,16 +19,23 @@
|
|
|
|
|
|
package org.elasticsearch.painless.node;
|
|
|
|
|
|
-import org.elasticsearch.painless.Constant;
|
|
|
import org.elasticsearch.painless.Location;
|
|
|
-import org.elasticsearch.painless.MethodWriter;
|
|
|
import org.elasticsearch.painless.Scope;
|
|
|
-import org.elasticsearch.painless.WriterConstants;
|
|
|
+import org.elasticsearch.painless.ir.BlockNode;
|
|
|
+import org.elasticsearch.painless.ir.CallNode;
|
|
|
+import org.elasticsearch.painless.ir.CallSubNode;
|
|
|
import org.elasticsearch.painless.ir.ClassNode;
|
|
|
-import org.elasticsearch.painless.ir.RegexNode;
|
|
|
+import org.elasticsearch.painless.ir.ConstantNode;
|
|
|
+import org.elasticsearch.painless.ir.FieldNode;
|
|
|
+import org.elasticsearch.painless.ir.MemberFieldLoadNode;
|
|
|
+import org.elasticsearch.painless.ir.MemberFieldStoreNode;
|
|
|
+import org.elasticsearch.painless.ir.StatementExpressionNode;
|
|
|
+import org.elasticsearch.painless.ir.StaticNode;
|
|
|
+import org.elasticsearch.painless.lookup.PainlessMethod;
|
|
|
import org.elasticsearch.painless.symbol.ScriptRoot;
|
|
|
|
|
|
import java.lang.reflect.Modifier;
|
|
|
+import java.util.Arrays;
|
|
|
import java.util.regex.Pattern;
|
|
|
import java.util.regex.PatternSyntaxException;
|
|
|
|
|
@@ -39,7 +46,7 @@ public final class ERegex extends AExpression {
|
|
|
|
|
|
private final String pattern;
|
|
|
private final int flags;
|
|
|
- private Constant constant;
|
|
|
+ private String name;
|
|
|
|
|
|
public ERegex(Location location, String pattern, String flagsString) {
|
|
|
super(location);
|
|
@@ -74,30 +81,89 @@ public final class ERegex extends AExpression {
|
|
|
new IllegalArgumentException("Error compiling regex: " + e.getDescription()));
|
|
|
}
|
|
|
|
|
|
- String name = scriptRoot.getNextSyntheticName("regex");
|
|
|
- scriptRoot.getClassNode().addField(
|
|
|
- new SField(location, Modifier.FINAL | Modifier.STATIC | Modifier.PRIVATE, name, Pattern.class));
|
|
|
- constant = new Constant(location, MethodWriter.getType(Pattern.class), name, this::initializeConstant);
|
|
|
+ name = scriptRoot.getNextSyntheticName("regex");
|
|
|
actual = Pattern.class;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- RegexNode write(ClassNode classNode) {
|
|
|
- RegexNode regexNode = new RegexNode();
|
|
|
- regexNode.setLocation(location);
|
|
|
+ MemberFieldLoadNode write(ClassNode classNode) {
|
|
|
+ FieldNode fieldNode = new FieldNode();
|
|
|
+ fieldNode.setLocation(location);
|
|
|
+ fieldNode.setModifiers(Modifier.FINAL | Modifier.STATIC | Modifier.PRIVATE);
|
|
|
+ fieldNode.setFieldType(Pattern.class);
|
|
|
+ fieldNode.setName(name);
|
|
|
|
|
|
- regexNode.setExpressionType(actual);
|
|
|
- regexNode.setFlags(flags);
|
|
|
- regexNode.setPattern(pattern);
|
|
|
- regexNode.setConstant(constant);
|
|
|
+ classNode.addFieldNode(fieldNode);
|
|
|
|
|
|
- return regexNode;
|
|
|
- }
|
|
|
+ try {
|
|
|
+ StatementExpressionNode statementExpressionNode = new StatementExpressionNode();
|
|
|
+ statementExpressionNode.setLocation(location);
|
|
|
+
|
|
|
+ BlockNode blockNode = classNode.getClinitBlockNode();
|
|
|
+ blockNode.addStatementNode(statementExpressionNode);
|
|
|
+
|
|
|
+ MemberFieldStoreNode memberFieldStoreNode = new MemberFieldStoreNode();
|
|
|
+ memberFieldStoreNode.setLocation(location);
|
|
|
+ memberFieldStoreNode.setExpressionType(void.class);
|
|
|
+ memberFieldStoreNode.setFieldType(Pattern.class);
|
|
|
+ memberFieldStoreNode.setName(name);
|
|
|
+ memberFieldStoreNode.setStatic(true);
|
|
|
+
|
|
|
+ statementExpressionNode.setExpressionNode(memberFieldStoreNode);
|
|
|
+
|
|
|
+ CallNode callNode = new CallNode();
|
|
|
+ callNode.setLocation(location);
|
|
|
+ callNode.setExpressionType(Pattern.class);
|
|
|
+
|
|
|
+ memberFieldStoreNode.setChildNode(callNode);
|
|
|
+
|
|
|
+ StaticNode staticNode = new StaticNode();
|
|
|
+ staticNode.setLocation(location);
|
|
|
+ staticNode.setExpressionType(Pattern.class);
|
|
|
+
|
|
|
+ callNode.setLeftNode(staticNode);
|
|
|
+
|
|
|
+ CallSubNode callSubNode = new CallSubNode();
|
|
|
+ callSubNode.setLocation(location);
|
|
|
+ callSubNode.setExpressionType(Pattern.class);
|
|
|
+ callSubNode.setBox(Pattern.class);
|
|
|
+ callSubNode.setMethod(new PainlessMethod(
|
|
|
+ Pattern.class.getMethod("compile", String.class, int.class),
|
|
|
+ Pattern.class,
|
|
|
+ Pattern.class,
|
|
|
+ Arrays.asList(String.class, int.class),
|
|
|
+ null,
|
|
|
+ null,
|
|
|
+ null
|
|
|
+ )
|
|
|
+ );
|
|
|
+
|
|
|
+ callNode.setRightNode(callSubNode);
|
|
|
+
|
|
|
+ ConstantNode constantNode = new ConstantNode();
|
|
|
+ constantNode.setLocation(location);
|
|
|
+ constantNode.setExpressionType(String.class);
|
|
|
+ constantNode.setConstant(pattern);
|
|
|
+
|
|
|
+ callSubNode.addArgumentNode(constantNode);
|
|
|
+
|
|
|
+ constantNode = new ConstantNode();
|
|
|
+ constantNode.setLocation(location);
|
|
|
+ constantNode.setExpressionType(int.class);
|
|
|
+ constantNode.setConstant(flags);
|
|
|
+
|
|
|
+ callSubNode.addArgumentNode(constantNode);
|
|
|
+ } catch (Exception exception) {
|
|
|
+ throw createError(new IllegalStateException("could not generate regex constant [" + pattern + "/" + flags +"] in clinit"));
|
|
|
+ }
|
|
|
+
|
|
|
+ MemberFieldLoadNode memberFieldLoadNode = new MemberFieldLoadNode();
|
|
|
+ memberFieldLoadNode.setLocation(location);
|
|
|
+ memberFieldLoadNode.setExpressionType(Pattern.class);
|
|
|
+ memberFieldLoadNode.setName(name);
|
|
|
+ memberFieldLoadNode.setStatic(true);
|
|
|
|
|
|
- private void initializeConstant(MethodWriter writer) {
|
|
|
- writer.push(pattern);
|
|
|
- writer.push(flags);
|
|
|
- writer.invokeStatic(org.objectweb.asm.Type.getType(Pattern.class), WriterConstants.PATTERN_COMPILE);
|
|
|
+ return memberFieldLoadNode;
|
|
|
}
|
|
|
|
|
|
private int flagForChar(char c) {
|