Access code file and line number from Scala macro? - scala

How can I access the name of the code file and line number in a Scala macro? I looked at SIP-19 and it says it can be easily implemented using macros...
EDIT:
To clarify, I want the code file and line number of the caller. I already have a debug macro and I want to modify it to print the line number and file name of whoever calls debug

You want c.macroApplication.pos, where c is for Context.
c.enclosingPosition finds the nearest macro on the stack that has a position. (See the other answer.) For instance, if your assert macro generates a tree for F"%p: $msg" but doesn't assign a position, the F macro would be positionless.
Example from a string interpolator macro, F"%p":
/* Convert enhanced conversions to something format likes.
* %Q for quotes, %p for position, %Pf for file, %Pn line number,
* %Pc column %Po offset.
*/
private def downConvert(parts: List[Tree]): List[Tree] = {
def fixup(t: Tree): Tree = {
val Literal(Constant(s: String)) = t
val r = "(?<!%)%(p|Q|Pf|Po|Pn|Pc)".r
def p = c.macroApplication.pos
def f(m: Match): String = m group 1 match {
case "p" => p.toString
case "Pf" => p.source.file.name
case "Po" => p.point.toString
case "Pn" => p.line.toString
case "Pc" => p.column.toString
case "Q" => "\""
}
val z = r.replaceAllIn(s, f _)
Literal(Constant(z)) //setPos t.pos
}
parts map fixup
}

If you mean file name and line number of the current position in the source code, for 2.10, my answer to that SO question is what your looking for:
def $currentPosition:String = macro _currentPosition
def _currentPosition(c:Context):c.Expr[String]={ import c.universe._
val pos = c.enclosingPosition
c.Expr(Literal(Constant(s"${pos.source.path}: line ${pos.line}, column ${pos.column}")))
}
That should work with 2.11 as well, although this way of creating the AST seems deprecated.
You can also have a look at that excerpt of my project Scart; it's how I use this technique to emit traces for debugging purposes.

The example in 'Writing Scala Compiler Plugins' shows how to access the line name and current number of the current position, as the others answers have mentioned.
http://www.scala-lang.org/old/node/140
In addition to the answers above, you can also get the position from the AST returned from a CompilationUnit.
For example:
def apply(unit: CompilationUnit) {
// Get the AST
val tree = unit.body
// Get the Position
// Scala.util.parsing.input.Position
val myPos = tree.pos
// Do something with the pos
unit.warning(pos, "Hello world")
}

Related

Macro expansion contains free variable

