CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-scala-lang--scala-reflect

Reflection Library for the Scala Programming Language providing runtime reflection capabilities and metaprogramming support

Pending
Overview
Eval results
Files

abstract-syntax-trees.mddocs/

Abstract Syntax Trees

AST representation and manipulation for compile-time and runtime tree processing, reification, and code generation. Trees represent the structure of Scala code as data that can be analyzed, transformed, and generated.

Capabilities

Base Tree API

Core tree operations and properties available on all tree nodes.

/**
 * Base tree trait providing fundamental tree operations
 */
trait TreeApi { this: Tree =>
  /** Position in source code */
  def pos: Position
  
  /** Type of this tree node */
  def tpe: Type
  
  /** Symbol associated with this tree */
  def symbol: Symbol
  
  /** Child trees */
  def children: List[Tree]
  
  /** Create a copy of this tree */
  def duplicate: Tree
  
  /** Check if this tree is empty */
  def isEmpty: Boolean
  
  /** Check if this tree represents a term */
  def isTerm: Boolean
  
  /** Check if this tree represents a type */
  def isType: Boolean
  
  /** Convert to string representation */  
  def toString: String
}

Tree Traversal and Transformation

Methods for traversing and transforming tree structures.

/**
 * Tree traversal operations
 */
trait TreeTraversal { this: Tree =>
  /** Apply function to this tree and all subtrees */
  def foreach(f: Tree => Unit): Unit
  
  /** Filter trees matching predicate */
  def filter(p: Tree => Boolean): List[Tree]
  
  /** Collect results from partial function application */
  def collect[T](pf: PartialFunction[Tree, T]): List[T]
  
  /** Find first tree matching predicate */
  def find(p: Tree => Boolean): Option[Tree]
  
  /** Check if any subtree matches predicate */
  def exists(p: Tree => Boolean): Boolean
  
  /** Transform tree using partial function */
  def transform(transformer: Transformer): Tree
  
  /** Map function over all subtrees */
  def map(f: Tree => Tree): Tree
}

Usage Example:

import scala.reflect.runtime.universe._

// Create a simple AST
val code = reify {
  val x = 10
  val y = 20
  x + y
}.tree

println(s"Original tree: $code")

// Traverse the tree
code.foreach { tree =>
  println(s"Node: ${tree.getClass.getSimpleName} -> $tree")
}

// Find all literal values
val literals = code.collect {
  case Literal(Constant(value)) => value
}
println(s"Literals found: $literals")

// Find variable references
val variables = code.collect {
  case Ident(name) => name.toString
}
println(s"Variables found: $variables")

Tree Reification

Converting runtime values and expressions into compile-time AST representations.

/**
 * Reification - converting expressions to trees
 */
def reify[T](expr: T): Expr[T]

/**
 * Expression wrapper providing typed AST access
 */
trait ExprApi[+T] { this: Expr[T] =>
  /** Underlying AST */
  def tree: Tree
  
  /** Static type */
  def staticType: Type
  
  /** Actual type */
  def actualType: Type
  
  /** Splice expression back to value */
  def splice: T
}

Usage Examples:

import scala.reflect.runtime.universe._

// Reify simple expressions
val numExpr = reify(42)
println(s"Number expression tree: ${numExpr.tree}")
println(s"Static type: ${numExpr.staticType}")

val stringExpr = reify("Hello World")
println(s"String expression tree: ${stringExpr.tree}")

// Reify complex expressions
val mathExpr = reify {
  val a = 10
  val b = 20
  a * b + 5
}
println(s"Math expression tree: ${mathExpr.tree}")

// Reify method calls
def greet(name: String): String = s"Hello $name"
val methodCallExpr = reify(greet("Alice"))
println(s"Method call tree: ${methodCallExpr.tree}")

// Reify control structures
val controlExpr = reify {
  val numbers = List(1, 2, 3, 4, 5)
  for (n <- numbers if n % 2 == 0) yield n * 2
}
println(s"Control structure tree: ${controlExpr.tree}")

Tree Construction

Programmatic construction of AST nodes.

/**
 * Tree construction utilities
 */
object TreeFactory {
  /** Create literal tree */
  def Literal(value: Any): Tree
  
  /** Create identifier tree */
  def Ident(name: String): Tree
  
  /** Create method application tree */
  def Apply(fun: Tree, args: List[Tree]): Tree
  
  /** Create type application tree */
  def TypeApply(fun: Tree, args: List[Tree]): Tree
  
  /** Create selection tree (obj.member) */
  def Select(qualifier: Tree, name: String): Tree
  
  /** Create block tree */
  def Block(stats: List[Tree], expr: Tree): Tree
  
  /** Create if-then-else tree */
  def If(cond: Tree, thenp: Tree, elsep: Tree): Tree
  
  /** Create value definition tree */
  def ValDef(name: String, tpt: Tree, rhs: Tree): Tree
  
  /** Create method definition tree */
  def DefDef(name: String, paramss: List[List[Tree]], tpt: Tree, rhs: Tree): Tree
}

Usage Example:

import scala.reflect.runtime.universe._

// Construct simple trees
val literalTree = Literal(Constant(42))
val identTree = Ident(TermName("x"))

// Construct method call: println("Hello")
val printlnTree = Select(Ident(TermName("scala")), TermName("println"))  
val helloTree = Literal(Constant("Hello"))
val callTree = Apply(printlnTree, List(helloTree))

println(s"Method call tree: $callTree")

// Construct block: { val x = 10; x + 5 }
val valDefTree = ValDef(
  Modifiers(), 
  TermName("x"), 
  TypeTree(), 
  Literal(Constant(10))
)
val addTree = Apply(
  Select(Ident(TermName("x")), TermName("$plus")),
  List(Literal(Constant(5)))
)
val blockTree = Block(List(valDefTree), addTree)

println(s"Block tree: $blockTree")

Tree Pattern Matching

Pattern matching on AST nodes for analysis and transformation.

/**
 * Common tree patterns for matching
 */
object TreePatterns {
  /** Match literal values */
  def unapply(tree: Tree): Option[Any] = tree match {
    case Literal(Constant(value)) => Some(value)
    case _ => None
  }
  
  /** Match variable references */
  object Variable {
    def unapply(tree: Tree): Option[String] = tree match {
      case Ident(name) => Some(name.toString)
      case _ => None
    }
  }
  
  /** Match method calls */
  object MethodCall {
    def unapply(tree: Tree): Option[(Tree, String, List[Tree])] = tree match {
      case Apply(Select(obj, name), args) => Some((obj, name.toString, args))
      case _ => None
    }
  }
  
  /** Match assignments */
  object Assignment {
    def unapply(tree: Tree): Option[(String, Tree)] = tree match {
      case Assign(Ident(name), rhs) => Some((name.toString, rhs))
      case _ => None
    }
  }
}

Usage Example:

import scala.reflect.runtime.universe._

val sampleCode = reify {
  val name = "Alice"
  val age = 25
  println(s"$name is $age years old")
  age + 1
}.tree

// Pattern match on tree nodes
def analyzeTree(tree: Tree): Unit = tree match {
  case Literal(Constant(value)) =>
    println(s"Found literal: $value (${value.getClass.getSimpleName})")
    
  case Ident(name) =>
    println(s"Found identifier: $name")
    
  case Apply(Select(obj, name), args) =>
    println(s"Found method call: $obj.$name with ${args.length} arguments")
    args.foreach(analyzeTree)
    analyzeTree(obj)
    
  case ValDef(mods, name, tpt, rhs) =>
    println(s"Found val definition: $name")
    analyzeTree(rhs)
    
  case Block(stats, expr) =>
    println(s"Found block with ${stats.length} statements")
    stats.foreach(analyzeTree)
    analyzeTree(expr)
    
  case other =>
    println(s"Other tree: ${other.getClass.getSimpleName}")
    other.children.foreach(analyzeTree)
}

analyzeTree(sampleCode)

Tree Transformers

Systematic tree transformation using the Transformer class.

/**
 * Base transformer for systematic tree transformation
 */
abstract class Transformer {
  /** Transform a tree */  
  def transform(tree: Tree): Tree
  
  /** Transform list of trees */
  def transformTrees(trees: List[Tree]): List[Tree]
  
  /** Transform modifiers */
  def transformModifiers(mods: Modifiers): Modifiers
  
  /** Transform template */
  def transformTemplate(templ: Template): Template
}

Usage Example:

import scala.reflect.runtime.universe._

// Custom transformer that replaces all integer literals with their double
class IntToDoubleTransformer extends Transformer {
  override def transform(tree: Tree): Tree = tree match {
    case Literal(Constant(value: Int)) =>
      Literal(Constant(value.toDouble))
    case _ =>
      super.transform(tree)
  }
}

val originalCode = reify {
  val x = 10
  val y = 20
  x + y
}.tree

println(s"Original: $originalCode")

val transformer = new IntToDoubleTransformer
val transformedCode = transformer.transform(originalCode)
println(s"Transformed: $transformedCode")

Tree Traversers

