Skip to content

Add filter/withFilter method to Parser#20

Closed
dcsobral wants to merge 1 commit intoscala:masterfrom
dcsobral:parserFilter
Closed

Add filter/withFilter method to Parser#20
dcsobral wants to merge 1 commit intoscala:masterfrom
dcsobral:parserFilter

Conversation

@dcsobral
Copy link
Contributor

@dcsobral dcsobral commented Dec 2, 2011

Complements map and flatMap in for comprehensions. This is required when pattern matching is used on the
result of the generators.

It is implemented through a new filterWithError method on ParseResult.

Contributed by: Daniel C. Sobral

… when used

in for comprehensions. This is required when pattern matching is used on the
result of the generators.

It is implemented through a new filterWithError method on ParseResult.

Contributed by: Daniel C. Sobral
@paulp paulp closed this Dec 2, 2011
gkossakowski added a commit to gkossakowski/scala that referenced this pull request Jan 11, 2012
Fix wrong object initialization order.
retronym referenced this pull request in retronym/scala Jul 31, 2015
Calls to synthetic case class apply methods are inlined to the
underlying constructor invocation in refchecks.

However, this can lead to accessibility errors if the constructor
is private.

This commit ensures that the constructor is at least as accessible
as the apply method before performing this tranform.

I've manually checked that other the optimization still works in other
cases:

scala> class CaseApply { Some(42)  }
defined class CaseApply

    scala> :javap -c CaseApply
    Compiled from "<console>"
    public class CaseApply {
      public CaseApply();
        Code:
           0: aload_0
           1: invokespecial #9                  // Method java/lang/Object."<init>":()V
           4: new           #11                 // class scala/Some
           7: dup
           8: bipush        42
          10: invokestatic  #17                 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
          13: invokespecial #20                 // Method scala/Some."<init>":(Ljava/lang/Object;)V
          16: pop
          17: return
    }
retronym referenced this pull request in retronym/scala Jul 31, 2015
Calls to synthetic case class apply methods are inlined to the
underlying constructor invocation in refchecks.

However, this can lead to accessibility errors if the constructor
is private.

This commit ensures that the constructor is at least as accessible
as the apply method before performing this tranform.

I've manually checked that other the optimization still works in other
cases:

scala> class CaseApply { Some(42)  }
defined class CaseApply

    scala> :javap -c CaseApply
    Compiled from "<console>"
    public class CaseApply {
      public CaseApply();
        Code:
           0: aload_0
           1: invokespecial #9                  // Method java/lang/Object."<init>":()V
           4: new           #11                 // class scala/Some
           7: dup
           8: bipush        42
          10: invokestatic  #17                 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
          13: invokespecial #20                 // Method scala/Some."<init>":(Ljava/lang/Object;)V
          16: pop
          17: return
    }
retronym referenced this pull request in retronym/scala Dec 3, 2015
```
cat sandbox/test1.scala && javap -c -classpath . T C
trait T {
  def m = 42
}

class C extends T

object Test {
  def main(args: Array[String]): Unit = {
    val c = new C()
    assert(c.m == 42)
  }
}
Compiled from "test1.scala"
public interface T {
  public int m();
    Code:
       0: bipush        42
       2: ireturn

  public void $init$();
    Code:
       0: return
}
Compiled from "test1.scala"
public class C implements T {
  public int m();
    Code:
       0: aload_0
       1: invokespecial #14                 // Method T.m:()I
       4: ireturn

  public C();
    Code:
       0: aload_0
       1: invokespecial #20                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: invokespecial #23                 // Method T.$init$:()V
       8: return
}
```

Here's another test that shows private methods working:

```
cat sandbox/test3.scala && qscalac sandbox/test3.scala && javap -private -classpath . -c T C && qscala Test
trait T {
  private def foo = 0
  def bar = foo
}

class C extends T

object Test {
  def main(args: Array[String]): Unit = {
    new C().bar
  }
}
Compiled from "test3.scala"
public interface T {
  private int foo();
    Code:
       0: iconst_0
       1: ireturn

  public int bar();
    Code:
       0: aload_0
       1: invokespecial #15                 // Method foo:()I
       4: ireturn

  public void $init$();
    Code:
       0: return
}
Compiled from "test3.scala"
public class C implements T {
  public int bar();
    Code:
       0: aload_0
       1: invokespecial #14                 // Method T.bar:()I
       4: ireturn

  public C();
    Code:
       0: aload_0
       1: invokespecial #20                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: invokespecial #23                 // Method T.$init$:()V
       8: return
}
```
lrytz pushed a commit to lrytz/scala that referenced this pull request May 20, 2016
This corrects an error in the change to the trait encoding
in scala#5003: getters in traits should have empty bodies and
be emitted as abstract.

```
% ~/scala/2.12.0-M4/bin/scalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public int x();
    Code:
       0: aload_0
       1: invokeinterface scala#15,  1           // InterfaceMethod x:()I
       6: ireturn

  public int y();
    Code:
       0: aload_0
       1: invokeinterface scala#20,  1           // InterfaceMethod y:()I
       6: ireturn

  public void y_$eq(int);
    Code:
       0: aload_0
       1: iload_1
       2: invokeinterface scala#24,  2           // InterfaceMethod y_$eq:(I)V
       7: return

  public void $init$();
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface scala#29,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface scala#24,  2           // InterfaceMethod y_$eq:(I)V
      16: return
}

% qscalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public abstract int x();

  public abstract int y();

  public abstract void y_$eq(int);

  public static void $init$(T);
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface scala#21,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface scala#23,  2           // InterfaceMethod y_$eq:(I)V
      16: return

  public void $init$();
    Code:
       0: aload_0
       1: invokestatic  scala#27                 // Method $init$:(LT;)V
       4: return
}
```
lrytz pushed a commit to lrytz/scala that referenced this pull request May 25, 2016
This corrects an error in the change to the trait encoding
in scala#5003: getters in traits should have empty bodies and
be emitted as abstract.

