10

Recently I've been writing a compiler for a JVM programming language and I've realised a problem.

I would like to access a Java method from my programming language and also allow a Java method to access a method in my language. The problem is that I need to know the Java methods signature to call it in the bytecode I generate and vice versa.

I've been trying to think of any methods for how Scala does this. Here are my thoughts.

  1. Scala accesses the .java files on the class path and parses them, extracting the method signatures from there.
  2. .java files are compiled to .class files. The Java ASM library is then used to access the .class files and get the method signatures. The problem with this method is that the .java files must be compiled first.
  3. .java files are loaded dynamically using reflection. The problem with this is I believe that the JVM doesn't allow for loading classes that are outside of the compilers class path.

Looking into Scala it works well with other JVM languages but I can't find information on exactly how it does it.

How does Scala get method signatures of other JVM language methods?

Michael
  • 3,411
  • 4
  • 25
  • 56
  • You should add info that you want to have access to java methods from your language and from java to your methods. (as that other answer was deleted) – GotoFinal Jul 12 '18 at 13:33
  • Having mixed java-yourLanguage projects it a pretty advanced use case. – Jasper-M Jul 12 '18 at 14:20
  • It may be advanced but languages such as Scala/Java can do this. It's not uncommon to mix the two languages and I will have to implement this feature in the future. – Michael Jul 12 '18 at 14:24
  • Reflection gives you only java -> yourLang interoperability, that is: you can call java stuff from your code, but not the other way round. To make it work the other way round, you have to generate something that `javac` can work with, i.e. compile your stuff to jvm bytecode and give the `.class` to the `javac`. – Andrey Tyukin Jul 12 '18 at 18:21

1 Answers1

5

I think you are confusing class path and source path: there are no .java or .scala files on the class path, there are .class files (possibly inside .jars). So for dependencies (on the class path), you don't need to do anything special. They can have their own dependencies on your language, including previous versions of your project, but they are already compiled by definition.

Now, for mixed projects, where you have Java and your language on the source path, scalac does parse Java with its own parser (i.e. your option 1).

The problem with option 3 is not that "the JVM doesn't allow for loading classes that are outside of the compilers class path", but that reflection also only works on classes, not on source files.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • That makes sense! So this means if a new JVM language was made Scala would have to write new parsers get the information? Also doesn't this mean that Java has parsers for Scala to be able to get Scala method signatures? – Michael Jul 12 '18 at 14:38
  • 2
    Java does not need to know about scala, scala can just generate stubs for own classes, so simple classes that only contains method signatures that are used for compilation of java. So javac will see compiled scala classes, normal ones, or stubs if it is not possible to compile them yet. – GotoFinal Jul 12 '18 at 14:40
  • 1
    @Michael Javac doesn't allow to compile mixed projects. Scalac also doesn't allow to compile projects that contain other languages than Java or Scala. – Jasper-M Jul 12 '18 at 14:41
  • I think I understand @GotoFinal. So if I repeat what you've said. Scala will generate `.class` files with stub methods. Then after Java has compiled its classes it would then run the Scala compiler and generate the methods fully? – Michael Jul 12 '18 at 14:43
  • 1
    @Michael Yep, just see how compilation of C/Cpp works, you have special header files that you include so you don't need to include full code as this might not always be possible/easy. Or you need to define method at top of the file but implement it somewhere lower - so compiler will already know about this method. But here you need to generate them instead. And then compile again to normal full classes. – GotoFinal Jul 12 '18 at 14:55
  • This makes sense now thank you! Very interesting how the compilers deal with things like this in the background! – Michael Jul 12 '18 at 14:57