Systematic tree traversal using the Traverser class.

/**
 * Base traverser for systematic tree traversal
 */
abstract class Traverser {
  /** Traverse a tree */
  def traverse(tree: Tree): Unit
  
  /** Traverse list of trees */
  def traverseTrees(trees: List[Tree]): Unit
  
  /** Traverse modifiers */
  def traverseModifiers(mods: Modifiers): Unit
  
  /** Traverse template */
  def traverseTemplate(templ: Template): Unit
}

Usage Example:

import scala.reflect.runtime.universe._

// Custom traverser that counts different node types
class NodeCounter extends Traverser {
  private var counts = scala.collection.mutable.Map[String, Int]()
  
  def getCounts: Map[String, Int] = counts.toMap
  
  override def traverse(tree: Tree): Unit = {
    val nodeType = tree.getClass.getSimpleName
    counts(nodeType) = counts.getOrElse(nodeType, 0) + 1
    super.traverse(tree)
  }
}

val code = reify {
  val numbers = List(1, 2, 3, 4, 5)
  val doubled = numbers.map(_ * 2)
  val sum = doubled.reduce(_ + _)
  println(s"Sum: $sum")
}.tree

val counter = new NodeCounter
counter.traverse(code)

println("Node counts:")
counter.getCounts.toSeq.sortBy(-_._2).foreach { case (nodeType, count) =>
  println(s"  $nodeType: $count")
}

Advanced Tree Operations

Complex tree operations for advanced use cases.

/**
 * Advanced tree manipulation utilities
 */
object TreeUtils {
  /** Find all nodes of specific type */
  def findNodesOfType[T <: Tree](tree: Tree)(implicit tag: scala.reflect.ClassTag[T]): List[T]
  
  /** Replace all occurrences of a subtree */
  def replaceTree(tree: Tree, target: Tree, replacement: Tree): Tree
  
  /** Extract all variable names */
  def extractVariableNames(tree: Tree): Set[String]
  
  /** Check if tree contains a specific pattern */
  def containsPattern(tree: Tree, pattern: Tree => Boolean): Boolean
  
  /** Get tree depth */
  def getDepth(tree: Tree): Int
  
  /** Pretty print tree structure */
  def prettyPrint(tree: Tree, indent: Int = 0): String
}

Complete Tree Analysis Example:

import scala.reflect.runtime.universe._

def completeTreeAnalysis(tree: Tree): Unit = {
  println("=== Tree Analysis ===")
  println(s"Tree: $tree")
  println(s"Type: ${tree.tpe}")
  println(s"Symbol: ${tree.symbol}")
  println(s"Position: ${tree.pos}")
  println(s"Is term: ${tree.isTerm}")
  println(s"Is type: ${tree.isType}")
  println(s"Is empty: ${tree.isEmpty}")
  
  // Children analysis
  println(s"\nChildren (${tree.children.length}):")
  tree.children.zipWithIndex.foreach { case (child, i) =>
    println(s"  [$i] ${child.getClass.getSimpleName}: $child")
  }
  
  // Pattern matching analysis
  tree match {
    case Literal(Constant(value)) =>
      println(s"\nLiteral value: $value (${value.getClass.getSimpleName})")
      
    case Ident(name) =>
      println(s"\nIdentifier: $name")
      
    case Apply(fun, args) =>
      println(s"\nApplication:")
      println(s"  Function: $fun")
      println(s"  Arguments (${args.length}): ${args.mkString(", ")}")
      
    case Select(qualifier, name) =>
      println(s"\nSelection:")
      println(s"  Qualifier: $qualifier")
      println(s"  Name: $name")
      
    case Block(stats, expr) =>
      println(s"\nBlock:")
      println(s"  Statements (${stats.length}): ${stats.mkString("; ")}")
      println(s"  Expression: $expr")
      
    case _ =>
      println(s"\nOther tree type: ${tree.getClass.getSimpleName}")
  }
  
  println("\n" + "="*50)
}

// Analyze various tree types
val examples = List(
  reify(42).tree,
  reify("hello").tree,
  reify(List(1, 2, 3)).tree,
  reify { val x = 10; x + 5 }.tree,
  reify { if (true) "yes" else "no" }.tree
)

examples.foreach(completeTreeAnalysis)

Install with Tessl CLI

npx tessl i tessl/maven-org-scala-lang--scala-reflect

docs

abstract-syntax-trees.md

expressions-reification.md

index.md

macro-development.md

mirrors-reflective-operations.md

runtime-reflection.md

symbol-system.md

type-system.md

type-tags-type-information.md

tile.json