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

macros desugars code blocks #2

Open
MasseGuillaume opened this issue Mar 25, 2016 · 3 comments
Open

macros desugars code blocks #2

MasseGuillaume opened this issue Mar 25, 2016 · 3 comments

Comments

@MasseGuillaume
Copy link

for example I see this in the trace

{
  val someVal = 2;
  (1).+(someVal).==(4)
}

I expect

{
  val someVal = 2
  1 + someVal == 4
}

this project solve the problem
https://github.com/lihaoyi/sourcecode#debug-prints

scalameta also has a good print of ast, but no def macro support yet.
https://github.com/scalameta/tutorial/tree/advanced-dendrology#showsyntax

@JohnReedLOL
Copy link
Owner

"sourcecode.Text[T]: when you want to take a value of type T, but also want to get the "source text" of that particular value. Note that if you have multiple statements in a {} block, "sourcecode.Text" will only capture the source code for the last expression that gets returned... sourcecode does not rely on runtime reflection or stack inspection, and is done at compile-time using macros. " - lihaoyi/sourcecode

Wait a second. If you have multiple statements... only capture the last expression that gets returned. I don't know if I am reading this correctly, but I don't think that this will work with multi-line expressions.

"The simplest prettyprinter in scala.meta is show[Syntax] that prints the code that the tree represents." - scalameta/tutorial

That looks nice, but it is pre-release, so I don't know if it will work in production.

In case neither of those things work, a temporary fix would be to manually get rid of the "." on all the scala operators via string manipulation and wait for scalameta to come out of pre-release

// Removal of "." produces a small but noticeable improvement
{
  val someVal = 2;
  (1) +(someVal) ==(4)
}

You can choose any of these three solutions as long as it works and it does not break anything and I will approve it.

@JohnReedLOL JohnReedLOL mentioned this issue Mar 26, 2016
@JohnReedLOL
Copy link
Owner

Hey Gaullaume,

I was wrong about the source code. Check this out:

case class Text[T](value: T, source: String)
object Text{
implicit def generate[T](v: T): Text[T] = macro Impls.text[T]
def apply[T](v: T): Text[T] = macro Impls.text[T]

}
object Impls{
def text[T: c.WeakTypeTag](c: Compat.Context)(v: c.Expr[T]): c.Expr[sourcecode.Text[T]] = {
import c.universe._
val fileContent = new String(v.tree.pos.source.content)
val start = v.tree.collect{case tree => tree.pos.startOrPoint}.min
val g = c.asInstanceOf[reflect.macros.runtime.Context].global
val parser = g.newUnitParser(fileContent.drop(start))
parser.expr()
val end = parser.in.lastOffset
val txt = fileContent.slice(start, start + end)
val tree = q"""${c.prefix}(${v.tree}, $txt)"""
c.Exprsourcecode.Text[T]
}

^ You mentioned sourceCode.Text and I didn't actually read it.

/** Java file corresponding to the source file of this position.
*

  • The return type is scala.reflect.io.AbstractFile, which belongs to an experimental part of Scala reflection.
  • It should not be used unless you know what you are doing. In subsequent releases, this API will be refined
  • and exposed as a part of scala.reflect.api.
  • @group Common
    */
    def source: scala.reflect.internal.util.SourceFile

^ The line "v.tree.pos.source.content" actually appears to be able to get the actual raw string.

@JohnReedLOL
Copy link
Owner

I solved the problem.

val fooVar = "foo"
val barVar = "bar"
Debug.traceCode{fooVar + barVar} // "(fooVar + barVar) -> foobar" in thread run-main-0:
Debug.traceCode({fooVar + barVar}, 3)
Debug.traceStackCode{fooVar + barVar}

Note that it does not always behave as you would expect. Example:

val trueVar = true
val falseVar = false
Debug.assertCode{(trueVar || falseVar || false) && false} // "trueVar || falseVar || false -> false" in thread run-main-1:

The reason is because if you wrap an expression in parenthesis, it cuts off everything outside the parenthesis. So (lala).toString becomes lala.

libraryDependencies += "scala-trace-debug" %% "scala-trace-debug" % "0.1.6"

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

No branches or pull requests

2 participants