My code compiles with the following error: Macro expansion contains free term variable Hello ...
I have reduced it to minimal example:
class Hello(val hi: String) {
val xx = reify(hi)
var yy = q""
}
def setYYImpl(c: Context)(hExpr: c.Expr[Hello]): c.Expr[Hello] = {
import c.universe._
val hello = c.eval(c.Expr[Hello](c.untypecheck(hExpr.tree.duplicate)))
val xxVal = c.internal.createImporter(u).importTree(hello.xx.tree)
c.Expr(q"""{val h = new Hello("HO"); h.yy=$xxVal; h}""") // it should set `h.yy` to Tree:"HO"
}
def setYY(hExpr: Hello): Hello = macro setYYImpl
setYY(new Hello("HI"))
After inspecting similar question: Can this free-term-variable error (produced at macro expansion) be avoided?
I have come to conclusion that the problem is reify(hi) which refers to the compile time value Hello.hi.
Is it possible to work around this problem? reify(hi) returns Expr Hello.hi, can I somehow remove the Hello. prefix?
Try to replace
val xx = reify(hi)
with
val xx = Literal(Constant(hi))
i.e. build the tree manually (and
.importTree(hello.xx.tree)
with
.importTree(hello.xx)).
(If it's Literal(Constant... only in your example and more complex tree in actual use case, anyway try to build it manually rather than use reify.)
Then you'll have different error
Error: type mismatch;
found : String("HI")
required: reflect.runtime.universe.Tree
setYY(new Hello("HI"))
because your macro returns
Expr[Hello]({
val h = new Hello("HO");
h.yy = "HI"; // h.yy is q"" i.e. Tree, "HI" is String
h
})

Get syntax string from runtime in scala [duplicate]

I want to do something like this:
def assuming[A](condition: => Boolean)(f: => A): A = {
require(condition, /* print source-code of condition */)
f
}
Sample usage:
def fib(n: Int) = n match { // yes, yes, I know this is not efficient
case 0 => 0
case 1 => 1
case i => assuming(i > 0) { fib(i-1) + fib(i-2) }
}
Now, for example, if you call fib(-20), I want it to throw an exception with a message like Assertion failed: -20 > 0 or Assertation failed: i > 0
Dude, isn't an assert macro one of the basic use cases you implement to learn how to use macros?
Well, that's what I thought, too.
By "glean snippets" in my other answer I meant what specs2 does in its s2 macro.
Or, you can do an arbitrary representation, as in my variant rip-off of expecty.
I thought I'd type your example into REPL, in a couple of lines. After all, you're just trying to print the snippet from the source that corresponds to the tree representing your conditional.
What could be easier?
Of course, it's easier under -Yrangepos, but we can postulate positions.
I'm willing to share how far I got before I lost interest.
People (e.g., paulp, who is the vox paulpuli) want trees to have attachments representing "the source I typed on my keyboard", because, you know, maybe I want it for a message or to figure out what the user was trying to accomplish.
It looks like the predicate p doesn't have a range position. So the other idea is that we know the start of the macro application, which is the paren of the second param list, so working backward through the source, matching the closing paren of the first param list, is doable.
Note that showCode isn't helpful because for a conditional like 10 < 5 it shows false, neatly folded.
object X {
import reflect.macros.blackbox.Context
def impl[A: c.WeakTypeTag](c: Context)(p: c.Expr[Boolean])(body: c.Expr[A]) = {
import c.universe._
def treeLine(t: Tree): String = lineAt(t.pos)
def lineAt(pos: Position): String = if (pos.isRange) pos.lineContent.drop(pos.column - 1).take(pos.end - pos.start + 1) else "???"
val msg =
if (p.tree.pos.isRange) { // oh, joy
treeLine(p.tree)
} else {
/*
Console println s"content ${p.tree.pos.lineContent}"
Console println s"column ${p.tree.pos.column}" // alas, that's the column of the point of the top of the tree, e.g., < in "a < b".
val len = body.tree.pos.start - p.tree.pos.start
p.tree.pos.lineContent drop (p.tree.pos.column - 1) take len
*/
// OK, I get it: positions are a big mystery. Make woo-woo ghost noises.
// What we do know is the start of the apply, which must have a close paren or brace in front of it to match:
// apply(condition)(body)
showCode(p.tree)
}
q"require($p, $msg) ; $body"
}
def x[A](p: Boolean)(body: =>A): A = macro X.impl[A]
}
It just occurred to me to get the rangy position this way:
object X {
import reflect.macros.blackbox.Context
def impl(c: Context)(p: c.Expr[Boolean]) = {
import c.universe._
def lineAt(pos: Position): String = if (pos.isRange) pos.lineContent.drop(pos.column - 1).take(pos.end - pos.start + 1) else "???"
val msg = lineAt(c.macroApplication.pos) // oh, joy
q"require($p, $msg) ; new { def apply[A](body: =>A): A = body }"
}
def x(p: Boolean): { def apply[A](body: =>A): A } = macro X.impl
}
That's close on usage x(10 < 5)(println("hi")): requirement failed: (10 < 5)(p. Margin for error.
Have you consulted the docs at:
http://www.scala-lang.org/api/2.11.0/scala-reflect/#scala.reflect.api.Printers
scala> show(q"-1 < 0")
res6: String = -1.$less(0)
scala> showCode(q"-1 < 0")
res7: String = (-1).<(0)
Alternatively, folks have used source positions to glean snippets to print.
If you are using Scala 2.11.x the best way to go is the showCode method. This method will correctly print an arbitrary Scala tree. For example:
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
showCode(q"3.14 < 42")
res1: String = 3.14.<(42)
In the previous versions of Scala you would have to use the method show which does not guarantee correctness:
scala> show(q"3.14 < 42")
res2: String = 3.14.$less(42)
The method showCode was designed with correctness in mind so it will not necessarily print beautiful code. If beauty is of importance for you can either contribute to the Scala Printers or you can write your own printer. Another interesting printer for Scala trees is the PrettyPrinter from Scala Refactoring.

How to read input from a file and convert data lines of the file to List[Map[Int,String]] using scala?

My Query is, read input from a file and convert data lines of the file to List[Map[Int,String]] using scala. Here I give a dataset as the input. My code is,
def id3(attrs: Attributes,
examples: List[Example],
label: Symbol
) : Node = {
level = level+1
// if all the examples have the same label, return a new node with that label
if(examples.forall( x => x(label) == examples(0)(label))){
new Leaf(examples(0)(label))
} else {
for(a <- attrs.keySet-label){ //except label, take all attrs
("Information gain for %s is %f".format(a,
informationGain(a,attrs,examples,label)))
}
// find the best splitting attribute - this is an argmax on a function over the list
var bestAttr:Symbol = argmax(attrs.keySet-label, (x:Symbol) =>
informationGain(x,attrs,examples,label))
// now we produce a new branch, which splits on that node, and recurse down the nodes.
var branch = new Branch(bestAttr)
for(v <- attrs(bestAttr)){
val subset = examples.filter(x=> x(bestAttr)==v)
if(subset.size == 0){
// println(levstr+"Tiny subset!")
// zero subset, we replace with a leaf labelled with the most common label in
// the examples
val m = examples.map(_(label))
val mostCommonLabel = m.toSet.map((x:Symbol) => (x,m.count(_==x))).maxBy(_._2)._1
branch.add(v,new Leaf(mostCommonLabel))
}
else {
// println(levstr+"Branch on %s=%s!".format(bestAttr,v))
branch.add(v,id3(attrs,subset,label))
}
}
level = level-1
branch
}
}
}
object samplet {
def main(args: Array[String]){
var attrs: sample.Attributes = Map()
attrs += ('0 -> Set('abc,'nbv,'zxc))
attrs += ('1 -> Set('def,'ftr,'tyh))
attrs += ('2 -> Set('ghi,'azxc))
attrs += ('3 -> Set('jkl,'fds))
attrs += ('4 -> Set('mno,'nbh))
val examples: List[sample.Example] = List(
Map(
'0 -> 'abc,
'1 -> 'def,
'2 -> 'ghi,
'3 'jkl,
'4 -> 'mno
),
........................
)
// obviously we can't use the label as an attribute, that would be silly!
val label = 'play
println(sample.try(attrs,examples,label).getStr(0))
}
}
But How I change this code to - accepting input from a .csv file?
I suggest you use Java's io / nio standard library to read your CSV file. I think there is no relevant drawback in doing so.
But the first question we need to answer is where to read the file in the code? The parsed input seems to replace the value of examples. This fact also hints us what type the parsed CSV input must have, namely List[Map[Symbol, Symbol]]. So let us declare a new class
class InputFromCsvLoader(charset: Charset = Charset.defaultCharset()) {
def getInput(file: Path): List[Map[Symbol, Symbol]] = ???
}
Note that the Charset is only needed if we must distinguish between differently encoded CSV-files.
Okay, so how do we implement the method? It should do the following:
Create an appropriate input reader
Read all lines
Split each line at the comma-separator
Transform each substring into the symbol it represents
Build a map from from the list of symbols, using the attributes as key
Create and return the list of maps
Or expressed in code:
class InputFromCsvLoader(charset: Charset = Charset.defaultCharset()) {
val Attributes = List('outlook, 'temperature, 'humidity, 'wind, 'play)
val Separator = ","
/** Get the desired input from the CSV file. Does not perform any checks, i.e., there are no guarantees on what happens if the input is malformed. */
def getInput(file: Path): List[Map[Symbol, Symbol]] = {
val reader = Files.newBufferedReader(file, charset)
/* Read the whole file and discard the first line */
inputWithHeader(reader).tail
}
/** Reads all lines in the CSV file using [[java.io.BufferedReader]] There are many ways to do this and this is probably not the prettiest. */
private def inputWithHeader(reader: BufferedReader): List[Map[Symbol, Symbol]] = {
(JavaConversions.asScalaIterator(reader.lines().iterator()) foldLeft Nil.asInstanceOf[List[Map[Symbol, Symbol]]]){
(accumulator, nextLine) =>
parseLine(nextLine) :: accumulator
}.reverse
}
/** Parse an entry. Does not verify the input: If there are less attributes than columns or vice versa, zip creates a list of the size of the shorter list */
private def parseLine(line: String): Map[Symbol, Symbol] = (Attributes zip (line split Separator map parseSymbol)).toMap
/** Create a symbol from a String... we could also check whether the string represents a valid symbol */
private def parseSymbol(symbolAsString: String): Symbol = Symbol(symbolAsString)
}
Caveat: Expecting only valid input, we are certain that the individual symbol representations do not contain the comma-separation character. If this cannot be assumed, then the code as is would fail to split certain valid input strings.
To use this new code, we could change the main-method as follows:
def main(args: Array[String]){
val csvInputFile: Option[Path] = args.headOption map (p => Paths get p)
val examples = (csvInputFile map new InputFromCsvLoader().getInput).getOrElse(exampleInput)
// ... your code
Here, examples uses the value exampleInput, which is the current, hardcoded value of examples if no input argument is specified.
Important: In the code, all error handling has been omitted for convenience. In most cases, errors can occur when reading from files and user input must be considered invalid, so sadly, error handling at the boundaries of your program is usally not optional.
Side-notes:
Try not to use null in your code. Returning Option[T] is a better option than returning null, because it makes "nullness" explicit and provides static safety thanks to the type-system.
The return-keyword is not required in Scala, as the last value of a method is always returned. You can still use the keyword if you find the code more readable or if you want to break in the middle of your method (which is usually a bad idea).
Prefer val over var, because immutable values are much easier to understand than mutable values.
The code will fail with the provided CSV string, because it contains the symbols TRUE and FALSE which are not legal according to your programs logic (they should be true and false instead).
Add all information to your error-messages. Your error message only tells me what that a value for the attribute 'wind is bad, but it does not tell me what the actual value is.
Read a csv file ,
val datalines = Source.fromFile(filepath).getLines()
So this datalines contains all the lines from the csv file.
Next, convert each line into a Map[Int,String]
val datamap = datalines.map{ line =>
line.split(",").zipWithIndex.map{ case (word, idx) => idx -> word}.toMap
}
Here, we split each line with ",". Then construct a map with key as column number and value as each word after the split.
Next, If we want List[Map[Int,String]],
val datamap = datalines.map{ line =>
line.split(",").zipWithIndex.map{ case (word, idx) => idx -> word}.toMap
}.toList

Scala macro to print code?

I want to do something like this:
def assuming[A](condition: => Boolean)(f: => A): A = {
require(condition, /* print source-code of condition */)
f
}
Sample usage:
def fib(n: Int) = n match { // yes, yes, I know this is not efficient
case 0 => 0
case 1 => 1
case i => assuming(i > 0) { fib(i-1) + fib(i-2) }
}
Now, for example, if you call fib(-20), I want it to throw an exception with a message like Assertion failed: -20 > 0 or Assertation failed: i > 0
Dude, isn't an assert macro one of the basic use cases you implement to learn how to use macros?
Well, that's what I thought, too.
By "glean snippets" in my other answer I meant what specs2 does in its s2 macro.
Or, you can do an arbitrary representation, as in my variant rip-off of expecty.
I thought I'd type your example into REPL, in a couple of lines. After all, you're just trying to print the snippet from the source that corresponds to the tree representing your conditional.
What could be easier?
Of course, it's easier under -Yrangepos, but we can postulate positions.
I'm willing to share how far I got before I lost interest.
People (e.g., paulp, who is the vox paulpuli) want trees to have attachments representing "the source I typed on my keyboard", because, you know, maybe I want it for a message or to figure out what the user was trying to accomplish.
It looks like the predicate p doesn't have a range position. So the other idea is that we know the start of the macro application, which is the paren of the second param list, so working backward through the source, matching the closing paren of the first param list, is doable.
Note that showCode isn't helpful because for a conditional like 10 < 5 it shows false, neatly folded.
object X {
import reflect.macros.blackbox.Context
def impl[A: c.WeakTypeTag](c: Context)(p: c.Expr[Boolean])(body: c.Expr[A]) = {
import c.universe._
def treeLine(t: Tree): String = lineAt(t.pos)
def lineAt(pos: Position): String = if (pos.isRange) pos.lineContent.drop(pos.column - 1).take(pos.end - pos.start + 1) else "???"
val msg =
if (p.tree.pos.isRange) { // oh, joy
treeLine(p.tree)
} else {
/*
Console println s"content ${p.tree.pos.lineContent}"
Console println s"column ${p.tree.pos.column}" // alas, that's the column of the point of the top of the tree, e.g., < in "a < b".
val len = body.tree.pos.start - p.tree.pos.start
p.tree.pos.lineContent drop (p.tree.pos.column - 1) take len
*/
// OK, I get it: positions are a big mystery. Make woo-woo ghost noises.
// What we do know is the start of the apply, which must have a close paren or brace in front of it to match:
// apply(condition)(body)
showCode(p.tree)
}
q"require($p, $msg) ; $body"
}
def x[A](p: Boolean)(body: =>A): A = macro X.impl[A]
}
It just occurred to me to get the rangy position this way:
object X {
import reflect.macros.blackbox.Context
def impl(c: Context)(p: c.Expr[Boolean]) = {
import c.universe._
def lineAt(pos: Position): String = if (pos.isRange) pos.lineContent.drop(pos.column - 1).take(pos.end - pos.start + 1) else "???"
val msg = lineAt(c.macroApplication.pos) // oh, joy
q"require($p, $msg) ; new { def apply[A](body: =>A): A = body }"
}
def x(p: Boolean): { def apply[A](body: =>A): A } = macro X.impl
}
That's close on usage x(10 < 5)(println("hi")): requirement failed: (10 < 5)(p. Margin for error.
Have you consulted the docs at:
http://www.scala-lang.org/api/2.11.0/scala-reflect/#scala.reflect.api.Printers
scala> show(q"-1 < 0")
res6: String = -1.$less(0)
scala> showCode(q"-1 < 0")
res7: String = (-1).<(0)
Alternatively, folks have used source positions to glean snippets to print.
If you are using Scala 2.11.x the best way to go is the showCode method. This method will correctly print an arbitrary Scala tree. For example:
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
showCode(q"3.14 < 42")
res1: String = 3.14.<(42)
In the previous versions of Scala you would have to use the method show which does not guarantee correctness:
scala> show(q"3.14 < 42")
res2: String = 3.14.$less(42)
The method showCode was designed with correctness in mind so it will not necessarily print beautiful code. If beauty is of importance for you can either contribute to the Scala Printers or you can write your own printer. Another interesting printer for Scala trees is the PrettyPrinter from Scala Refactoring.

How to use scalax.io.CommandLineParser?

I want to create a class that takes string array as a constructor argument and has command line option values as members vals. Something like below, but I don't understand how the Bistate works.
import scalax.data._
import scalax.io.CommandLineParser
class TestCLI(arguments: Array[String]) extends CommandLineParser {
private val opt1Option = new Flag("p", "print") with AllowAll
private val opt2Option = new Flag("o", "out") with AllowAll
private val strOption = new StringOption("v", "value") with AllowAll
private val result = parse(arguments)
// true or false
val opt1 = result(opt1Option)
val opt2 = result(opt2Option)
val str = result(strOption)
}
Here are shorter alternatives to that pattern matching to get a boolean:
val opt1 = result(opt1Option).isInstanceOf[Positive[_]]
val opt2 = result(opt2Option).posValue.isDefined
The second one is probably better. The field posValue is an Option (there's negValue as well). The method isDefined from Option tells you whether it is a Some(x) or None.
I'm not personally familiar with Scalax or Bistate in particular, but just looking at the scaladocs, it looks like a left-right disjunction. Scala's main library has a monad very much like this (Either), so I'm surprised that they didn't just use the standard one.
In essence, Bistate and Either are a bit like Option, except their "None-equivalent" can contain a value. For example, if I were writing code using Either, I might do something like this:
def div(a: Int, b: Int) = if (b != 0) Left(a / b) else Right("Divide by zero")
div(4, 2) match {
case Left(x) => println("Result: " + x)
case Right(e) => Println("Error: " + e)
}
This would print "Result: 2". In this case, we're using Either to simulate an exception. We return an instance of Left which contains the value we want, unless that value cannot be computed for some reason, in which case we return an error message wrapped up inside an instance of Right.
So if I want to assign to variable boolean value of whether flag is found I have to do like below?
val opt1 = result(opt1Option) match {
case Positive(_) => true
case Negative(_) => false
}
Isn't there a way to write this common case with less code than that?