Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.lang.ClassCastException: java.util.regex.Matcher$ImmutableMatchResult cannot be cast to java.util.regex.Matcher #165

Closed
talios opened this issue Aug 18, 2015 · 4 comments
Labels

Comments

@talios
Copy link
Contributor

talios commented Aug 18, 2015

I'm experimenting with using the bazel.io build tool from Google to build a simple Frege app ([https://github.com/talios/fregebzl](repo is here), and I'm getting the following out of the compiler:

Exception in thread "main" java.lang.ClassCastException: java.util.regex.Matcher$ImmutableMatchResult cannot be cast to java.util.regex.Matcher
  at frege.runtime.Regex.clone(Regex.java:55)
  at frege.runtime.Regex.find(Regex.java:99)
  at frege.java.util.Regex._tilde(Regex.java:1111)
  at frege.compiler.common.CompilerOptions.scanOpts(CompilerOptions.java:929)
  at frege.compiler.common.CompilerOptions$37.eval(CompilerOptions.java:2279)
  at frege.compiler.common.CompilerOptions$37.eval(CompilerOptions.java:2277)
  at frege.runtime.Delayed.call(Delayed.java:198)
  at frege.runtime.Delayed.forced(Delayed.java:267)
  at frege.compiler.Main$43.eval(Main.java:7142)
  at frege.runtime.Fun1$1.eval(Fun1.java:63)
  at frege.runtime.Delayed.call(Delayed.java:198)
  at frege.runtime.Runtime.runMain(Runtime.java:273)
  at frege.compiler.Main.main(Main.java:8211)

This is when running:

  rm -rf bazel-out/local_darwin-fastbuild/bin/src/main/libfrege_test-impl.jar.build_output
  mkdir -p bazel-out/local_darwin-fastbuild/bin/src/main/libfrege_test-impl.jar.build_output
  java -Xss2m -jar external/frege-lib/jar/frege3.22.525-g704b834.jar -v -hints \
    -d bazel-out/local_darwin-fastbuild/bin/src/main/libfrege_test-impl.jar.build_output \
    src/main/frege/test.fr

from the build.

I suspect from the trace this is something tripping when parsing the command line arguments, when I run those commands manually in my terminal the build seems to execute fine.

This is using frege3.22.525-g704b834.jar.

@talios
Copy link
Contributor Author

talios commented Aug 18, 2015

Turns out the build was running "exec env -" and running inside a new environment, which was picking up my JDK9 EA install as the JDK it was running against.

Once I removed that the build worked fine :)

@talios talios closed this as completed Aug 18, 2015
@Ingo60
Copy link
Member

Ingo60 commented Aug 18, 2015 via email

@Ingo60 Ingo60 reopened this Aug 18, 2015
@Ingo60 Ingo60 added the bug label Aug 18, 2015
@Ingo60
Copy link
Member

Ingo60 commented Aug 18, 2015

Not so fast, @talios !
I shall devise a solution before closing this.

The solution can only be a rewrite of the existing functionality in such a way that the type java.util.Matcher will not get exposed anymore as an apparently pure type.

Some background may be in order here: java.util.regex.Matcher neither has public constructors nor is it Cloneable. In addition, all matching operations mutate the state of the matcher. This is particularly bad when you want a pure Regex library and don't have a ST monad yet (as it was the case in the early days of Frege. The functionality was especially important because the lexical analyser worked with regular expressions, which in turn was a remnant of the even older Frege in Perl era.).

Because in the case where there is no way to clone the state of a Matcher, you can't use the technique known as defensive copying. The idea is here, that you don't work on the Matcher passed by the user, but on a clone, and then return the new Matcher as result. This way, each Matcher object is used only one time inside the library, and appears immutable to the outside.

However, somehow I realized that the method toMatchResult() which returns a java.util.regex.MatchResult would in fact just create a new Matcher and copy the state over to it. In fact, back then in Java 1.6 Matcher was the one and only class that implemented MatchResult! The following expression, then, would effectively clone a Matcher m:

((Matcher)m.toMatchResult()).usePattern(m.pattern())

And this did work, until now. Apparently,JDK9 introduces a new, non-public java.util.regex.Matcher$ImmutableMatchResult that is the result of toMatchResult() and this, of course, effectively eliminates the last possibility to clone a Matcher.

The only thing I don't understand is why, in the world, can't Matcher not implement Cloneable? Things would be so easy, then!

Ingo60 added a commit that referenced this issue Aug 19, 2015
Ingo60 added a commit that referenced this issue Aug 19, 2015
@Ingo60 Ingo60 closed this as completed in aa3af0c Aug 19, 2015
Ingo60 added a commit that referenced this issue Aug 19, 2015
It turned out to be useless.

This reverts commit ec92c01.
Ingo60 added a commit that referenced this issue Aug 19, 2015
Ingo60 added a commit that referenced this issue Aug 19, 2015
@Ingo60
Copy link
Member

Ingo60 commented Aug 20, 2015

The following functionality is gone or changed:

  • operators ?~ and /~

  • replaceAll and replaceFirst are now members of String and have signature:

    String -> Pattern -> String -> String

The first argument is the String to operate on. The first substring/all substrings of that String matched by the Pattern is/are replaced with the (possibly expanded) 3rd argument.

"John Mayer".replaceFirst '(\w+)\s+(\w+)' "$2, $1" == "Mayer, John"

This reflects the usual Java syntax, except that the Pattern cannot be given as String. Which is a good thing, IMHO.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants