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

expressions-reification.mddocs/

Expressions and Reification

Typed AST wrappers and reification system for converting between runtime values and compile-time AST representations. Expressions provide a bridge between runtime computation and compile-time code generation and manipulation.

Capabilities

Expression Wrapper

Typed wrapper around AST trees providing type-safe access to code representations.

/**
 * Typed expression wrapper providing access to AST and type information
 */
trait ExprApi[+T] { this: Expr[T] =>
  /** Underlying abstract syntax tree */
  def tree: Tree
  
  /** Static type as determined at compile time */
  def staticType: Type
  
  /** Actual type considering runtime type refinements */
  def actualType: Type
  
  /** Splice the expression back into code context */
  def splice: T
  
  /** Convert to different universe */
  def in[U <: Universe with Singleton](otherMirror: scala.reflect.api.Mirror[U]): U#Expr[T]
}

/**
 * Create expression wrapper from tree
 */
def Expr[T: WeakTypeTag](tree: Tree): Expr[T]

Basic Expression Usage:

import scala.reflect.runtime.universe._

// Create expressions from values
val intExpr = Expr[Int](Literal(Constant(42)))
val stringExpr = Expr[String](Literal(Constant("hello")))

println(s"Int expression tree: ${intExpr.tree}")
println(s"Int expression type: ${intExpr.staticType}")
println(s"String expression tree: ${stringExpr.tree}")
println(s"String expression type: ${stringExpr.staticType}")

// Access expression properties
def analyzeExpression[T](expr: Expr[T]): Unit = {
  println(s"Tree: ${expr.tree}")
  println(s"Static type: ${expr.staticType}")
  println(s"Actual type: ${expr.actualType}")
  println(s"Tree class: ${expr.tree.getClass.getSimpleName}")
  println()
}

analyzeExpression(intExpr)
analyzeExpression(stringExpr)

Reification

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

/**
 * Reify runtime expressions into AST form
 */
def reify[T](expr: T): Expr[T]

/**
 * Reification with explicit type
 */
def reifyType[T: TypeTag](expr: T): Expr[T]

/**
 * Reify expressions with free variables
 */
def reifyEnclosingRuntimeClass[T](expr: T): Expr[T]

Reification Examples:

import scala.reflect.runtime.universe._

// Simple value reification
val numReified = reify(42)
val stringReified = reify("Hello World")
val boolReified = reify(true)

println(s"Number: ${numReified.tree}")
println(s"String: ${stringReified.tree}")  
println(s"Boolean: ${boolReified.tree}")

// Expression reification
val mathReified = reify(2 + 3 * 4)
val comparisonReified = reify(10 > 5)

println(s"Math: ${mathReified.tree}")
println(s"Comparison: ${comparisonReified.tree}")

// Complex expression reification
val complexReified = reify {
  val x = 10
  val y = 20
  if (x < y) x + y else x - y
}

println(s"Complex: ${complexReified.tree}")

// Method call reification  
def greet(name: String): String = s"Hello $name"
val methodCallReified = reify(greet("Alice"))

println(s"Method call: ${methodCallReified.tree}")

Splicing

Converting AST representations back into runtime values and expressions.

/**
 * Splice expressions back into code context
 */
trait Splicing {
  /** Splice expression into surrounding code */
  def splice[T](expr: Expr[T]): T
  
  /** Splice with explicit evaluation context */
  def eval[T](expr: Expr[T]): T
  
  /** Splice tree directly */  
  def spliceTree[T](tree: Tree): T
}

Splicing Examples:

import scala.reflect.runtime.universe._

// Create expressions
val addExpr = reify(5 + 3)
val stringExpr = reify("Hello".toUpperCase)

// Splice back to values (conceptual - actual splicing happens at compile time)
// In practice, splicing is primarily used within macro contexts

println(s"Add expression: ${addExpr.tree}")
println(s"String expression: ${stringExpr.tree}")

// Splicing in macro context example (conceptual)
def macroWithSplicing(c: scala.reflect.macros.blackbox.Context)(expr: c.Expr[Int]): c.Expr[String] = {
  import c.universe._
  
  // Create new expression using spliced value
  val newExpr = reify {
    val value = expr.splice  // Splice the expression
    s"The value is: $value"
  }
  
  newExpr
}

Expression Transformation

Transforming expressions while preserving type information.

/**
 * Expression transformation operations
 */
trait ExpressionTransformation[T] { this: Expr[T] =>
  /** Transform underlying tree */
  def transform(transformer: Tree => Tree): Expr[T]
  
  /** Map over expression value */
  def map[U: WeakTypeTag](f: T => U): Expr[U]
  
  /** FlatMap over expression */
  def flatMap[U: WeakTypeTag](f: T => Expr[U]): Expr[U]
  
  /** Filter expression */
  def filter(p: T => Boolean): Expr[Option[T]]
  
  /** Combine with another expression */
  def zip[U](other: Expr[U]): Expr[(T, U)]
}

Expression Transformation Examples:

import scala.reflect.runtime.universe._

// Create base expressions
val numExpr = reify(10)
val listExpr = reify(List(1, 2, 3, 4, 5))

// Transform expressions (conceptual API)
def transformExpression[T, U: WeakTypeTag](expr: Expr[T])(f: Tree => Tree): Expr[U] = {
  val transformedTree = f(expr.tree)
  Expr[U](transformedTree)
}

// Example transformation: double all numbers
val doubledExpr = transformExpression[Int, Int](numExpr) { tree =>
  Apply(Select(tree, TermName("$times")), List(Literal(Constant(2))))
}

println(s"Original: ${numExpr.tree}")
println(s"Doubled: ${doubledExpr.tree}")

Expression Composition

Composing multiple expressions into larger expressions.

/**
 * Expression composition utilities
 */
object ExprComposition {
  /** Combine two expressions with binary operation */
  def combine[A, B, C: WeakTypeTag](
    exprA: Expr[A], 
    exprB: Expr[B]
  )(op: (A, B) => C): Expr[C]
  
  /** Sequence multiple expressions */
  def sequence[T: WeakTypeTag](exprs: List[Expr[T]]): Expr[List[T]]
  
  /** Conditional expression composition */
  def conditional[T: WeakTypeTag](
    condition: Expr[Boolean],
    thenExpr: Expr[T], 
    elseExpr: Expr[T]
  ): Expr[T]
  
  /** Block expression from statements and result */
  def block[T: WeakTypeTag](
    statements: List[Expr[Any]], 
    result: Expr[T]
  ): Expr[T]
}

Expression Composition Examples:

import scala.reflect.runtime.universe._

// Create component expressions
val aExpr = reify(10)
val bExpr = reify(20)
val condExpr = reify(true)

// Combine expressions
val addExpr = reify(aExpr.splice + bExpr.splice)
val multExpr = reify(aExpr.splice * bExpr.splice)

println(s"Add: ${addExpr.tree}")
println(s"Multiply: ${multExpr.tree}")

// Conditional expression
val conditionalExpr = reify {
  if (condExpr.splice) aExpr.splice else bExpr.splice
}

println(s"Conditional: ${conditionalExpr.tree}")

// Block expression
val blockExpr = reify {
  val temp1 = aExpr.splice
  val temp2 = bExpr.splice
  temp1 + temp2
}

println(s"Block: ${blockExpr.tree}")

Expression Analysis

Analyzing expressions for various properties and patterns.

/**
 * Expression analysis utilities
 */
object ExpressionAnalysis {
  /** Check if expression is pure (no side effects) */
  def isPure[T](expr: Expr[T]): Boolean
  
  /** Extract free variables from expression */
  def freeVariables[T](expr: Expr[T]): Set[String]
  
  /** Get expression complexity score */
  def complexity[T](expr: Expr[T]): Int
  
  /** Check if expression contains specific patterns */
  def containsPattern[T](expr: Expr[T], pattern: Tree => Boolean): Boolean
  
  /** Extract all method calls from expression */
  def extractMethodCalls[T](expr: Expr[T]): List[(String, List[Tree])]
  
  /** Get all referenced types */
  def referencedTypes[T](expr: Expr[T]): Set[Type]
}

Expression Analysis Examples:

import scala.reflect.runtime.universe._

def analyzeExpression[T](expr: Expr[T]): Unit = {
  println(s"=== Analyzing Expression ===")
  println(s"Tree: ${expr.tree}")
  println(s"Type: ${expr.staticType}")
  
  // Manual analysis functions (conceptual implementations)
  def countNodes(tree: Tree): Int = {
    1 + tree.children.map(countNodes).sum
  }
  
  def findLiterals(tree: Tree): List[Any] = {
    tree.collect {
      case Literal(Constant(value)) => value
    }
  }
  
  def findIdentifiers(tree: Tree): List[String] = {
    tree.collect {
      case Ident(name) => name.toString
    }
  }
  
  def findMethodCalls(tree: Tree): List[String] = {
    tree.collect {
      case Apply(Select(_, name), _) => name.toString
      case Apply(Ident(name), _) => name.toString
    }
  }
  
  println(s"Node count: ${countNodes(expr.tree)}")
  println(s"Literals: ${findLiterals(expr.tree)}")
  println(s"Identifiers: ${findIdentifiers(expr.tree)}")
  println(s"Method calls: ${findMethodCalls(expr.tree)}")
  println()
}

// Analyze various expressions
analyzeExpression(reify(42))
analyzeExpression(reify("hello".toUpperCase))
analyzeExpression(reify(List(1, 2, 3).map(_ * 2).sum))
analyzeExpression(reify {
  val x = 10
  val y = 20
  if (x < y) x + y else x * y
})

Advanced Expression Patterns

Advanced patterns for working with expressions in complex scenarios.

/**
 * Advanced expression patterns and utilities
 */
object AdvancedExpressionPatterns {
  /** Partial evaluation of expressions */
  def partialEval[T](expr: Expr[T]): Expr[T]
  
  /** Expression memoization */
  def memoize[T](expr: Expr[T]): Expr[T]
  
  /** Expression optimization */
  def optimize[T](expr: Expr[T]): Expr[T]
  
  /** Dead code elimination */
  def eliminateDeadCode[T](expr: Expr[T]): Expr[T]
  
  /** Constant folding */
  def foldConstants[T](expr: Expr[T]): Expr[T]
  
  /** Expression serialization */
  def serialize[T](expr: Expr[T]): String
  
  /** Expression deserialization */
  def deserialize[T: WeakTypeTag](serialized: String): Expr[T]
}

Complete Expression and Reification Example:

import scala.reflect.runtime.universe._

// Comprehensive expression manipulation example
object ExpressionWorkshop {
  
  // Create various types of expressions
  val simpleExpr = reify(42)
  val stringExpr = reify("Hello World")
  val mathExpr = reify(2 + 3 * 4)
  val listExpr = reify(List(1, 2, 3, 4, 5))
  
  val complexExpr = reify {
    val numbers = List(1, 2, 3, 4, 5)
    val doubled = numbers.map(_ * 2)
    val filtered = doubled.filter(_ > 5)
    filtered.sum
  }
  
  // Expression introspection
  def inspectExpression[T](name: String, expr: Expr[T]): Unit = {
    println(s"=== $name ===")
    println(s"Tree: ${expr.tree}")
    println(s"Static type: ${expr.staticType}")
    println(s"Actual type: ${expr.actualType}")
    println(s"Tree structure:")
    printTreeStructure(expr.tree, 0)
    println()
  }
  
  def printTreeStructure(tree: Tree, indent: Int): Unit = {
    val spaces = "  " * indent
    println(s"$spaces${tree.getClass.getSimpleName}: $tree")
    tree.children.foreach(printTreeStructure(_, indent + 1))
  }
  
  // Pattern matching on expressions
  def analyzeExpressionPattern[T](expr: Expr[T]): String = {
    expr.tree match {
      case Literal(Constant(value)) => 
        s"Literal value: $value (${value.getClass.getSimpleName})"
      case Ident(name) => 
        s"Identifier: $name"
      case Apply(Select(obj, method), args) => 
        s"Method call: $obj.$method(${args.mkString(", ")})"
      case Apply(fun, args) => 
        s"Function call: $fun(${args.mkString(", ")})"
      case Block(statements, expr) => 
        s"Block with ${statements.length} statements, result: $expr"
      case If(condition, thenp, elsep) => 
        s"Conditional: if ($condition) $thenp else $elsep"
      case ValDef(mods, name, tpt, rhs) => 
        s"Value definition: $name = $rhs"
      case _ => 
        s"Other: ${tree.getClass.getSimpleName}"
    }
  }
  
  // Expression transformation
  def transformExpression[T](expr: Expr[T]): Expr[T] = {
    val transformer = new Transformer {
      override def transform(tree: Tree): Tree = tree match {
        // Double all integer literals
        case Literal(Constant(n: Int)) => 
          Literal(Constant(n * 2))
        // Convert string literals to uppercase
        case Literal(Constant(s: String)) => 
          Literal(Constant(s.toUpperCase))
        case _ => 
          super.transform(tree)
      }
    }
    
    Expr[T](transformer.transform(expr.tree))
  }
  
  // Run analysis
  def runAnalysis(): Unit = {
    // Inspect all expressions
    inspectExpression("Simple", simpleExpr)
    inspectExpression("String", stringExpr)
    inspectExpression("Math", mathExpr)
    inspectExpression("List", listExpr)
    inspectExpression("Complex", complexExpr)
    
    // Pattern analysis
    println("=== Pattern Analysis ===")
    println(s"Simple: ${analyzeExpressionPattern(simpleExpr)}")
    println(s"String: ${analyzeExpressionPattern(stringExpr)}")
    println(s"Math: ${analyzeExpressionPattern(mathExpr)}")
    println(s"List: ${analyzeExpressionPattern(listExpr)}")
    println()
    
    // Transformation
    println("=== Transformation ===")
    val transformedSimple = transformExpression(simpleExpr)
    val transformedString = transformExpression(stringExpr)
    
    println(s"Original simple: ${simpleExpr.tree}")
    println(s"Transformed simple: ${transformedSimple.tree}")
    println(s"Original string: ${stringExpr.tree}")
    println(s"Transformed string: ${transformedString.tree}")
    
    // Expression composition
    println("=== Composition ===")
    val combinedExpr = reify {
      val a = simpleExpr.splice
      val b = transformedSimple.splice
      a + b
    }
    println(s"Combined expression: ${combinedExpr.tree}")
  }
}

// Run the workshop
ExpressionWorkshop.runAnalysis()

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