manifold-systems / manifold

Manifold is a Java compiler plugin, its features include Metaprogramming, Properties, Extension Methods, Operator Overloading, Templates, a Preprocessor, and more.
http://manifold.systems/
Apache License 2.0
2.41k stars 125 forks source link

Create your own autoboxing #332

Closed lilumat closed 2 years ago

lilumat commented 2 years ago

Hi, To begin, what a very good job, overloading operators and extension method, !!! It reminds me of my past development with the best langage : Smalltalk ;)

Can you think it's possible to create your own autoboxing ? I work on an emulator of Oracle Forms and I would you like write this in Java :

VarcharSql value = "MANIFOLD"; or public VarcharSql killCovid() { return "SUCCESS"; }

where VarcharSql is my java class that used overloading operators and implements the behavior of Varchar2

Regards & Merry XMas

rsmckinney commented 2 years ago

Hi @lilumat. Smalltalk was ahead of its time :)

Looks like what you want is some type of auto-coercion. Although manifold could support this, I tend to stay clear of auto-coercion due to its history of producing unintended results.

One feature manifold offers that may be of use, however, is structural typing. If VarcharSql were a structural interface, you could implement it with String using extension methods and extension interfaces. As such, the example code you have above would work as-is.

Merry Christmas to you too!

lilumat commented 2 years ago

Hi, @rsmckinney , I made some tests but it seems that I'am a beginner with Manifold libraries :) It is simple and complex at the same time, the force of this tool !

In my future transpiler "Forms/PL-SQL to Java", all basic types will SqlNumber, SqlVarchar, ... in declaration and used for emulate the native behavior. So I tested this with compile error / runtime error ...

Test for SqlNumber

@Structural public interface SqlNumber {}

@Extension public abstract class BigDecimalExt implements SqlNumber {
   public static BigDecimal plus(@This BigDecimal thiz, BigDecimal operand) {
    return thiz.add(operand) ;
  }
}

@Test SqlNumber val1 = (SqlNumber) new BigDecimal(19); // the cast not necessary but without there is a warning on interface SqlNumber under IntelliJ "related problem" SqlNumber val2 = (SqlNumber) new BigDecimal(77); SqlNumber vador = val1 + val2 ; // <======= compile error

If I had below in SqlNumber interface :  SqlNumber plus(SqlNumber val) ;

Compile ok but error at runtime : java: java.math.BigDecimal is not abstract and does not override abstract method plus(com.airforms.runtime.core.types.SqlNumber) in com.airforms.runtime.core.types.SqlNumber

I will beleive that SqlNumber is like BigDecimal for compiler ...

Test for SqlVarchar

@Structural public interface SqlVarchar {   void sayHello(); }

@Extension public abstract class StringExt implements SqlVarchar {   public static void sayHello(@This String thiz) {     System.out.println("hello world!");   } }

@Test SqlVarchar var1 = "Manifold"; var1.sayHello(); // Error at runtime : java.lang.RuntimeException: Receiver type 'java.lang.String' does not implement a method structurally compatible with method: public abstract void com.airforms.runtime.core.types.SqlVarchar.sayHello()

I will beleive that SqlVarchar is like String for compiler ...

What I don't understand ? Maybe simply, my need is not in the scope

Regards, Thanks to read me

rsmckinney commented 2 years ago

Hi @lilumat. Your use-case has exposed an issue dealing with the trifecta of overloaded operators, extension methods, and structural typing. I have the issue fixed locally and will have a new release ready tomorrow. I also have a better solution for you involving a custom proxy. I'll update this issue with that info after the release. Thanks for reporting this!

lilumat commented 2 years ago

Hi @rsmckinney , Very good. I wait next release and your comments. Regards

rsmckinney commented 2 years ago

Note, #333 and #334 address this issue.

rsmckinney commented 2 years ago

Hi @lilumat. A new manifold release (2021.1.36) is out with fixes for this issue. A new manifold plugin release is also available (2021.x.40 & 2020.3.49) sometime Wednesday when JetBrains processes it for their Marketplace.

Note, you must provide an IProxyFactory service implementation when working with a structural interface that is implemented with extension methods, as with your example above. A later release will generate such proxies automatically, but for now they must be provided explicitly. Here is a zip file containing your project using the latest release: Issue332.zip.

Please let me know if you have questions. And thanks for reporting this!

rsmckinney commented 2 years ago

Feature #337 provides the auto-generated proxy factory, which completes the changes for this issue