зеркало из
				https://github.com/iharh/notes.git
				synced 2025-11-03 23:26:09 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			164 строки
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			164 строки
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
Tutorial
 | 
						|
http://scalameta.org/tutorial/
 | 
						|
https://github.com/scalameta/tutorial
 | 
						|
 | 
						|
download the amonite-shell (0.5.7)
 | 
						|
 | 
						|
load.ivy("org.scalameta" && "scalameta" % "0.20.0")
 | 
						|
 | 
						|
 | 
						|
import scala.meta._
 | 
						|
 | 
						|
$ "foo + bar".parse[Term]
 | 
						|
res2: Parsed[Term] = foo + bar
 | 
						|
$ res2.get
 | 
						|
res3: Term = foo + bar
 | 
						|
$ res3.structure // dbg-stuff
 | 
						|
res4: String = """
 | 
						|
Term.ApplyInfix(Term.Name("foo"), Term.Name("+"), Nil, Seq(Term.Name("bar")))
 | 
						|
"""
 | 
						|
$ "foo.+(bar)"
 | 
						|
res5: Term = foo.+(bar)
 | 
						|
$ res5.structure
 | 
						|
res6: String = """
 | 
						|
Term.Apply(Term.Select(Term.Name("foo"), Term.Name("+")), Seq(Term.Name("bar")))
 | 
						|
"""
 | 
						|
 | 
						|
$ """
 | 
						|
    def foo = bar
 | 
						|
  /* hello world */
 | 
						|
  foo
 | 
						|
"""
 | 
						|
res7: String = """
 | 
						|
....
 | 
						|
$ res7.parse[Term]
 | 
						|
res8: Parsed[Term] = <input>:2: error: illegal start of simple expression
 | 
						|
def foo = bar
 | 
						|
        ^
 | 
						|
$("{" + res7 + "}").parse[Term]
 | 
						|
res9: Parsed[Term]  {
 | 
						|
    def foo = bar
 | 
						|
  /* hello world */
 | 
						|
foo
 | 
						|
}
 | 
						|
$ res9.structure
 | 
						|
Main.scala:158: value structure is not a member of scala.meta.parsers.Parsed[
 | 
						|
res9.structure
 | 
						|
     ^
 | 
						|
Compilation Failed
 | 
						|
$ res9.get.structure
 | 
						|
res10: String = """
 | 
						|
Term.Block(Seq[Defn.Def(Nil, Term.Name("foo"), Nil, Nil, None, Term.Name("bar
 | 
						|
// !!! don't see any comments
 | 
						|
$ res9.get.tokens
 | 
						|
res11: Tokens = Tokens(
 | 
						|
    ,
 | 
						|
    {,
 | 
						|
 | 
						|
,
 | 
						|
    ,
 | 
						|
    ,
 | 
						|
    ....
 | 
						|
  def,
 | 
						|
...
 | 
						|
@ res9.get.tokens.structure
 | 
						|
res12: String = """
 | 
						|
Tokens(BOF [0..0), { [0..1), \n [1..2),   [2..3),   [3..4), 
 | 
						|
...
 | 
						|
... [26..27), /* hello world */
 | 
						|
foo [f5..48), \n [48..49), } [49..50), EOF [50..50))
 | 
						|
"""
 | 
						|
// !!! preserve all the stuff
 | 
						|
 | 
						|
 | 
						|
+++++++
 | 
						|
+ SBT +
 | 
						|
+++++++
 | 
						|
 | 
						|
$ val buildsbt = new java.io.File("/.../build.sbt")
 | 
						|
buildsbt: java.io.File = /.../build.sbt
 | 
						|
$ buildsbt.parse[Source]
 | 
						|
res14: Parsed[Source] = build.sbt:6: error: expected class or object defined...
 | 
						|
def ifAt...
 | 
						|
^
 | 
						|
$ scala.meta.dialects.Sbt0137(buildsbt).parse[Source]
 | 
						|
res18: Parsed[Source] = import sbtrelease._
 | 
						|
...
 | 
						|
def ifAtLeast(scala....)
 | 
						|
    case class ScalaBinaryVersion...
 | 
						|
...
 | 
						|
$ res18.get.structure
 | 
						|
res19: String = """
 | 
						|
Source(Seq[Import(Seq(Importer(Term.Name...
 | 
						|
"""
 | 
						|
 | 
						|
++++++
 | 
						|
+ QQ +
 | 
						|
++++++
 | 
						|
 | 
						|
$ val foo = q"foo"
 | 
						|
foo: Term.Name = fool
 | 
						|
$ q"$foo + bar"
 | 
						|
res21: Term.ApplyInfix = foo + bar
 | 
						|
$ val q "$x + $y" = q"$foo + bar"
 | 
						|
x: Term = foo
 | 
						|
y: Term.Arg = bar
 | 
						|
// y type is an Argument, not a Term
 | 
						|
 | 
						|
 | 
						|
Old macros:
 | 
						|
 | 
						|
class Table[T](val query: Query[T]) {
 | 
						|
    def map[U](fn: T => U): Table[U] = macro Macros.map
 | 
						|
}
 | 
						|
 | 
						|
object Macros {
 | 
						|
    def map(c: Context)(fn: c.Tree): c.Tree = {
 | 
						|
        val subquery: c.Tree = translate(fn)
 | 
						|
        q"new Table(Map(${c.prefix}, $subquery))"
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
val users: Table[User] = ....
 | 
						|
users.map(u => u.name)
 | 
						|
- expands into -
 | 
						|
val users: Table[User] = ...
 | 
						|
new Table(Map(users, Ref("name", classOf[String])))
 | 
						|
 | 
						|
 | 
						|
New macros sketch
 | 
						|
 | 
						|
class Table[T](val query: Query[T]) {
 | 
						|
    inline def map[U](fn: T => U): Table[U] = meta {
 | 
						|
        val subquery: c.Tree = translate(fn)
 | 
						|
        q"new Table(Map($this, $subquery))"
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
val users: Table[User] = ....
 | 
						|
users.map(u => u.name)
 | 
						|
- expands into (via inline) -
 | 
						|
val users: Table[User] = ...
 | 
						|
meta{ ...; q"new Table(Map(users, $subquery))" }
 | 
						|
- and later into -
 | 
						|
new Table(Map(users, Ref("name", classOf[String])))
 | 
						|
 | 
						|
+++++++++++++
 | 
						|
+ LIVE DEMO +
 | 
						|
+++++++++++++
 | 
						|
 | 
						|
import scala.meta._
 | 
						|
 | 
						|
object main{
 | 
						|
    inline def apply()(defn: Any) = meta {
 | 
						|
        val q"..$mods object $name extends { ..$early } with .. $base { $self => .. $stats}"
 | 
						|
        val main = q"def main(args: Array[String]): Unit = { ..$stats}"
 | 
						|
        q"..$mods object $name extends { ..$early } with ..$base { $self => $main }"
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
// using by
 | 
						|
@main object Test {
 | 
						|
    println("hello world")
 | 
						|
}
 |