Last active
February 1, 2023 06:12
-
-
Save mohnishkodnani/23dbb6a7cf16076bb3d53d9c50202b8d to your computer and use it in GitHub Desktop.
Trying to see if we can build such a table at compile time if all values are known.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// If I want to take the code here to build a Table using context functions and convert it to compile time check using macros, to validate rows / cell values etc how do i do that. | |
// https://docs.scala-lang.org/scala3/reference/contextual/context-functions.html | |
class Table: | |
val rows = new ArrayBuffer[Row] | |
def add(r: Row): Unit = rows += r | |
override def toString = rows.mkString("Table(", ", ", ")") | |
class Row: | |
val cells = new ArrayBuffer[Cell] | |
def add(c: Cell): Unit = cells += c | |
override def toString = cells.mkString("Row(", ", ", ")") | |
case class Cell(elem: String) | |
// WORKING DSL without macro. | |
/** | |
def table(init: Table ?=> Unit) = | |
given t: Table = Table() | |
init | |
t | |
def row(init: Row ?=> Unit)(using t: Table) = | |
given r: Row = Row() | |
init | |
t.add(r) | |
def cell(str: String)(using r: Row) = | |
r.add(new Cell(str)) | |
*/ | |
// With MACRO | |
inline def table(init: Table ?=> Unit) = ${tableImpl('init)} | |
def tableImpl(initExpr: Expr[Table ?=> Unit])(using Quotes) = | |
import quotes.reflect.* | |
given table: Table = new Table() | |
// Do some validations on the rows added to this table with the row function call. | |
// How to call init at compile time like the call above | |
// Return the EXPR of table | |
Expr(table) | |
// My initial thought was to make this into a macro as well, however, if I conver this to macro to perform compile time | |
// checks by converting this to inline, then this function is expanded before the table macro is expanded and the "table instance t" is empty and so cannot add rows, they are lost. | |
// so keeping this as is, such that table macro expansion happens first. | |
def row(init: Row ?=> Unit)(using t: Table) = | |
given r: Row = Row() | |
init | |
t.add(r) | |
// Example of the row function as a compile time macro. | |
def rowImpl(initExpr: Expr[Row ?=> Unit], tExpr: Expr[Table])(using Quotes) = | |
import quotes.reflect.* | |
given r: Row = Row() | |
// DO NOT KNOW how to invoke initExpr here as well. | |
val rowExpr = Expr(r) | |
// Also, if I add to a table here it doesn't show up in the end table returned by the table function. | |
'{${tExpr}.add(${rowExpr})} | |
rowExpr |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment