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

Add Functional features #42

Closed
wants to merge 100 commits into from
Closed

Add Functional features #42

wants to merge 100 commits into from

Conversation

StefanosChaliasos
Copy link
Collaborator

@StefanosChaliasos StefanosChaliasos commented Jul 28, 2021

This PR adds support for functional features such as lambdas and function references.

Specifically, it enhances the generator with capabilities for producing lambdas and function references. Furthermore, the generator can use function references to perform function calls.

The following example illustrates the capabilities of the features added in this PR.

class Main {
  static public final Double chiseled(Short regards) {
    final Double trusties = 7.900;
    return trusties;
  }

  public static void main(String[] args) {
    Function0<Double> tuners = (rimmed) -> {
      Double honest = 100.478;
      return honest;
    };
    var x = tuners.apply(4);
  }
}

interface Function0<R> {
  public R apply();
}

interface Function1<A1, R> {
  public R apply(A1 a1);
}

abstract class Leland {
  public final Character geneva;

  public Leland(Character geneva) {
    this.geneva = geneva;
  }

  public Function3<? super Short, Double> somebody() {
    Function3<? super Short, Double> blackwell = Main::chiseled;
    return blackwell;
  }
}

Changes

  • Adds --examine option that must be combined with -R to examine the AST of the produced program through ipdb.
  • Adds logger to the generator.
  • Adds Lambda expression in AST. Lambda includes a field called name, which is used for internal purposes in the context.
  • Adds FunctionReference expression in AST. This node contains a function name and a receiver expression. The receiver could be an expression such as a variable or a new containing the function.
  • Adds get_signature in FunctionDeclaration. This method returns a parameterized class type that represents the signature of a function.
  • Adds FunctionType in builtin types. Function type represents the type contructor for function signatures.
  • Introduces a new field in the context for lambdas. This field contains all lambda declarations.
  • Adds support for FunctionReferences and Lambdas in get_type_hint.
  • Adds is_function_type method to ParameterizedType.
  • Updates the translators.
  • Enhance the generator to produce Lambdas, FunctionReferencess, and perform function calls by exploiting function references.
  • Adds _namespace dict in context to get the namespace of a declaration by using get_namespace.
  • Adds get_parent in context

Notes on generator

In the generator we updated gen_new to produce FunctionReferences and Lambdas. To do so, we have created the following functions.

  • gen_func_ref: It tries to create a FunctionDeclaration for a given function signature, and if succeeds, it returns a FunctionReference to that function.
  • get_func_refs: It finds all FunctionReferences that can be use to return a specific type.
  • gen_lambda: Produces a Lambda expression.

We also updated gen_func_call to call _gen_func_call_ref that creates a function call through a FunctionReference.

TODOs

  • Handle functions of parameterized classes in get_func_refs. For instance, consider that we have the following class, and we search for functions with Function1<Integer, Integer> as a signature.
class A<T> {
	A foo(A a) {return a;}
}

Currently, we won't detect that the foo function can implement the Function1<Integer, Integer> signature.

  • Detect receivers in get_func_refs. We won't detect that we can use a::foo when searching for a function with Function0<Integer> signature in the following example.
class A {
	Integer foo() {return 1;}
}

public static void main(String[] args) {
	A a = new A();
}
  • Adapt generator to create more SAMs and use function reference or lambdas instead of SAM objects.
fun interface IntPredicate {
   fun accept(i: Int): Boolean
}

fun test(f: IntPredicate) {}

fun f() {
   test({ it: Int -> it % 2 == 0 })
}
  • Implement PECS for variance in Functions.
  • Stress test Java
  • Stress test Kotlin
    • update translator
  • Stress test Groovy
    • update translator

We use shadow_name for namespaces internally.
We should first try to find a function with the appropriate signature
for producing a function reference.

There are some issues with the lambdas we create:

1. Wrong signatures when using variance
2. Wrong lambdas in conditionals
@StefanosChaliasos
Copy link
Collaborator Author

StefanosChaliasos commented Sep 24, 2021

Java known errors

In 2000 programs 74 fail (26 are programming errors and 48 are javac issues marked as not an issue).

False positives

7/4000

  • incompatible types: Function1<CAP#1,CAP#2> cannot be converted to Function1<Ashlee,? extends Integer> this happens because in Java we cannot use var inference with function types. As a result, we use get_type_hint in translator to get the type of a conditional which returns the wrong type because find_lub returns the wrong result (1/4000).

Example

final Function1<Ashlee, ? extends Integer> remedies = Main::falloffs;
final Function1<? super Ashlee, ? extends Integer> greenland = remedies;
Function1<? super Ashlee, ? extends Integer> x_7 = ((boxer) ?
  remedies :
   greenland);
  • incompatible types: bad type in conditional expression: Main::strength); ... Object is not a functional interface same with the above. It will be fixed if we implement fund_lub correctly (4/4000).

  • error: local variables referenced from a lambda expression must be final or effectively final -- there should be an issue with _inside_java_lambda somewhere in the generator (1/4000).

  • cannot find symbol ... symbol: class A -- Probably an issue in gen_lambda or the generator in general (1/4000).

Marked as not an issue

41/4000

  • type argument ? extends Function2<Float,Float,Float> is not within bounds of type-variable G -- JDK-8269586 (41/4000)
  • incompatible types: Showery<CAP#1> cannot be converted to Showery<? super Character> -- JDK-8269386 (0/4000)

@StefanosChaliasos
Copy link
Collaborator Author

StefanosChaliasos commented Sep 27, 2021

Groovy known errors

Between 40% and 50% of the programs fail with the error message: The type ? is not a valid substitute for the bounded parameter ....

If we disable the feature that triggers the above bug, we have:

groovyc errors

  • Cannot assign value of type T to variable of type Z GROOVY-10268
  • Cannot assign value of type java.lang.Number<? extends java.lang.Number<java.math.BigDecimal>> -- BigDecimal and Double in ternary, similar to GROOVY-10081
  • Cannot assign value of type java.lang.Object to variable of type java.util.function.Supplier<java.lang.Integer> -- Lambda + ternary inference
  • Incompatible generic argument types. Cannot assign groovy.lang.Closure<java.lang.Long> to: java.util.function.Function<java.lang.Byte, java.lang.Long> -- var inference with Function Type, in Java this is not permitted and it reports an error when you assign something of a function type to var.
  • Cannot find matching method int#call(groovy.lang.Closure) GROOVY-10265 -- parsing error
  • Possible loss of precision from int to byte GROOVY-10081
  • Stackoverflow GROOVY-10269

@StefanosChaliasos
Copy link
Collaborator Author

@theosotr I think this PR is ready. There are a few issues like the LUB computation, but we can fix them later. Regarding Groovy, almost half of the programs fail to compile (I haven't found an FP yet, I collect the bugs to a backlog). I believe that #45 will help us to better testing groovyc.

@StefanosChaliasos
Copy link
Collaborator Author

StefanosChaliasos commented Nov 3, 2021

This PR was merged through integration

@StefanosChaliasos StefanosChaliasos deleted the functional-features branch November 3, 2021 16:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants