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

Re-assign enclosing object properties to local vals. #21

Closed
3 tasks done
aalexandrov opened this issue Apr 30, 2015 · 11 comments
Closed
3 tasks done

Re-assign enclosing object properties to local vals. #21

aalexandrov opened this issue Apr 30, 2015 · 11 comments
Assignees
Milestone

Comments

@aalexandrov
Copy link
Contributor

Code bracketed with parallelize is normalized as a first step of the compiler chain.

As part of the normalization

For example, in the following code example the "parallelized" code accesses k.

class KMeans(val k) {

  def g(x: Int): Int = x + 42

  var u = 0

  def run() = {
    val alg = emma.parallelize {
      val z = f(k) // OK as f is not a local method
      val w = g(k) // not OK as g is local method
      // ...
      xs.map(x => { /* ... */; u = u + 1; /* ... */ } // not OK as u is local state
    }
  } 
}

As part of the normalization, the code should be rewritten as:

      val __this$k = k
      val z = f(__this$k)
      // ...
@aalexandrov aalexandrov added this to the Week 20 2015 milestone Apr 30, 2015
@aalexandrov aalexandrov changed the title Re-assign enclosing object properties to local vars. Re-assign enclosing object properties to local vals. Apr 30, 2015
@joroKr21
Copy link
Member

joroKr21 commented May 5, 2015

What is the difference between a read / write property of the class and a method? In Scala those are one and the same. Isn't it possible to inline those instead of renaming them?

@aalexandrov
Copy link
Contributor Author

I think that in the following class

class Foo {
  val Int x = 0
  def x: Int = x
}

The first member is a property and the second a method. Regarding inlining, I am not sure whether you can get hold on the method definition from the macro context in order to do the inlining. Moreover, using methods (like the x getter) inside UDFs in systems like Flink and Spark might be problematic if the enclosing object is not serializable.

I would therefore restrict the use of enclosing object methods in the first step and focus only on the properties.

@joroKr21
Copy link
Member

joroKr21 commented May 5, 2015

I meant inlining their value, but I guess we don't know it at compile time. My point is that at the call site we cannot distinguish between vals, vars and defs with no arguments, as they are all represented as Selects in the AST. To do that you would have to access the enclosing class definition, which I guess is possible, but goes against the principles of locality.

On the other hand, why restrict access to no-argument methods, when they shouldn't have side effects anyway? At the same time it's easy enough to prohibit calls to methods with arguments.

@aalexandrov
Copy link
Contributor Author

You can lookup the exact type of a select (val, var, def) through its symbol.

@joroKr21
Copy link
Member

joroKr21 commented May 6, 2015

Yes indeed, I still have a lot to learn about the Scala reflection API. You can just use isStable then.

@aalexandrov
Copy link
Contributor Author

Didn't know about that method, good hint!

@aalexandrov aalexandrov modified the milestones: Week 20 2015, Week 21 2015 May 19, 2015
@aalexandrov aalexandrov modified the milestones: Week 21 2015, Week 24 2015, Week 25 2015 Jun 17, 2015
@aalexandrov aalexandrov modified the milestones: Week 25 2015, Week 27 2015 Jun 29, 2015
@aalexandrov aalexandrov modified the milestones: Week 27 2015, Week 28 2015 Jul 7, 2015
@aalexandrov aalexandrov removed this from the Week 27 2015 milestone Jul 7, 2015
@aalexandrov aalexandrov modified the milestones: Week 28 2015, Week 29 2015 Jul 17, 2015
@aalexandrov aalexandrov assigned ParkL and unassigned andi3 Jan 6, 2016
@joroKr21
Copy link
Member

joroKr21 commented Jan 8, 2016

@ParkL I just realized that it doesn't matter if you get Outer.this.x = 42 or Outer.this.x_=(42) in the macro since calling a method of the enclosing class should also be prohibited unless it isStable.

@ParkL
Copy link
Contributor

ParkL commented Jan 8, 2016

@joroKr21 Will do! Thanks for the advice! I'm new to the whole thing so all help is greatly appreciated :) I guess there's even more cases to think about ...

Andreas and I just found out one more thing that's weird (at least to me), but it may be a hint at the underlying problem: If I paste my test-quasiquote (with the assignment) into the scala console it renders as expected with an Assign. If I set a breakpoint at doSemanticChecks(e.tree) and run the test in debug mode, inspecting e.tree yields the weird Apply structure. So something is happening to the tree "in between".

If this rings a bell, please let me know. Anyway I'll be looking into this on Monday! Have a nice weekend!

@aalexandrov
Copy link
Contributor Author

@ParkL This might be something for the scala macros mailing list / JIRA.

@joroKr21
Copy link
Member

joroKr21 commented Jan 8, 2016

What happens in between is typechecking that resolves the assignment to the compiler-generated setter x_=. To see this effect in the REPL:

import scala.reflect.runtime.universe._
import scala.reflect.runtime.currentMirror
import scala.tools.reflect.ToolBox
val tb = currentMirror.mkToolBox()
val code = q"class Outer { var x = 1; class Inner { x = 2 } }"
showCode(code)
showCode(tb.typecheck(code))

In contrast method- or block-local vars remain assignments, which I guess is why they differentiate between these cases.

@joroKr21 joroKr21 added this to the Jan 2016 milestone Jan 18, 2016
@joroKr21
Copy link
Member

Resolved via 04032bd and #141

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

No branches or pull requests

4 participants