```
% ~/scala/2.12.0-M4/bin/scalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public int x();
    Code:
       0: aload_0
       1: invokeinterface scala#15,  1           // InterfaceMethod x:()I
       6: ireturn

  public int y();
    Code:
       0: aload_0
       1: invokeinterface scala#20,  1           // InterfaceMethod y:()I
       6: ireturn

  public void y_$eq(int);
    Code:
       0: aload_0
       1: iload_1
       2: invokeinterface scala#24,  2           // InterfaceMethod y_$eq:(I)V
       7: return

  public void $init$();
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface scala#29,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface scala#24,  2           // InterfaceMethod y_$eq:(I)V
      16: return
}

% qscalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public abstract int x();

  public abstract int y();

  public abstract void y_$eq(int);

  public static void $init$(T);
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface scala#21,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface scala#23,  2           // InterfaceMethod y_$eq:(I)V
      16: return

  public void $init$();
    Code:
       0: aload_0
       1: invokestatic  scala#27                 // Method $init$:(LT;)V
       4: return
}
```
lrytz pushed a commit to lrytz/scala that referenced this pull request Jun 6, 2016
This corrects an error in the change to the trait encoding
in scala#5003: getters in traits should have empty bodies and
be emitted as abstract.

```
% ~/scala/2.12.0-M4/bin/scalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public int x();
    Code:
       0: aload_0
       1: invokeinterface scala#15,  1           // InterfaceMethod x:()I
       6: ireturn

  public int y();
    Code:
       0: aload_0
       1: invokeinterface scala#20,  1           // InterfaceMethod y:()I
       6: ireturn

  public void y_$eq(int);
    Code:
       0: aload_0
       1: iload_1
       2: invokeinterface scala#24,  2           // InterfaceMethod y_$eq:(I)V
       7: return

  public void $init$();
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface scala#29,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface scala#24,  2           // InterfaceMethod y_$eq:(I)V
      16: return
}

% qscalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public abstract int x();

  public abstract int y();

  public abstract void y_$eq(int);

  public static void $init$(T);
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface scala#21,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface scala#23,  2           // InterfaceMethod y_$eq:(I)V
      16: return

  public void $init$();
    Code:
       0: aload_0
       1: invokestatic  scala#27                 // Method $init$:(LT;)V
       4: return
}
```
lrytz pushed a commit that referenced this pull request Jun 29, 2016
This corrects an error in the change to the trait encoding
in #5003: getters in traits should have empty bodies and
be emitted as abstract.

```
% ~/scala/2.12.0-M4/bin/scalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public int x();
    Code:
       0: aload_0
       1: invokeinterface #15,  1           // InterfaceMethod x:()I
       6: ireturn

  public int y();
    Code:
       0: aload_0
       1: invokeinterface #20,  1           // InterfaceMethod y:()I
       6: ireturn

  public void y_$eq(int);
    Code:
       0: aload_0
       1: iload_1
       2: invokeinterface #24,  2           // InterfaceMethod y_$eq:(I)V
       7: return

  public void $init$();
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface #29,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface #24,  2           // InterfaceMethod y_$eq:(I)V
      16: return
}

% qscalac sandbox/test.scala && javap -c T
Compiled from "test.scala"
public interface T {
  public abstract void T$_setter_$x_$eq(int);

  public abstract int x();

  public abstract int y();

  public abstract void y_$eq(int);

  public static void $init$(T);
    Code:
       0: aload_0
       1: bipush        42
       3: invokeinterface #21,  2           // InterfaceMethod T$_setter_$x_$eq:(I)V
       8: aload_0
       9: bipush        24
      11: invokeinterface #23,  2           // InterfaceMethod y_$eq:(I)V
      16: return

  public void $init$();
    Code:
       0: aload_0
       1: invokestatic  #27                 // Method $init$:(LT;)V
       4: return
}
```
OlivierBlanvillain pushed a commit to OlivierBlanvillain/scala that referenced this pull request Jun 27, 2017
szeiger pushed a commit to szeiger/scala that referenced this pull request Mar 20, 2018
da-liii pushed a commit to da-liii/scala that referenced this pull request Nov 11, 2018
lrytz pushed a commit to lrytz/scala that referenced this pull request Feb 19, 2026
Motivation is to remove avoidable synthetic branches/instructions
for null data that are intepreted as uncovered code by JaCoCo etc.

Bytecode is also reduced.

Note that if either operand is potential `Number` or `Character`,
the backend delegates to `BoxesRuntime.equals` which handles Scala
semantic edge cases for boxed primitives. This PR does not change
that at all.

Before:

```
  public boolean test1(java.lang.String, java.lang.String);
    descriptor: (Ljava/lang/String;Ljava/lang/String;)Z
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=3
         0: aload_1
         1: aload_2
         2: astore_3
         3: dup
         4: ifnonnull     15
         7: pop
         8: aload_3
         9: ifnull        22
        12: goto          26
        15: aload_3
        16: invokevirtual scala#20                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
        19: ifeq          26
        22: iconst_1
        23: goto          27
        26: iconst_0
        27: ireturn
```

After

```
  public boolean test1(java.lang.String, java.lang.String);
    descriptor: (Ljava/lang/String;Ljava/lang/String;)Z
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=3
         0: aload_1
         1: aload_2
         2: invokestatic  scala#22                 // Method java/util/Objects.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z
         5: ifeq          12
         8: iconst_1
         9: goto          13
        12: iconst_0
        13: ireturn
```
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