0

I have a simple Scala function in which I want to increment a class variable every time a statement is executed.

    class C {
        var cnt: Int: 0

        def fun(): Unit = {
             var a: Int = 0
             var b: Int = -10
             var sum: Int = 0
             sum = a + b
             return sum
        }
    }

I want the function to be like this:

    class C {
        var cnt: Int: 0

        def fun(): Unit = {
             var a: Int = 0
             cnt = cnt + 1
             var b: Int = -10
             cnt = cnt + 1
             var sum: Int = 0
             cnt = cnt + 1
             sum = a + b
             cnt = cnt + 1
             return sum
        }
    }

But doing so at the software level makes the code messy. Can I use bytecode manipulation to implement this or I should intervene in other levels of compilation?

13leak
  • 73
  • 9
  • 2
    This looks like an XY problem. Why do you need to count the number of lines in your function? Perhaps there is an easier workaround. – user Dec 16 '20 at 16:23
  • 1
    I want to implement a logical clock for a bunch of actors in the Akka library. There is no functionality for this in the Akka Actor library. An Akka contributor suggested this so I guess there is no other way. – 13leak Dec 16 '20 at 16:35
  • 3
    A macro could do it. Scala macros are rather difficult to write, though. – Seth Tisue Dec 16 '20 at 16:42
  • What about bytecode instrumentation? I thought I can evade the difficulty by dealing with Java byte codes. @seth-tisue – 13leak Dec 16 '20 at 16:44
  • 3
    The major difficulty in bytecode manipulation would be figuring out where one statement ended and where the next began. There is a line number table in the bytecode, but lines aren't statements (e.g. `stmt1; stmt2` is 1 line, but two statements). Just from that (and that a macro actually sees statements), I suspect bytecode manipulation is going to be more difficult than a macro. A macro is also more likely to work (or at least fail the build if it doesn't) as the compiler version changes (though I'd defer to @SethTisue on that question) – Levi Ramsey Dec 16 '20 at 18:33
  • For the particular usecase of a vector clock, it also would seem to me that a statement-based clock would be suboptimal, in that I wouldn't expect _every_ statement to be actually meaningful for the clock. – Levi Ramsey Dec 16 '20 at 18:41
  • You are right. I don't need to count each statement. Counting the lines would suffice. – 13leak Dec 16 '20 at 19:10
  • 1
    I don't think that's what @LeviRamsey meant. Counting lines/statements both won't be very useful. – user Dec 16 '20 at 19:38
  • In a logical vector clock, we have to somehow count the logical steps we took in a node. Do you have any alternative suggestions for doing so? – 13leak Dec 16 '20 at 22:12
  • 3
    @13leak: "Counting the lines would suffice." – That's easy. Linebreaks are optional in Scala, you can simply replace them with semicolons. If you do that, all of your methods will always have one line. – Jörg W Mittag Dec 17 '20 at 04:25
  • I did not consider this but in this situation counting the lines wouldn't solve my problem. I have to estimate the number of logical steps. @jörg-w-mittag – 13leak Dec 17 '20 at 06:45
  • I think [this topic](https://developer.jboss.org/thread/267144) argues that detecting lines at the bytecode level is fragile regardless of Scala's structure. – 13leak Dec 17 '20 at 07:43

1 Answers1

3

I'm not sure who added the tag Byteman to this question but Byteman is not going to be able help you with this. As a previous poster said this is not really a problem that can be solved using bytecode manipulation. Bytecode has a fairly opaque link to source line and source statement boundaries and it is often not possible to derive either type of boundary from the instructions encoded in the bytecode.

A source to source translator based on a language parser would be a much better option.

  • My bad. I was not sure whether I can use byteman. Can you provide more detail about the source translator so I can accept it as the answer? – 13leak Jan 12 '21 at 15:12
  • 1
    I am afraid I don't know of any ready made source to source translators or parsers for Scala. There are lots of parser generator tools around though. Many Java programmers like Antlr, which is ok if you are happy with the verbosity of recursive descent parsing. You should be able to link an Antlr parser into Scala code and you can feed it a Backus Naur Format (BNF) grammar. Which is lucky for you as there is a Scala grammar in that format available at scala-lang.org. – Byteman Project Jan 12 '21 at 16:15