diff --git a/tests/run-macros/simple-interpreter.check b/tests/run-macros/simple-interpreter.check new file mode 100644 index 000000000000..1bebf4af8ba3 --- /dev/null +++ b/tests/run-macros/simple-interpreter.check @@ -0,0 +1,5 @@ +Some(BYTE) +Some(INT) +Some(OPTION[INT]) +Some(OPTION[OPTION[INT]]) +Some(MAP[INT,INT]) diff --git a/tests/run-macros/simple-interpreter/Macro_1.scala b/tests/run-macros/simple-interpreter/Macro_1.scala new file mode 100644 index 000000000000..2a5f8a36ebe6 --- /dev/null +++ b/tests/run-macros/simple-interpreter/Macro_1.scala @@ -0,0 +1,51 @@ + +trait Schema[T] +trait SchemaType[T] extends Schema[T] + +object Schema { + given intSchema: SchemaType[Int] = new SchemaType { override def toString = "INT" } + given byteSchema: SchemaType[Byte] = new SchemaType { override def toString = "BYTE" } + given optionSchema[T](using t: Schema[T]): Schema[Option[T]] = new Schema { override def toString = s"OPTION[$t]" } + given mapSchema[K, V](using k: Schema[K], v: Schema[V]): Schema[Map[K, V]] = new Schema { override def toString = s"MAP[$k,$v]" } +} + +/** Intereter for Schema. + * Assumes that all instances of schema come from `object Schema` + */ +object SchemaInterpreter { + import scala.quoted._ + + def interpretSchemaType[T: Type](schema: Expr[SchemaType[T]])(using Quotes): Option[SchemaType[T]] = + schema match { + case '{ Schema.intSchema } => Some(Schema.intSchema.asInstanceOf[SchemaType[T]]) + case '{ Schema.byteSchema } => Some(Schema.byteSchema.asInstanceOf[SchemaType[T]]) + case _ => None + } + + def interpretSchema[T: Type](schemaExpr: Expr[Schema[T]])(using Quotes): Option[Schema[T]] = + schemaExpr match { + case '{ $typeSchemaExpr: SchemaType[T] } => + interpretSchemaType(typeSchemaExpr) + case '{ Schema.optionSchema[t](using $tSchemaExpr) } => + for tSchema <- interpretSchema(tSchemaExpr) + yield Schema.optionSchema(using tSchema).asInstanceOf[Schema[T]] + case '{ Schema.mapSchema[k, v](using $kSchemaExpr, $vSchemaExpr) } => + for kSchema <- interpretSchema(kSchemaExpr) + vSchema <- interpretSchema(vSchemaExpr) + yield Schema.mapSchema(using kSchema, vSchema).asInstanceOf[Schema[T]] + case _ => + None // could also hangle with `quotes.reflect.{error, throwError}` + } +} + +object Macro { + import scala.quoted._ + + inline def useSchema[T](using inline schema: Schema[T]): String = + ${ useSchemaExpr[T]('schema) } + + private def useSchemaExpr[T: Type](schemaExpr: Expr[Schema[T]])(using Quotes): Expr[String] = { + val schemaOpt: Option[Schema[T]] = SchemaInterpreter.interpretSchema(schemaExpr) + Expr(schemaOpt.toString) + } +} diff --git a/tests/run-macros/simple-interpreter/Test_2.scala b/tests/run-macros/simple-interpreter/Test_2.scala new file mode 100644 index 000000000000..c5176441be06 --- /dev/null +++ b/tests/run-macros/simple-interpreter/Test_2.scala @@ -0,0 +1,9 @@ +import Macro.useSchema + +@main def Test: Unit = { + println(useSchema[Byte]) + println(useSchema[Int]) + println(useSchema[Option[Int]]) + println(useSchema[Option[Option[Int]]]) + println(useSchema[Map[Int, Int]]) +}