DelayedInit or OnCreate, any solution?

My actual usage is in a embedded DSL (SpinalHDL), it use DelayedInit/onCreate to automaticaly build a component hierarchy from the user code execution:

//embedded DSL core
object Component{
   val componentStack = mutable.Stack[Component]()
}

class Component extends OnCreate{
  val children = ArrayBuffer[Component]()
  val parent = Component.componentStack.head()
  parent.children += this

  Component.componentStack.push(this)
  
  //Automatic callback after the whole object construction
  def onCreate() = Component.componentStack.pop() 
}

//User code
class UserSubComponent extends Component{
  //behaviour code
}

class UserComponent extends Component{
  //behaviour code
  val subA = new UserSubComponent() //subA automaticaly know his parrent component via the componentStack, and it will automaticaly add itself to the UserComponent children list.
  val subB = new UserSubComponent()
}

It is also used in some other similar cases.

I do not think it is equal replacement. IIUC An ide code assistant will work much worse on complex structures.

I am sure good code assistant is a killer feature in industrial programming.

I’m dropping the usage of DelayedInit in my project by using a compiler plugin providing a equivalent functionality.

There is the user trait :

And there is the compiler plugin implementation (the case cd: ClassDef is for another feature)

For each “new XXX()” where XXX implement the PostInitCallback trait, it transform it into :
“new XXX().postInitCallback()”

So far it seem to work fine.

3 Likes

Some sort of DelayedInit replacement for scope management:

import db.Connection
@main def main():Unit = {
  val c = new Connection()
  //It is less error prone because nobody can forget  to call method and do import. 
  //And it is more easy to write
  c.execute{new{ 
    setValue(2.ss) 
  }}
}
package db
class Statement(){
  var value:String = "default value"
  def execute():Unit = println(s"value=$value")
}
class StatementBuilder(given private val  s:Statement){
  //here it can be extensions, typeclasses 
  def (v:Int)ss: String = v.toString()
  def setValue(v:String):Unit = s.value = v 
}
class Connection{
  def execute(buildStatement:(given Statement)=>StatementBuilder): Unit = {
    //before advice
    given s:Statement = new Statement()
    //dsl statement
    buildStatement
    //after advice
    s.execute()
  }
}
1 Like