Open
Description
It took long to minimize 😢
Here is the code that demonstrates two bugs: an error and a compiler crash (see the comments at the end).
package DFiant
object Extras {
type <>[DF <: DFAny, Dir <: DFDir] = DFAny.Port[DF, Dir] with DF
//Direction of a Port
sealed trait DFDir
sealed trait IN extends DFDir
implicit object IN extends IN
sealed trait OUT extends DFDir
implicit object OUT extends OUT
////////////////////////////////////////////////////////////////////////////////////
}
import Extras._
class IfWithRetVal[RV <: DFAny, Builder[L, R] <: DFAny.Op.Builder[L, R]] {
protected[DFiant] class DFIfBlock(val cond : Boolean, block : => RV) {
def elsedf[R](elseBlock: => Unit)(implicit op : Builder[RV, R]) : RV = ???
}
def apply[R](cond: Boolean)(block: => Unit)(implicit op : Builder[RV, R]) : DFIfBlock = ???
}
trait DFAny {
type TVal <: DFAny.Unbounded[TCompanion]
type TCompanion <: DFAny.Companion
type TUnbounded = protComp.Unbounded
protected[DFiant] val protComp : TCompanion
}
object DFAny {
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Head Types
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
trait Unbounded[T <: DFAny.Companion] extends DFAny {
type TCompanion = T
}
trait Var extends DFAny {
final def <> [RDIR <: DFDir](right: TVal <> RDIR) : Unit = ???
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Abstract Constructors
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
abstract class NewVar[DF <: DFAny](
implicit cmp : Companion
) extends DFAny.Var {
final protected[DFiant] lazy val protComp : TCompanion = cmp.asInstanceOf[TCompanion]
def <> [Dir <: DFDir](dir : Dir)(implicit port : protComp.Port.Builder[TVal, Dir]) : Unit = {}
final object ifdf extends IfWithRetVal[TVal, protComp.`Op:=`.Builder]
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Port
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
abstract class Port[DF <: DFAny, Dir <: DFDir](dfVar : DF, val dir : Dir)(
implicit cmp : Companion
) extends DFAny.Var {
final protected[DFiant] lazy val protComp : TCompanion = cmp.asInstanceOf[TCompanion]
}
object Port {
trait Builder[L <: DFAny, Dir <: DFDir] {
def apply(right : L, dir : Dir) : Unit
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Op
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
object Op {
trait Builder[L, R] {
type Comp <: DFAny
def apply(left : L, rightR : R) : Comp
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Create Companion object of DFXXX extenders of DFAny
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
trait Companion {
type Unbounded <: DFAny.Unbounded[this.type]
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Port
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
trait PortCO {
type Builder[L <: DFAny, Dir <: DFDir] <: DFAny.Port.Builder[L, Dir]
}
val Port : PortCO
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Common Ops
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
trait `Op:=` {
type Builder[L, R] <: DFAny.Op.Builder[L, R]
}
val `Op:=` : `Op:=`
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
implicit val cmp = this
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
trait DFBits extends DFBits.Unbounded {
}
object DFBits extends DFAny.Companion {
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Unbounded Val
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
trait Unbounded extends DFAny.Unbounded[DFBits.type] {
type TVal = DFBits
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Var
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
trait Var extends DFBits with DFAny.Var {
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Public Constructors
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
def apply() : NewVar = ???
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Protected Constructors
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected[DFiant] final class NewVar extends DFAny.NewVar[DFBits] with Var {}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Port
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
object Port extends PortCO {
trait Builder[L <: DFAny, Dir <: DFDir] extends DFAny.Port.Builder[L, Dir]
object Builder {
implicit def conn[LW, Dir <: DFDir]
: Builder[DFBits, Dir] = ???
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Assign & Connect
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
trait `Ops:=,<>` extends `Op:=` {
@scala.annotation.implicitNotFound("Dataflow variable ${L} does not support assignment/connect operation with the type ${R}")
trait Builder[L, R] extends DFAny.Op.Builder[L, R]
object Builder {
type Aux[L, R, Comp0] = Builder[L, R] {
type Comp = Comp0
}
implicit def evDFBits_op_DFBits[LW, RW] : Aux[DFBits, DFBits, DFBits] = ???
}
}
object `Op:=` extends `Ops:=,<>`
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
trait Bugs {
val bug1 = DFBits() <> IN //error: does not take parameters
val bug2 = DFBits().ifdf(true) {} elsedf {} //compiler crash: mkAttributedQualifier(_1.type, <none>)
val workaround = DFBits()
val ok1 = workaround <> IN
val ok2 = workaround.ifdf(true) {} elsedf {}
}