From 6d32c64776603bcd84f78bfcc5cefb0f63d8c4b9 Mon Sep 17 00:00:00 2001 From: Emilien Bauer Date: Mon, 17 Mar 2025 15:20:30 +0000 Subject: [PATCH 1/9] Forward full opDef in macros. --- clairV2/src/main/scala-3/CodeGen.scala | 2 +- clairV2/src/main/scala-3/Macros.scala | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/clairV2/src/main/scala-3/CodeGen.scala b/clairV2/src/main/scala-3/CodeGen.scala index 57ee165..b865d3c 100644 --- a/clairV2/src/main/scala-3/CodeGen.scala +++ b/clairV2/src/main/scala-3/CodeGen.scala @@ -77,4 +77,4 @@ case class OperationDef( val properties: Seq[OpPropertyDef] = Seq(), val attributes: Seq[OpAttributeDef] = Seq(), val assembly_format: Option[String] = None -) +) \ No newline at end of file diff --git a/clairV2/src/main/scala-3/Macros.scala b/clairV2/src/main/scala-3/Macros.scala index 818a4b6..c0a2647 100644 --- a/clairV2/src/main/scala-3/Macros.scala +++ b/clairV2/src/main/scala-3/Macros.scala @@ -45,7 +45,7 @@ def getClassPathImpl[T: Type](using Quotes): Expr[String] = { || Hook for UnverifiedOp Constructor || \*≡==---==≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡==---==≡*/ -inline def constructUnverifiedOpHook[T](opDef: OperationDef)( +inline def constructUnverifiedOpHook[T]( opDef: OperationDef)( operands: ListType[Value[Attribute]], successors: ListType[scair.ir.Block], results_types: ListType[Attribute], @@ -55,7 +55,7 @@ inline def constructUnverifiedOpHook[T](opDef: OperationDef)( ): UnverifiedOp[T] = ${ constructUnverifiedOpHookMacro[T]( - '{ opDef.name }, + 'opDef, 'operands, 'successors, 'results_types, @@ -74,7 +74,7 @@ def getNameLowerImpl[T: Type](using Quotes): Expr[String] = { inline def getNameLower[T]: String = ${ getNameLowerImpl[T] } def constructUnverifiedOpHookMacro[T: Type]( - name: Expr[String], + opDef: Expr[OperationDef], operands: Expr[ListType[Value[Attribute]]], successors: Expr[ListType[scair.ir.Block]], results_types: Expr[ListType[Attribute]], @@ -83,10 +83,9 @@ def constructUnverifiedOpHookMacro[T: Type]( dictionaryAttributes: Expr[DictType[String, Attribute]] )(using Quotes): Expr[UnverifiedOp[T]] = { import quotes.reflect.* - '{ UnverifiedOp[T]( - name = $name, + name = ${opDef}.name, operands = $operands, successors = $successors, results_types = $results_types, @@ -102,9 +101,9 @@ def constructUnverifiedOpHookMacro[T: Type]( \*≡==---==≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡==---==≡*/ inline def fromADTOperation[T](opDef: OperationDef)(gen: T): UnverifiedOp[T] = - ${ fromADTOperationMacro[T]('{ opDef.name }, 'gen) } + ${ fromADTOperationMacro[T]('opDef, 'gen) } -def fromADTOperationMacro[T: Type](name: Expr[String], adtOpExpr: Expr[T])(using +def fromADTOperationMacro[T: Type](opDef: Expr[OperationDef], adtOpExpr: Expr[T])(using Quotes ): Expr[UnverifiedOp[T]] = import quotes.reflect.* @@ -304,7 +303,7 @@ def fromADTOperationMacro[T: Type](name: Expr[String], adtOpExpr: Expr[T])(using '{ val x = UnverifiedOp[T]( - name = $name, + name = ${opDef}.name, operands = $operandSeqExpr, successors = $successorSeqExpr, results_types = ListType.empty[Attribute], From a627f4e39a16e03a20729d21fe3b5dc5bfe62328 Mon Sep 17 00:00:00 2001 From: Emilien Bauer Date: Mon, 17 Mar 2025 15:45:36 +0000 Subject: [PATCH 2/9] Refactor operands through opDef. --- clairV2/src/main/scala-3/CV2Mirror.scala | 16 ++++---- clairV2/src/main/scala-3/CodeGen.scala | 14 +++---- clairV2/src/main/scala-3/Macros.scala | 50 ++++++++++++++++++++---- 3 files changed, 57 insertions(+), 23 deletions(-) diff --git a/clairV2/src/main/scala-3/CV2Mirror.scala b/clairV2/src/main/scala-3/CV2Mirror.scala index 92148d6..7f1f167 100644 --- a/clairV2/src/main/scala-3/CV2Mirror.scala +++ b/clairV2/src/main/scala-3/CV2Mirror.scala @@ -53,46 +53,46 @@ inline def getDefInput[Label, Elem]: OpInput = { inline erasedValue[Elem] match case _: Variadic[Operand[t]] => OperandDef( - id = name, + name = name, typeString = typeToString[t], Variadicity.Variadic ) case _: Variadic[Result[t]] => OperandDef( - id = name, + name = name, typeString = typeToString[t], Variadicity.Variadic ) case _: Result[t] => ResultDef( - id = name, + name = name, typeString = typeToString[t], Variadicity.Single ) case _: Operand[t] => OperandDef( - id = name, + name = name, typeString = typeToString[t], Variadicity.Single ) case _: Region => RegionDef( - id = name, + name = name, Variadicity.Single ) case _: Successor => SuccessorDef( - id = name, + name = name, Variadicity.Single ) case _: Property[t] => OpPropertyDef( - id = name, + name = name, typeString = typeToString[t] ) case _: Attr[t] => OpAttributeDef( - id = name, + name = name, typeString = typeToString[t] ) case _ => diff --git a/clairV2/src/main/scala-3/CodeGen.scala b/clairV2/src/main/scala-3/CodeGen.scala index b865d3c..7acde5a 100644 --- a/clairV2/src/main/scala-3/CodeGen.scala +++ b/clairV2/src/main/scala-3/CodeGen.scala @@ -32,34 +32,34 @@ enum Variadicity { } case class OperandDef( - val id: String, + val name: String, val typeString: String, val variadicity: Variadicity = Variadicity.Single ) extends OpInput {} case class ResultDef( - val id: String, + val name: String, val typeString: String, val variadicity: Variadicity = Variadicity.Single ) extends OpInput {} case class RegionDef( - val id: String, + val name: String, val variadicity: Variadicity = Variadicity.Single ) extends OpInput {} case class SuccessorDef( - val id: String, + val name: String, val variadicity: Variadicity = Variadicity.Single ) extends OpInput {} case class OpPropertyDef( - val id: String, + val name: String, val typeString: String ) extends OpInput {} case class OpAttributeDef( - val id: String, + val name: String, val typeString: String ) extends OpInput {} @@ -77,4 +77,4 @@ case class OperationDef( val properties: Seq[OpPropertyDef] = Seq(), val attributes: Seq[OpAttributeDef] = Seq(), val assembly_format: Option[String] = None -) \ No newline at end of file +) diff --git a/clairV2/src/main/scala-3/Macros.scala b/clairV2/src/main/scala-3/Macros.scala index c0a2647..3e30bfb 100644 --- a/clairV2/src/main/scala-3/Macros.scala +++ b/clairV2/src/main/scala-3/Macros.scala @@ -10,7 +10,7 @@ import scala.collection.mutable.ListBuffer import scala.compiletime._ import scair.clairV2.mirrored.getDef import scala.deriving.Mirror -import scair.clairV2.codegen.OperationDef +import scair.clairV2.codegen._ // ░█████╗░ ██╗░░░░░ ░█████╗░ ██╗ ██████╗░ ██╗░░░██╗ ██████╗░ // ██╔══██╗ ██║░░░░░ ██╔══██╗ ██║ ██╔══██╗ ██║░░░██║ ╚════██╗ @@ -45,7 +45,7 @@ def getClassPathImpl[T: Type](using Quotes): Expr[String] = { || Hook for UnverifiedOp Constructor || \*≡==---==≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡==---==≡*/ -inline def constructUnverifiedOpHook[T]( opDef: OperationDef)( +inline def constructUnverifiedOpHook[T](opDef: OperationDef)( operands: ListType[Value[Attribute]], successors: ListType[scair.ir.Block], results_types: ListType[Attribute], @@ -85,7 +85,7 @@ def constructUnverifiedOpHookMacro[T: Type]( import quotes.reflect.* '{ UnverifiedOp[T]( - name = ${opDef}.name, + name = ${ opDef }.name, operands = $operands, successors = $successors, results_types = $results_types, @@ -100,10 +100,44 @@ def constructUnverifiedOpHookMacro[T: Type]( || ADT to Unverified conversion Macro || \*≡==---==≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡==---==≡*/ +inline def ADTFlatOperands[T](opDef: OperationDef)(gen: T) = + ${ ADTFlatOperandsMacro[T]('{ opDef.operands }, 'gen) } + +def ADTFlatOperandsMacro[T: Type]( + operandDefs: Expr[Iterable[OperandDef]], + adtOpExpr: Expr[T] +)(using + Quotes +) = + import quotes.reflect.* + + val operands_exprs = '{ + ListType.from( + ${ operandDefs }.map((o: OperandDef) => + ${ + Select( + adtOpExpr.asTerm, + adtOpExpr.asTerm.tpe.typeSymbol.fieldMember(o.name) + ).asExprOf[Operand[Attribute]] + } + ) + ) + } + + operands_exprs + + // extracting operand instances from the ADT + // '{ ListType.from($operandDefs.map {${ (o : OperandDef) => + // Select.unique(adtOpExpr.asTerm, o.name).asExpr .asInstanceOf[Operand[Attribute]] }) } + inline def fromADTOperation[T](opDef: OperationDef)(gen: T): UnverifiedOp[T] = - ${ fromADTOperationMacro[T]('opDef, 'gen) } + ${ fromADTOperationMacro[T]('opDef, '{ ADTFlatOperands(opDef)(gen) }, 'gen) } -def fromADTOperationMacro[T: Type](opDef: Expr[OperationDef], adtOpExpr: Expr[T])(using +def fromADTOperationMacro[T: Type]( + opDef: Expr[OperationDef], + flatOperands: Expr[ListType[Value[Attribute]]], + adtOpExpr: Expr[T] +)(using Quotes ): Expr[UnverifiedOp[T]] = import quotes.reflect.* @@ -174,7 +208,7 @@ def fromADTOperationMacro[T: Type](opDef: Expr[OperationDef], adtOpExpr: Expr[T] \*-- SUCCESSORS --*/ // partitioning ADT parameters by Successor - val (successorParams, restParams1) = restParams0.partition { sym => + val (successorParams, restParams1) = params.partition { sym => sym.termRef.widenTermRefByName match case tycon => tycon =:= TypeRepr.of[scair.ir.Block] } @@ -303,8 +337,8 @@ def fromADTOperationMacro[T: Type](opDef: Expr[OperationDef], adtOpExpr: Expr[T] '{ val x = UnverifiedOp[T]( - name = ${opDef}.name, - operands = $operandSeqExpr, + name = ${ opDef }.name, + operands = $flatOperands, successors = $successorSeqExpr, results_types = ListType.empty[Attribute], regions = $regionSeqExpr, From 0b2b8e13e49efa40e8ea25f2508d5fa6dc216ddb Mon Sep 17 00:00:00 2001 From: Emilien Bauer Date: Wed, 19 Mar 2025 15:49:13 +0000 Subject: [PATCH 3/9] temp --- clairV2/src/main/scala-3/CV2Mirror.scala | 4 +- clairV2/src/main/scala-3/CodeGen.scala | 36 +++++++++------ clairV2/src/main/scala-3/Macros.scala | 57 ++++++++++++------------ 3 files changed, 53 insertions(+), 44 deletions(-) diff --git a/clairV2/src/main/scala-3/CV2Mirror.scala b/clairV2/src/main/scala-3/CV2Mirror.scala index 7f1f167..513cbba 100644 --- a/clairV2/src/main/scala-3/CV2Mirror.scala +++ b/clairV2/src/main/scala-3/CV2Mirror.scala @@ -43,7 +43,7 @@ inline def inputVariadicity[Elem] = inline erasedValue[Elem] match * Input to OperationDef, either: OperandDef, ResultDef, RegionDef, * SuccessorDef, OpPropertyDef, OpAttributeDef */ -inline def getDefInput[Label, Elem]: OpInput = { +inline def getDefInput[Label, Elem]: OpInputDef = { val name = inline erasedValue[Label] match case _: String => constValue[Label].asInstanceOf[String] @@ -107,7 +107,7 @@ inline def getDefInput[Label, Elem]: OpInput = { * @return * Lambda that produces an input to OperationDef, given a string */ -inline def summonInput[Labels <: Tuple, Elems <: Tuple]: List[OpInput] = { +inline def summonInput[Labels <: Tuple, Elems <: Tuple]: List[OpInputDef] = { inline erasedValue[(Labels, Elems)] match case _: ((label *: labels, elem *: elems)) => diff --git a/clairV2/src/main/scala-3/CodeGen.scala b/clairV2/src/main/scala-3/CodeGen.scala index 7acde5a..cc998b7 100644 --- a/clairV2/src/main/scala-3/CodeGen.scala +++ b/clairV2/src/main/scala-3/CodeGen.scala @@ -3,6 +3,7 @@ package scair.clairV2.codegen import java.io.File import java.io.PrintStream import scala.reflect.* +import scair.ir._ // ░█████╗░ ██╗░░░░░ ░█████╗░ ██╗ ██████╗░ ██╗░░░██╗ ██████╗░ // ██╔══██╗ ██║░░░░░ ██╔══██╗ ██║ ██╔══██╗ ██║░░░██║ ╚════██╗ @@ -22,7 +23,7 @@ import scala.reflect.* || CONTAINERS || \*≡=--==≡≡==--=≡*/ -abstract class OpInput {} +sealed trait OpInputDef(val name:String) {} // TODO: Add support for optionals AFTER variadic support is laid out // It really just adds cognitive noise otherwise IMO. The broader structure and logic is exactly the same. @@ -31,37 +32,46 @@ enum Variadicity { case Single, Variadic } +type DefinedInput[T <: OpInputDef] = T match { + case OperandDef => Operand[Attribute] + case ResultDef => Result[Attribute] + case RegionDef => Region + case SuccessorDef => Successor + case OpPropertyDef => Property[Attribute] + case OpAttributeDef => Attribute +} + case class OperandDef( - val name: String, + override val name: String, val typeString: String, val variadicity: Variadicity = Variadicity.Single -) extends OpInput {} +) extends OpInputDef(name) {} case class ResultDef( - val name: String, + override val name: String, val typeString: String, val variadicity: Variadicity = Variadicity.Single -) extends OpInput {} +) extends OpInputDef(name) {} case class RegionDef( - val name: String, + override val name: String, val variadicity: Variadicity = Variadicity.Single -) extends OpInput {} +) extends OpInputDef(name) {} case class SuccessorDef( - val name: String, + override val name: String, val variadicity: Variadicity = Variadicity.Single -) extends OpInput {} +) extends OpInputDef(name) {} case class OpPropertyDef( - val name: String, + override val name: String, val typeString: String -) extends OpInput {} +) extends OpInputDef(name) {} case class OpAttributeDef( - val name: String, + override val name: String, val typeString: String -) extends OpInput {} +) extends OpInputDef(name) {} /*≡≡=---=≡≡≡≡≡=---=≡≡*\ || OPERATION DEF || diff --git a/clairV2/src/main/scala-3/Macros.scala b/clairV2/src/main/scala-3/Macros.scala index 3e30bfb..a76dffa 100644 --- a/clairV2/src/main/scala-3/Macros.scala +++ b/clairV2/src/main/scala-3/Macros.scala @@ -100,38 +100,38 @@ def constructUnverifiedOpHookMacro[T: Type]( || ADT to Unverified conversion Macro || \*≡==---==≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡==---==≡*/ -inline def ADTFlatOperands[T](opDef: OperationDef)(gen: T) = - ${ ADTFlatOperandsMacro[T]('{ opDef.operands }, 'gen) } +import scala.quoted.* -def ADTFlatOperandsMacro[T: Type]( - operandDefs: Expr[Iterable[OperandDef]], - adtOpExpr: Expr[T] -)(using - Quotes -) = +inline def symbolicField[T](inline obj: T, inline fieldName: String): Any = + ${ symbolicFieldImpl('obj, 'fieldName) } + +def symbolicFieldImpl[T: Type](obj: Expr[T], fieldName: Expr[String])(using Quotes): Expr[Any] = { import quotes.reflect.* - val operands_exprs = '{ - ListType.from( - ${ operandDefs }.map((o: OperandDef) => - ${ - Select( - adtOpExpr.asTerm, - adtOpExpr.asTerm.tpe.typeSymbol.fieldMember(o.name) - ).asExprOf[Operand[Attribute]] - } - ) - ) + fieldName.value match { + case Some(name) => + val symbol = obj.asTerm.tpe.typeSymbol.fieldMember(name) + Select(obj.asTerm, symbol).asExpr + case None => + report.errorAndAbort(s"Field name ${fieldName.show} must be a known string at compile-time") } +} - operands_exprs +inline def ADTFlatInput[Def <: OpInputDef, T]( + inline opInputDefs: Seq[Def], inline gen: T): ListType[DefinedInput[Def]] = + ${ ADTFlatInputMacro('opInputDefs, 'gen) } - // extracting operand instances from the ADT - // '{ ListType.from($operandDefs.map {${ (o : OperandDef) => - // Select.unique(adtOpExpr.asTerm, o.name).asExpr .asInstanceOf[Operand[Attribute]] }) } +def ADTFlatInputMacro[Def <: OpInputDef, T: Type]( + opInputDefs: Expr[Seq[Def]], + adtOpExpr: Expr[T] +)(using Quotes)(using Type[Def]): Expr[ListType[DefinedInput[Def]]] = { + import quotes.reflect.* + val inputs = '{${opInputDefs}.map((d : Def) => symbolicField(${adtOpExpr}, d.name)).asInstanceOf[Seq[DefinedInput[Def]]]} + '{ListType(${inputs}: _*)} +} -inline def fromADTOperation[T](opDef: OperationDef)(gen: T): UnverifiedOp[T] = - ${ fromADTOperationMacro[T]('opDef, '{ ADTFlatOperands(opDef)(gen) }, 'gen) } +inline def fromADTOperation[T](inline opDef: OperationDef)(inline gen: T): UnverifiedOp[T] = + ${ fromADTOperationMacro[T]('opDef, '{ ADTFlatInput(opDef.operands, gen) }, 'gen) } def fromADTOperationMacro[T: Type]( opDef: Expr[OperationDef], @@ -1006,11 +1006,10 @@ trait MLIRTrait[T] extends MLIRTraitI[T] { object MLIRTrait { inline def derived[T](using m: Mirror.ProductOf[T]): MLIRTrait[T] = - val opDef = getDef[T] new MLIRTrait[T]: - def getName: String = opDef.name + def getName: String = getDef[T].name def constructUnverifiedOp( operands: ListType[Value[Attribute]] = ListType(), @@ -1022,7 +1021,7 @@ object MLIRTrait { dictionaryAttributes: DictType[String, Attribute] = DictType.empty[String, Attribute] ): UnverifiedOp[T] = - constructUnverifiedOpHook(opDef)( + constructUnverifiedOpHook(getDef[T])( operands, successors, results_types, @@ -1032,7 +1031,7 @@ object MLIRTrait { ) def unverify(adtOp: T): UnverifiedOp[T] = - fromADTOperation[T](opDef)(adtOp) + fromADTOperation[T](getDef[T])(adtOp) def verify(unverOp: UnverifiedOp[T]): T = fromUnverifiedOperation[T](unverOp) From 714e2665f8e5baa5e1e095f01f973735b0d4833e Mon Sep 17 00:00:00 2001 From: Emilien Bauer Date: Sat, 22 Mar 2025 16:12:27 +0000 Subject: [PATCH 4/9] OpDef Macro. --- clairV2/src/main/scala-3/CV2Mirror.scala | 144 ++++++++++------------- 1 file changed, 59 insertions(+), 85 deletions(-) diff --git a/clairV2/src/main/scala-3/CV2Mirror.scala b/clairV2/src/main/scala-3/CV2Mirror.scala index 513cbba..62c076c 100644 --- a/clairV2/src/main/scala-3/CV2Mirror.scala +++ b/clairV2/src/main/scala-3/CV2Mirror.scala @@ -9,6 +9,7 @@ import scala.deriving._ import scala.Tuple.Zip import scala.collection.View.Empty +import scala.quoted._ // ░█████╗░ ██╗░░░░░ ░█████╗░ ██╗ ██████╗░ ██╗░░░██╗ ██████╗░ // ██╔══██╗ ██║░░░░░ ██╔══██╗ ██║ ██╔══██╗ ██║░░░██║ ╚════██╗ @@ -43,62 +44,56 @@ inline def inputVariadicity[Elem] = inline erasedValue[Elem] match * Input to OperationDef, either: OperandDef, ResultDef, RegionDef, * SuccessorDef, OpPropertyDef, OpAttributeDef */ -inline def getDefInput[Label, Elem]: OpInputDef = { +def getDefInput[Label : Type, Elem : Type](using Quotes): OpInputDef = { + val name = Type.of[Label] match + case '[String] => + Type.valueOfConstant[Label].get.asInstanceOf[String] - val name = inline erasedValue[Label] match - case _: String => constValue[Label].asInstanceOf[String] - case _ => - throw new Exception("Internal error!") - - inline erasedValue[Elem] match - case _: Variadic[Operand[t]] => + Type.of[Elem] match + case '[Variadic[Operand[t]]] => OperandDef( name = name, typeString = typeToString[t], Variadicity.Variadic ) - case _: Variadic[Result[t]] => + case '[Variadic[Result[t]]] => OperandDef( name = name, typeString = typeToString[t], Variadicity.Variadic ) - case _: Result[t] => + case '[Result[t]] => ResultDef( name = name, typeString = typeToString[t], Variadicity.Single ) - case _: Operand[t] => + case '[Operand[t]] => OperandDef( name = name, typeString = typeToString[t], Variadicity.Single ) - case _: Region => + case '[Region] => RegionDef( name = name, Variadicity.Single ) - case _: Successor => + case '[Successor] => SuccessorDef( name = name, Variadicity.Single ) - case _: Property[t] => + case '[Property[t]] => OpPropertyDef( name = name, typeString = typeToString[t] ) - case _: Attr[t] => + case '[Attr[t]] => OpAttributeDef( name = name, typeString = typeToString[t] ) - case _ => - throw new Exception( - s"Unsupported shennaigans here with field $name of type ${typeToString[Elem]}" - ) } /** Loops through a Tuple of Input definitions and produces a List of inputs to @@ -107,12 +102,12 @@ inline def getDefInput[Label, Elem]: OpInputDef = { * @return * Lambda that produces an input to OperationDef, given a string */ -inline def summonInput[Labels <: Tuple, Elems <: Tuple]: List[OpInputDef] = { +def summonInput[Labels : Type, Elems : Type](using Quotes): List[OpInputDef] = { - inline erasedValue[(Labels, Elems)] match - case _: ((label *: labels, elem *: elems)) => + Type.of[(Labels, Elems)] match + case '[(label *: labels, elem *: elems)] => getDefInput[label, elem] :: summonInput[labels, elems] - case _: (EmptyTuple, EmptyTuple) => Nil + case '[(EmptyTuple, EmptyTuple)] => Nil } /** Translates a Tuple of string types into a list of strings. @@ -120,12 +115,12 @@ inline def summonInput[Labels <: Tuple, Elems <: Tuple]: List[OpInputDef] = { * @return * Tuple of String types */ -inline def stringifyLabels[Elems <: Tuple]: List[String] = { +def stringifyLabels[Elems : Type](using Quotes): List[String] = { - inline erasedValue[Elems] match - case _: (elem *: elems) => - constValue[elem].asInstanceOf[String] :: stringifyLabels[elems] - case _: EmptyTuple => Nil + Type.of[Elems] match + case '[elem *: elems] => + Type.valueOfConstant[elem].get.asInstanceOf[String] :: stringifyLabels[elems] + case '[EmptyTuple] => Nil } inline def getMLIRName[T] = inline erasedValue[T] match @@ -142,60 +137,39 @@ inline def getMLIRName[T] = inline erasedValue[T] match * @return * Lambda that produces an Operadtion Def given a dialect name. */ -inline def getDef[T](using - m: Mirror.ProductOf[T] -): OperationDef = { - - val defname = constValue[m.MirroredLabel] - val paramLabels = stringifyLabels[m.MirroredElemLabels] - - val inputs = summonInput[m.MirroredElemLabels, m.MirroredElemTypes] - - val operands: ListType[OperandDef] = ListType() - val results: ListType[ResultDef] = ListType() - val regions: ListType[RegionDef] = ListType() - val successors: ListType[SuccessorDef] = ListType() - val opProperty: ListType[OpPropertyDef] = ListType() - val opAttribute: ListType[OpAttributeDef] = ListType() - var assembly_format: Option[String] = None - - for (input <- inputs) yield input match { - case a: OperandDef => operands += a - case b: ResultDef => results += b - case c: RegionDef => regions += c - case d: SuccessorDef => successors += d - case e: OpPropertyDef => opProperty += e - case f: OpAttributeDef => opAttribute += f - case _ => throw new Exception("Internal error!") - } - - val name = getMLIRName[T] - - OperationDef( - name, - defname, - operands.toSeq, - results.toSeq, - regions.toSeq, - successors.toSeq, - opProperty.toSeq, - opAttribute.toSeq, - assembly_format - ) - -} - -/** Generates a list of OperationDef given enum cases. - * - * @param dialect_name - */ -inline def summonOperationDefs[Prods <: Tuple]: Seq[OperationDef] = { - - inline erasedValue[Prods] match - case _: (prod *: prods) => - getDef[prod](using - summonInline[Mirror.ProductOf[prod]] - ) +: summonOperationDefs[prods] - - case _: EmptyTuple => Seq.empty -} +// inline def getDef[T](using + // m: Mirror.ProductOf[T]) : OperationDef = ${ getDefImpl[T] } + +def getDefImpl[T : Type](using quotes : Quotes): OperationDef = + + val m = Expr.summon[Mirror.ProductOf[T]].get + m match + case '{$m : Mirror.ProductOf[T]{ type MirroredLabel = label; type MirroredElemLabels = elemLabels; type MirroredElemTypes = elemTypes}} => + // val defname = constValue[m.MirroredLabel] + val defname = Type.valueOfConstant[label].get.asInstanceOf[String] + + val paramLabels = stringifyLabels[elemLabels] + val name = Type.of[T] match + case '[MLIRName[name]] => Type.valueOfConstant[name].get.asInstanceOf[String] + + + // val inputs = summonInput[m.MirroredElemLabels, m.MirroredElemTypes] + val inputs = Type.of[(elemLabels, elemTypes)] match + case _: Type[(Tuple, Tuple)] => summonInput[elemLabels, elemTypes] + val e = OperationDef( + name = name, + className = defname, + operands = inputs.collect { case a: OperandDef => a }, + results = inputs.collect { case a: ResultDef => a }, + regions = inputs.collect { case a: RegionDef => a }, + successors = inputs.collect { case a: SuccessorDef => a }, + properties = inputs.collect { case a: OpPropertyDef => a }, + attributes = inputs.collect { case a: OpAttributeDef => a }, + assembly_format = None + ) + e + +inline def getNameDefBlaBla[T] = ${getNameDefBlaBlaImpl[T]} + +def getNameDefBlaBlaImpl[T : Type](using quotes : Quotes): Expr[String] = + Expr(getDefImpl[T].name) From 82224eb592e8cb19dc8f106a96e4ca5d7ab9cbc9 Mon Sep 17 00:00:00 2001 From: Emilien Bauer Date: Sun, 23 Mar 2025 12:51:10 +0000 Subject: [PATCH 5/9] COmpiling, remains runtime bugs. --- clairV2/src/main/scala-3/CodeGen.scala | 18 +-- clairV2/src/main/scala-3/Macros.scala | 166 +++++-------------------- 2 files changed, 40 insertions(+), 144 deletions(-) diff --git a/clairV2/src/main/scala-3/CodeGen.scala b/clairV2/src/main/scala-3/CodeGen.scala index cc998b7..215e96d 100644 --- a/clairV2/src/main/scala-3/CodeGen.scala +++ b/clairV2/src/main/scala-3/CodeGen.scala @@ -25,6 +25,8 @@ import scair.ir._ sealed trait OpInputDef(val name:String) {} +sealed trait MayVariadicOpInputDef(val variadicity : Variadicity) extends OpInputDef + // TODO: Add support for optionals AFTER variadic support is laid out // It really just adds cognitive noise otherwise IMO. The broader structure and logic is exactly the same. // (An Optional structurally is just a Variadic capped at one.) @@ -44,24 +46,24 @@ type DefinedInput[T <: OpInputDef] = T match { case class OperandDef( override val name: String, val typeString: String, - val variadicity: Variadicity = Variadicity.Single -) extends OpInputDef(name) {} + override val variadicity: Variadicity = Variadicity.Single +) extends OpInputDef(name) with MayVariadicOpInputDef(variadicity) {} case class ResultDef( override val name: String, val typeString: String, - val variadicity: Variadicity = Variadicity.Single -) extends OpInputDef(name) {} + override val variadicity: Variadicity = Variadicity.Single +) extends OpInputDef(name) with MayVariadicOpInputDef(variadicity) {} case class RegionDef( override val name: String, - val variadicity: Variadicity = Variadicity.Single -) extends OpInputDef(name) {} + override val variadicity: Variadicity = Variadicity.Single +) extends OpInputDef(name) with MayVariadicOpInputDef(variadicity) {} case class SuccessorDef( override val name: String, - val variadicity: Variadicity = Variadicity.Single -) extends OpInputDef(name) {} + override val variadicity: Variadicity = Variadicity.Single +) extends OpInputDef(name) with MayVariadicOpInputDef(variadicity) {} case class OpPropertyDef( override val name: String, diff --git a/clairV2/src/main/scala-3/Macros.scala b/clairV2/src/main/scala-3/Macros.scala index a76dffa..a17908d 100644 --- a/clairV2/src/main/scala-3/Macros.scala +++ b/clairV2/src/main/scala-3/Macros.scala @@ -8,7 +8,7 @@ import scair.dialects.builtin.* import scala.collection.mutable.ListBuffer import scala.compiletime._ -import scair.clairV2.mirrored.getDef +import scair.clairV2.mirrored.getDefImpl import scala.deriving.Mirror import scair.clairV2.codegen._ @@ -41,60 +41,6 @@ def getClassPathImpl[T: Type](using Quotes): Expr[String] = { Expr(classPath) } -/*≡==--==≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡==--=≡≡*\ -|| Hook for UnverifiedOp Constructor || -\*≡==---==≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡==---==≡*/ - -inline def constructUnverifiedOpHook[T](opDef: OperationDef)( - operands: ListType[Value[Attribute]], - successors: ListType[scair.ir.Block], - results_types: ListType[Attribute], - regions: ListType[Region], - dictionaryProperties: DictType[String, Attribute], - dictionaryAttributes: DictType[String, Attribute] -): UnverifiedOp[T] = - ${ - constructUnverifiedOpHookMacro[T]( - 'opDef, - 'operands, - 'successors, - 'results_types, - 'regions, - 'dictionaryProperties, - 'dictionaryAttributes - ) - } - -def getNameLowerImpl[T: Type](using Quotes): Expr[String] = { - import quotes.reflect.* - val typeRepr = TypeRepr.of[T] - Expr(typeRepr.typeSymbol.name.toLowerCase()) -} - -inline def getNameLower[T]: String = ${ getNameLowerImpl[T] } - -def constructUnverifiedOpHookMacro[T: Type]( - opDef: Expr[OperationDef], - operands: Expr[ListType[Value[Attribute]]], - successors: Expr[ListType[scair.ir.Block]], - results_types: Expr[ListType[Attribute]], - regions: Expr[ListType[Region]], - dictionaryProperties: Expr[DictType[String, Attribute]], - dictionaryAttributes: Expr[DictType[String, Attribute]] -)(using Quotes): Expr[UnverifiedOp[T]] = { - import quotes.reflect.* - '{ - UnverifiedOp[T]( - name = ${ opDef }.name, - operands = $operands, - successors = $successors, - results_types = $results_types, - regions = $regions, - dictionaryProperties = $dictionaryProperties, - dictionaryAttributes = $dictionaryAttributes - ) - } -} /*≡==--==≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡==--=≡≡*\ || ADT to Unverified conversion Macro || @@ -117,25 +63,21 @@ def symbolicFieldImpl[T: Type](obj: Expr[T], fieldName: Expr[String])(using Quot } } -inline def ADTFlatInput[Def <: OpInputDef, T]( - inline opInputDefs: Seq[Def], inline gen: T): ListType[DefinedInput[Def]] = - ${ ADTFlatInputMacro('opInputDefs, 'gen) } - -def ADTFlatInputMacro[Def <: OpInputDef, T: Type]( - opInputDefs: Expr[Seq[Def]], +def ADTFlatInputMacro[Def <: OpInputDef : Type, T: Type]( + opInputDefs: Seq[Def], adtOpExpr: Expr[T] -)(using Quotes)(using Type[Def]): Expr[ListType[DefinedInput[Def]]] = { +)(using Quotes): Expr[ListType[DefinedInput[Def]]] = { import quotes.reflect.* - val inputs = '{${opInputDefs}.map((d : Def) => symbolicField(${adtOpExpr}, d.name)).asInstanceOf[Seq[DefinedInput[Def]]]} - '{ListType(${inputs}: _*)} + val stuff = Expr.ofList(opInputDefs.map((d : Def ) => (d match + case d: MayVariadicOpInputDef if (d.variadicity == Variadicity.Variadic) => + symbolicFieldImpl(adtOpExpr, Expr(d.name)) + case _ => '{Seq(${symbolicFieldImpl(adtOpExpr, Expr(d.name)).asExprOf[DefinedInput[Def]]})} + ).asExprOf[Seq[DefinedInput[Def]]])) + '{ListType.from(${stuff}.flatten)} } -inline def fromADTOperation[T](inline opDef: OperationDef)(inline gen: T): UnverifiedOp[T] = - ${ fromADTOperationMacro[T]('opDef, '{ ADTFlatInput(opDef.operands, gen) }, 'gen) } - def fromADTOperationMacro[T: Type]( - opDef: Expr[OperationDef], - flatOperands: Expr[ListType[Value[Attribute]]], + opDef: OperationDef, adtOpExpr: Expr[T] )(using Quotes @@ -153,56 +95,7 @@ def fromADTOperationMacro[T: Type]( /*______________*\ \*-- OPERANDS --*/ - // partitioning ADT parameters by Operand - val (operandParams, restParams0) = params.partition { sym => - sym.termRef.widenTermRefByName match - case AppliedType(_, List(AppliedType(tycon, _))) => - tycon =:= TypeRepr.of[Operand] - case AppliedType(tycon, _) => - tycon =:= TypeRepr.of[Operand] - case _ => false - } - - // extracting operand instances from the ADT - val operandExprs = - Expr.ofList( - operandParams - .map { param => - param.termRef.widenTermRefByName match { - case AppliedType(_, List(AppliedType(tycon, _))) => - val select = Select - .unique(adtOpExpr.asTerm, param.name) - .asExprOf[Seq[Operand[Attribute]]] - select - case AppliedType(tycon, _) => - val select = Select - .unique(adtOpExpr.asTerm, param.name) - .asExprOf[Operand[Attribute]] - select - case _ => report.errorAndAbort("this really should not happen") - } - } - ) - - // TODO: refactor this, becuase what is this - // constructing a sequence of operands to construct the UnverifiedOp with - val operandSeqExpr = '{ - val opers = $operandExprs - val what = opers - .map { x => - x match { - case a: Operand[Attribute] => Seq(a) - case x: Seq[Operand[Attribute]] => x - } - } - .flatten - .toSeq - - if (opers.isEmpty) - ListType.empty[Operand[Attribute]] - else - ListType[Operand[Attribute]](what: _*) - } + val flatOperands = ADTFlatInputMacro(opDef.operands, adtOpExpr) /*________________*\ \*-- SUCCESSORS --*/ @@ -337,7 +230,7 @@ def fromADTOperationMacro[T: Type]( '{ val x = UnverifiedOp[T]( - name = ${ opDef }.name, + name = ${Expr(opDef.name)}, operands = $flatOperands, successors = $successorSeqExpr, results_types = ListType.empty[Attribute], @@ -1005,11 +898,15 @@ trait MLIRTrait[T] extends MLIRTraitI[T] { object MLIRTrait { - inline def derived[T](using m: Mirror.ProductOf[T]): MLIRTrait[T] = + inline def derived[T]: MLIRTrait[T] = ${ derivedImpl[T] } + + def derivedImpl[T: Type](using Quotes): Expr[MLIRTrait[T]] = + val opDef = getDefImpl[T] + '{ new MLIRTrait[T]: - def getName: String = getDef[T].name + def getName: String = ${Expr(opDef.name)} def constructUnverifiedOp( operands: ListType[Value[Attribute]] = ListType(), @@ -1020,32 +917,29 @@ object MLIRTrait { DictType.empty[String, Attribute], dictionaryAttributes: DictType[String, Attribute] = DictType.empty[String, Attribute] - ): UnverifiedOp[T] = - constructUnverifiedOpHook(getDef[T])( - operands, - successors, - results_types, - regions, - dictionaryProperties, - dictionaryAttributes - ) + ): UnverifiedOp[T] = UnverifiedOp[T]( + name = ${Expr(opDef.name)}, + operands = operands, + successors = successors, + results_types = results_types, + regions = regions, + dictionaryProperties = dictionaryProperties, + dictionaryAttributes = dictionaryAttributes) def unverify(adtOp: T): UnverifiedOp[T] = - fromADTOperation[T](getDef[T])(adtOp) + ${fromADTOperationMacro[T](opDef, '{adtOp})} def verify(unverOp: UnverifiedOp[T]): T = fromUnverifiedOperation[T](unverOp) extension (op: T) override def MLIRTrait: MLIRTrait[T] = this -} +}} inline def summonMLIRTraits[T <: Tuple]: Seq[MLIRTrait[_]] = inline erasedValue[T] match case _: (t *: ts) => - MLIRTrait.derived[t](using - summonInline[Mirror.ProductOf[t]] - ) +: summonMLIRTraits[ts] + MLIRTrait.derived[t] +: summonMLIRTraits[ts] case _: EmptyTuple => Seq() inline def summonDialect[T <: Tuple]( From effbf780eb6d207276c7b84ac6d2d20a68596f30 Mon Sep 17 00:00:00 2001 From: Emilien Bauer Date: Sun, 23 Mar 2025 12:52:36 +0000 Subject: [PATCH 6/9] FOrmatting & cleanup. --- clairV2/src/main/scala-3/CV2Mirror.scala | 58 +++++++------ clairV2/src/main/scala-3/CodeGen.scala | 29 ++++--- clairV2/src/main/scala-3/Macros.scala | 105 +++++++++++++---------- 3 files changed, 110 insertions(+), 82 deletions(-) diff --git a/clairV2/src/main/scala-3/CV2Mirror.scala b/clairV2/src/main/scala-3/CV2Mirror.scala index 62c076c..dd5df97 100644 --- a/clairV2/src/main/scala-3/CV2Mirror.scala +++ b/clairV2/src/main/scala-3/CV2Mirror.scala @@ -44,7 +44,7 @@ inline def inputVariadicity[Elem] = inline erasedValue[Elem] match * Input to OperationDef, either: OperandDef, ResultDef, RegionDef, * SuccessorDef, OpPropertyDef, OpAttributeDef */ -def getDefInput[Label : Type, Elem : Type](using Quotes): OpInputDef = { +def getDefInput[Label: Type, Elem: Type](using Quotes): OpInputDef = { val name = Type.of[Label] match case '[String] => Type.valueOfConstant[Label].get.asInstanceOf[String] @@ -102,7 +102,7 @@ def getDefInput[Label : Type, Elem : Type](using Quotes): OpInputDef = { * @return * Lambda that produces an input to OperationDef, given a string */ -def summonInput[Labels : Type, Elems : Type](using Quotes): List[OpInputDef] = { +def summonInput[Labels: Type, Elems: Type](using Quotes): List[OpInputDef] = { Type.of[(Labels, Elems)] match case '[(label *: labels, elem *: elems)] => @@ -115,11 +115,14 @@ def summonInput[Labels : Type, Elems : Type](using Quotes): List[OpInputDef] = { * @return * Tuple of String types */ -def stringifyLabels[Elems : Type](using Quotes): List[String] = { +def stringifyLabels[Elems: Type](using Quotes): List[String] = { Type.of[Elems] match case '[elem *: elems] => - Type.valueOfConstant[elem].get.asInstanceOf[String] :: stringifyLabels[elems] + Type + .valueOfConstant[elem] + .get + .asInstanceOf[String] :: stringifyLabels[elems] case '[EmptyTuple] => Nil } @@ -138,38 +141,41 @@ inline def getMLIRName[T] = inline erasedValue[T] match * Lambda that produces an Operadtion Def given a dialect name. */ // inline def getDef[T](using - // m: Mirror.ProductOf[T]) : OperationDef = ${ getDefImpl[T] } +// m: Mirror.ProductOf[T]) : OperationDef = ${ getDefImpl[T] } + +def getDefImpl[T: Type](using quotes: Quotes): OperationDef = -def getDefImpl[T : Type](using quotes : Quotes): OperationDef = - val m = Expr.summon[Mirror.ProductOf[T]].get m match - case '{$m : Mirror.ProductOf[T]{ type MirroredLabel = label; type MirroredElemLabels = elemLabels; type MirroredElemTypes = elemTypes}} => - // val defname = constValue[m.MirroredLabel] + case '{ + $m: Mirror.ProductOf[T] { + type MirroredLabel = label; type MirroredElemLabels = elemLabels; + type MirroredElemTypes = elemTypes + } + } => val defname = Type.valueOfConstant[label].get.asInstanceOf[String] - + val paramLabels = stringifyLabels[elemLabels] val name = Type.of[T] match - case '[MLIRName[name]] => Type.valueOfConstant[name].get.asInstanceOf[String] - + case '[MLIRName[name]] => + Type.valueOfConstant[name].get.asInstanceOf[String] - // val inputs = summonInput[m.MirroredElemLabels, m.MirroredElemTypes] val inputs = Type.of[(elemLabels, elemTypes)] match - case _: Type[(Tuple, Tuple)] => summonInput[elemLabels, elemTypes] + case _: Type[(Tuple, Tuple)] => summonInput[elemLabels, elemTypes] val e = OperationDef( - name = name, - className = defname, - operands = inputs.collect { case a: OperandDef => a }, - results = inputs.collect { case a: ResultDef => a }, - regions = inputs.collect { case a: RegionDef => a }, - successors = inputs.collect { case a: SuccessorDef => a }, - properties = inputs.collect { case a: OpPropertyDef => a }, - attributes = inputs.collect { case a: OpAttributeDef => a }, - assembly_format = None - ) + name = name, + className = defname, + operands = inputs.collect { case a: OperandDef => a }, + results = inputs.collect { case a: ResultDef => a }, + regions = inputs.collect { case a: RegionDef => a }, + successors = inputs.collect { case a: SuccessorDef => a }, + properties = inputs.collect { case a: OpPropertyDef => a }, + attributes = inputs.collect { case a: OpAttributeDef => a }, + assembly_format = None + ) e -inline def getNameDefBlaBla[T] = ${getNameDefBlaBlaImpl[T]} +inline def getNameDefBlaBla[T] = ${ getNameDefBlaBlaImpl[T] } -def getNameDefBlaBlaImpl[T : Type](using quotes : Quotes): Expr[String] = +def getNameDefBlaBlaImpl[T: Type](using quotes: Quotes): Expr[String] = Expr(getDefImpl[T].name) diff --git a/clairV2/src/main/scala-3/CodeGen.scala b/clairV2/src/main/scala-3/CodeGen.scala index 215e96d..91529c9 100644 --- a/clairV2/src/main/scala-3/CodeGen.scala +++ b/clairV2/src/main/scala-3/CodeGen.scala @@ -23,9 +23,10 @@ import scair.ir._ || CONTAINERS || \*≡=--==≡≡==--=≡*/ -sealed trait OpInputDef(val name:String) {} +sealed trait OpInputDef(val name: String) {} -sealed trait MayVariadicOpInputDef(val variadicity : Variadicity) extends OpInputDef +sealed trait MayVariadicOpInputDef(val variadicity: Variadicity) + extends OpInputDef // TODO: Add support for optionals AFTER variadic support is laid out // It really just adds cognitive noise otherwise IMO. The broader structure and logic is exactly the same. @@ -35,35 +36,39 @@ enum Variadicity { } type DefinedInput[T <: OpInputDef] = T match { - case OperandDef => Operand[Attribute] - case ResultDef => Result[Attribute] - case RegionDef => Region - case SuccessorDef => Successor - case OpPropertyDef => Property[Attribute] - case OpAttributeDef => Attribute + case OperandDef => Operand[Attribute] + case ResultDef => Result[Attribute] + case RegionDef => Region + case SuccessorDef => Successor + case OpPropertyDef => Property[Attribute] + case OpAttributeDef => Attribute } case class OperandDef( override val name: String, val typeString: String, override val variadicity: Variadicity = Variadicity.Single -) extends OpInputDef(name) with MayVariadicOpInputDef(variadicity) {} +) extends OpInputDef(name) + with MayVariadicOpInputDef(variadicity) {} case class ResultDef( override val name: String, val typeString: String, override val variadicity: Variadicity = Variadicity.Single -) extends OpInputDef(name) with MayVariadicOpInputDef(variadicity) {} +) extends OpInputDef(name) + with MayVariadicOpInputDef(variadicity) {} case class RegionDef( override val name: String, override val variadicity: Variadicity = Variadicity.Single -) extends OpInputDef(name) with MayVariadicOpInputDef(variadicity) {} +) extends OpInputDef(name) + with MayVariadicOpInputDef(variadicity) {} case class SuccessorDef( override val name: String, override val variadicity: Variadicity = Variadicity.Single -) extends OpInputDef(name) with MayVariadicOpInputDef(variadicity) {} +) extends OpInputDef(name) + with MayVariadicOpInputDef(variadicity) {} case class OpPropertyDef( override val name: String, diff --git a/clairV2/src/main/scala-3/Macros.scala b/clairV2/src/main/scala-3/Macros.scala index a17908d..2649e48 100644 --- a/clairV2/src/main/scala-3/Macros.scala +++ b/clairV2/src/main/scala-3/Macros.scala @@ -41,7 +41,6 @@ def getClassPathImpl[T: Type](using Quotes): Expr[String] = { Expr(classPath) } - /*≡==--==≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡==--=≡≡*\ || ADT to Unverified conversion Macro || \*≡==---==≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡==---==≡*/ @@ -49,9 +48,11 @@ def getClassPathImpl[T: Type](using Quotes): Expr[String] = { import scala.quoted.* inline def symbolicField[T](inline obj: T, inline fieldName: String): Any = - ${ symbolicFieldImpl('obj, 'fieldName) } + ${ symbolicFieldImpl('obj, 'fieldName) } -def symbolicFieldImpl[T: Type](obj: Expr[T], fieldName: Expr[String])(using Quotes): Expr[Any] = { +def symbolicFieldImpl[T: Type](obj: Expr[T], fieldName: Expr[String])(using + Quotes +): Expr[Any] = { import quotes.reflect.* fieldName.value match { @@ -59,21 +60,34 @@ def symbolicFieldImpl[T: Type](obj: Expr[T], fieldName: Expr[String])(using Quot val symbol = obj.asTerm.tpe.typeSymbol.fieldMember(name) Select(obj.asTerm, symbol).asExpr case None => - report.errorAndAbort(s"Field name ${fieldName.show} must be a known string at compile-time") + report.errorAndAbort( + s"Field name ${fieldName.show} must be a known string at compile-time" + ) } } -def ADTFlatInputMacro[Def <: OpInputDef : Type, T: Type]( +def ADTFlatInputMacro[Def <: OpInputDef: Type, T: Type]( opInputDefs: Seq[Def], adtOpExpr: Expr[T] )(using Quotes): Expr[ListType[DefinedInput[Def]]] = { import quotes.reflect.* - val stuff = Expr.ofList(opInputDefs.map((d : Def ) => (d match - case d: MayVariadicOpInputDef if (d.variadicity == Variadicity.Variadic) => - symbolicFieldImpl(adtOpExpr, Expr(d.name)) - case _ => '{Seq(${symbolicFieldImpl(adtOpExpr, Expr(d.name)).asExprOf[DefinedInput[Def]]})} - ).asExprOf[Seq[DefinedInput[Def]]])) - '{ListType.from(${stuff}.flatten)} + val stuff = Expr.ofList( + opInputDefs.map((d: Def) => + (d match + case d: MayVariadicOpInputDef + if (d.variadicity == Variadicity.Variadic) => + symbolicFieldImpl(adtOpExpr, Expr(d.name)) + case _ => + '{ + Seq(${ + symbolicFieldImpl(adtOpExpr, Expr(d.name)) + .asExprOf[DefinedInput[Def]] + }) + } + ).asExprOf[Seq[DefinedInput[Def]]] + ) + ) + '{ ListType.from(${ stuff }.flatten) } } def fromADTOperationMacro[T: Type]( @@ -230,7 +244,7 @@ def fromADTOperationMacro[T: Type]( '{ val x = UnverifiedOp[T]( - name = ${Expr(opDef.name)}, + name = ${ Expr(opDef.name) }, operands = $flatOperands, successors = $successorSeqExpr, results_types = ListType.empty[Attribute], @@ -900,41 +914,44 @@ object MLIRTrait { inline def derived[T]: MLIRTrait[T] = ${ derivedImpl[T] } - def derivedImpl[T: Type](using Quotes): Expr[MLIRTrait[T]] = + def derivedImpl[T: Type](using Quotes): Expr[MLIRTrait[T]] = val opDef = getDefImpl[T] '{ - new MLIRTrait[T]: - - def getName: String = ${Expr(opDef.name)} - - def constructUnverifiedOp( - operands: ListType[Value[Attribute]] = ListType(), - successors: ListType[scair.ir.Block] = ListType(), - results_types: ListType[Attribute] = ListType(), - regions: ListType[Region] = ListType(), - dictionaryProperties: DictType[String, Attribute] = - DictType.empty[String, Attribute], - dictionaryAttributes: DictType[String, Attribute] = - DictType.empty[String, Attribute] - ): UnverifiedOp[T] = UnverifiedOp[T]( - name = ${Expr(opDef.name)}, - operands = operands, - successors = successors, - results_types = results_types, - regions = regions, - dictionaryProperties = dictionaryProperties, - dictionaryAttributes = dictionaryAttributes) - - def unverify(adtOp: T): UnverifiedOp[T] = - ${fromADTOperationMacro[T](opDef, '{adtOp})} - - def verify(unverOp: UnverifiedOp[T]): T = - fromUnverifiedOperation[T](unverOp) - - extension (op: T) override def MLIRTrait: MLIRTrait[T] = this - -}} + new MLIRTrait[T]: + + def getName: String = ${ Expr(opDef.name) } + + def constructUnverifiedOp( + operands: ListType[Value[Attribute]] = ListType(), + successors: ListType[scair.ir.Block] = ListType(), + results_types: ListType[Attribute] = ListType(), + regions: ListType[Region] = ListType(), + dictionaryProperties: DictType[String, Attribute] = + DictType.empty[String, Attribute], + dictionaryAttributes: DictType[String, Attribute] = + DictType.empty[String, Attribute] + ): UnverifiedOp[T] = UnverifiedOp[T]( + name = ${ Expr(opDef.name) }, + operands = operands, + successors = successors, + results_types = results_types, + regions = regions, + dictionaryProperties = dictionaryProperties, + dictionaryAttributes = dictionaryAttributes + ) + + def unverify(adtOp: T): UnverifiedOp[T] = + ${ fromADTOperationMacro[T](opDef, '{ adtOp }) } + + def verify(unverOp: UnverifiedOp[T]): T = + fromUnverifiedOperation[T](unverOp) + + extension (op: T) override def MLIRTrait: MLIRTrait[T] = this + + } + +} inline def summonMLIRTraits[T <: Tuple]: Seq[MLIRTrait[_]] = inline erasedValue[T] match From 8831ddcd7510a055f7c4c11689cdd94111dd1d7b Mon Sep 17 00:00:00 2001 From: Emilien Bauer Date: Sun, 23 Mar 2025 12:53:49 +0000 Subject: [PATCH 7/9] . --- clairV2/src/main/scala-3/CV2Mirror.scala | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/clairV2/src/main/scala-3/CV2Mirror.scala b/clairV2/src/main/scala-3/CV2Mirror.scala index dd5df97..0b98868 100644 --- a/clairV2/src/main/scala-3/CV2Mirror.scala +++ b/clairV2/src/main/scala-3/CV2Mirror.scala @@ -29,15 +29,6 @@ import scala.quoted._ || MIRROR LOGIC || \*≡==----=≡≡≡≡=----==≡*/ -// currently not supported, but will soon be :) -inline def inputVariadicity[Elem] = inline erasedValue[Elem] match - case _: Variadic[t] => Variadicity.Variadic - case _ => Variadicity.Single - -// for some reason match types do not work here, as an inline erasedValue[unwrappedInput[Elem]] -// tries to match on that type exactly (ie. unwrappedType[Value[IntegerType]] for example) rather than the matched type... -// very weird things going on - /** Produces an OpInput to OperationDef given a definition of a Type. * * @return @@ -133,16 +124,6 @@ inline def getMLIRName[T] = inline erasedValue[T] match "Expected this type to extend MLIRName with a constant type-parameter." ) -/** Generates a OperationDef given param m. - * - * @param m - * \- Mirror Product of an dialect enum case. - * @return - * Lambda that produces an Operadtion Def given a dialect name. - */ -// inline def getDef[T](using -// m: Mirror.ProductOf[T]) : OperationDef = ${ getDefImpl[T] } - def getDefImpl[T: Type](using quotes: Quotes): OperationDef = val m = Expr.summon[Mirror.ProductOf[T]].get From 643da5ce5d963c71f0e68c7774d64e9fd4f7e2cd Mon Sep 17 00:00:00 2001 From: Emilien Bauer Date: Sun, 23 Mar 2025 13:34:57 +0000 Subject: [PATCH 8/9] match fix --- clairV2/src/main/scala-3/CV2Mirror.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clairV2/src/main/scala-3/CV2Mirror.scala b/clairV2/src/main/scala-3/CV2Mirror.scala index 0b98868..884f041 100644 --- a/clairV2/src/main/scala-3/CV2Mirror.scala +++ b/clairV2/src/main/scala-3/CV2Mirror.scala @@ -41,13 +41,13 @@ def getDefInput[Label: Type, Elem: Type](using Quotes): OpInputDef = { Type.valueOfConstant[Label].get.asInstanceOf[String] Type.of[Elem] match - case '[Variadic[Operand[t]]] => - OperandDef( + case '[Variadic[Result[t]]] => + ResultDef( name = name, typeString = typeToString[t], Variadicity.Variadic ) - case '[Variadic[Result[t]]] => + case '[Variadic[Operand[t]]] => OperandDef( name = name, typeString = typeToString[t], From a5b795c1332faf99b529d112958a0ab061732263 Mon Sep 17 00:00:00 2001 From: Emilien Bauer Date: Sun, 23 Mar 2025 13:39:02 +0000 Subject: [PATCH 9/9] Factor other variadic constructs in. --- clairV2/src/main/scala-3/Macros.scala | 99 ++------------------------- 1 file changed, 7 insertions(+), 92 deletions(-) diff --git a/clairV2/src/main/scala-3/Macros.scala b/clairV2/src/main/scala-3/Macros.scala index 2649e48..1eb9f7b 100644 --- a/clairV2/src/main/scala-3/Macros.scala +++ b/clairV2/src/main/scala-3/Macros.scala @@ -114,108 +114,23 @@ def fromADTOperationMacro[T: Type]( /*________________*\ \*-- SUCCESSORS --*/ - // partitioning ADT parameters by Successor - val (successorParams, restParams1) = params.partition { sym => - sym.termRef.widenTermRefByName match - case tycon => tycon =:= TypeRepr.of[scair.ir.Block] - } - - // extracting successor instances from the ADT - val successorExprs = successorParams.map { param => - val select = Select.unique(adtOpExpr.asTerm, param.name).asExpr - '{ ${ select }.asInstanceOf[scair.ir.Block] } - }.toSeq - - // constructing a sequence of successors to construct the UnverifiedOp with - val successorSeqExpr = - if (successorExprs.isEmpty) '{ - ListType.empty[scair.ir.Block] - } - else - '{ - ListType[scair.ir.Block](${ Varargs(successorExprs) }: _*) - } + val flatSuccessors = ADTFlatInputMacro(opDef.successors, adtOpExpr) /*_____________*\ \*-- RESULTS --*/ - // partitioning ADT parameters by Result - val (resultParams, restParams2) = restParams1.partition { sym => - sym.termRef.widenTermRefByName match - case AppliedType(_, List(AppliedType(tycon, _))) => - tycon =:= TypeRepr.of[Result] - case AppliedType(tycon, _) => tycon =:= TypeRepr.of[Result] - case x => false - } - - val resultExprs = - Expr.ofList( - resultParams - .map { param => - param.termRef.widenTermRefByName match { - case AppliedType(_, List(AppliedType(tycon, _))) => - val select = Select - .unique(adtOpExpr.asTerm, param.name) - .asExprOf[Seq[Result[Attribute]]] - select - case AppliedType(tycon, _) => - val select = Select - .unique(adtOpExpr.asTerm, param.name) - .asExprOf[Result[Attribute]] - select - case _ => report.errorAndAbort("this really should not happen") - } - } - ) - - val resultSeqExpr = '{ - val ress = $resultExprs - val what = ress - .map { x => - x match { - case a: Result[Attribute] => Seq(a) - case x: Seq[Result[Attribute]] => x - } - } - .flatten - .toSeq - - if (ress.isEmpty) - ListType.empty[Result[Attribute]] - else - ListType[Result[Attribute]](what: _*) - } + val flatResults = ADTFlatInputMacro(opDef.results, adtOpExpr) /*_____________*\ \*-- REGIONS --*/ - // partitioning ADT parameters by Regions - val (regionParams, restParams3) = restParams2.partition { sym => - sym.termRef.widenTermRefByName match - case tycon => tycon =:= TypeRepr.of[Region] - } - - // extracting region instances from the ADT - val regionExprs = regionParams.map { param => - val select = Select.unique(adtOpExpr.asTerm, param.name).asExpr - '{ ${ select }.asInstanceOf[Region] } - }.toSeq - - // constructing a sequence of regions to construct the UnverifiedOp with - val regionSeqExpr = - if (regionExprs.isEmpty) '{ - ListType.empty[Region] - } - else - '{ - ListType[Region](${ Varargs(regionExprs) }: _*) - } + val flatRegions = ADTFlatInputMacro(opDef.regions, adtOpExpr) /*________________*\ \*-- PROPERTIES --*/ // partitioning ADT parameters by Properties - val (propertyParams, _) = restParams3.partition { sym => + val (propertyParams, _) = params.partition { sym => sym.termRef.widenTermRefByName match case AppliedType(tycon, _) => tycon =:= TypeRepr.of[Property] case x => false @@ -246,13 +161,13 @@ def fromADTOperationMacro[T: Type]( val x = UnverifiedOp[T]( name = ${ Expr(opDef.name) }, operands = $flatOperands, - successors = $successorSeqExpr, + successors = $flatSuccessors, results_types = ListType.empty[Attribute], - regions = $regionSeqExpr, + regions = $flatRegions, dictionaryProperties = $propertySeqExpr, dictionaryAttributes = DictType.empty[String, Attribute] ) - x.results.addAll($resultSeqExpr) + x.results.addAll($flatResults) x }