+ @Override\r
+ public boolean equals(Object obj) {\r
+ if(this == obj)\r
+ return true;\r
+ if(obj == null || obj.getClass() != getClass())\r
+ return false;\r
+ StringInterpolation other = (StringInterpolation)obj;\r
+ return Arrays.equals(textParts, other.textParts) && Arrays.equals(parameterTypes, other.parameterTypes);\r
+ }\r
+ \r
+ @Override\r
+ public int constructorTag() {\r
+ return textParts.length == 2 && parameterTypes[0] == Types.STRING ? 0 : -1;\r
+ }\r
+ \r
+ @Override\r
+ public void deconstruct(MethodBuilder mb, IVal parameter, Cont success, Label failure) {\r
+ if(textParts.length != 2)\r
+ throw new InternalCompilerError("String interpolation with more than one open string parts cannot be used as a pattern.");\r
+ mb.push(parameter, Types.STRING);\r
+ LocalVariable temp = mb.createLocalVariable(null, TypeDesc.STRING);\r
+ mb.storeLocal(temp);\r
+ if(!textParts[0].isEmpty()) {\r
+ mb.loadLocal(temp);\r
+ mb.loadConstant(textParts[0]);\r
+ mb.invokeVirtual("java/lang/String", "startsWith", TypeDesc.BOOLEAN, new TypeDesc[] {TypeDesc.STRING});\r
+ mb.ifZeroComparisonBranch(failure, "==");\r
+ }\r
+ if(!textParts[1].isEmpty()) {\r
+ mb.loadLocal(temp);\r
+ mb.loadConstant(textParts[1]);\r
+ mb.invokeVirtual("java/lang/String", "endsWith", TypeDesc.BOOLEAN, new TypeDesc[] {TypeDesc.STRING});\r
+ mb.ifZeroComparisonBranch(failure, "==");\r
+ }\r
+ mb.loadLocal(temp);\r
+ mb.loadConstant(textParts[0].length());\r
+ mb.loadLocal(temp);\r
+ mb.invokeVirtual("java/lang/String", "length", TypeDesc.INT, Constants.EMPTY_TYPEDESC_ARRAY);\r
+ mb.loadConstant(textParts[1].length());\r
+ mb.math(Opcodes.ISUB);\r
+ mb.invokeVirtual("java/lang/String", "substring", TypeDesc.STRING, new TypeDesc[] {TypeDesc.INT, TypeDesc.INT});\r
+ mb.storeLocal(temp);\r
+ mb.jump(success, new LocalVariableConstant(Types.STRING, temp));\r
+ }\r
+ \r