All Downloads are FREE. Search and download functionalities are using the official Maven repository.

miksilo.modularLanguages.deltas.javac.classes.FieldDeclarationWithInitializer.scala Maven / Gradle / Ivy

The newest version!
package miksilo.modularLanguages.deltas.javac.classes

import miksilo.modularLanguages.core.deltas._
import miksilo.modularLanguages.core.deltas.grammars.LanguageGrammars
import miksilo.modularLanguages.core.deltas.path.{NodePath, PathRoot}
import miksilo.modularLanguages.core.node.{Node, NodeShape}
import miksilo.languageServer.core.language.{Compilation, Language}
import miksilo.modularLanguages.deltas.bytecode.types.{TypeSkeleton, VoidTypeDelta}
import miksilo.modularLanguages.deltas.expression.{ExpressionDelta, VariableDelta}
import miksilo.modularLanguages.deltas.javac.statements.ExpressionAsStatementDelta
import miksilo.modularLanguages.deltas.statement.LocalDeclarationWithInitializerDelta.LocalDeclarationWithInitializer
import miksilo.modularLanguages.deltas.statement.assignment.SimpleAssignmentDelta
import miksilo.modularLanguages.deltas.statement.{BlockDelta, LocalDeclarationWithInitializerDelta}
import miksilo.modularLanguages.deltas.HasNameDelta.Name
import miksilo.modularLanguages.deltas.classes.ClassDelta.JavaClass
import miksilo.modularLanguages.deltas.classes.constructor.{ConstructorDelta, SuperCallExpression}
import miksilo.modularLanguages.deltas.javac.classes.FieldDeclarationDelta.{Field, Type}
import miksilo.modularLanguages.deltas.javac.methods.AccessibilityFieldsDelta
import miksilo.modularLanguages.deltas.method.MethodDelta
import miksilo.modularLanguages.deltas.method.call.CallDelta

import scala.collection.immutable.ArraySeq
import scala.collection.mutable.ArrayBuffer

object FieldDeclarationWithInitializer extends DeltaWithGrammar with DeltaWithPhase {

  override def description: String = "Enables fields to have initializers."

  override def dependencies: Set[Contract] = Set(FieldDeclarationDelta)

  override def transformGrammars(grammars: LanguageGrammars, state: Language): Unit = {
    import grammars._
    val typeGrammar = find(TypeSkeleton.JavaTypeGrammar)
    val expression = find(ExpressionDelta.FirstPrecedenceGrammar)
    val fieldDeclarationGrammar = find(AccessibilityFieldsDelta.VisibilityField) ~ find(AccessibilityFieldsDelta.Static) ~
      typeGrammar.as(Type) ~~ identifier.as(Name) ~~ ("=" ~~> expression.as(LocalDeclarationWithInitializerDelta.Initializer)) ~< ";"  asNode Shape
    find(FieldDeclarationDelta.Shape).addAlternative(fieldDeclarationGrammar)
  }

  object Shape extends NodeShape

  def transformDeclarationWithInitializer(node: NodePath, initializerStatements: ArrayBuffer[Node], state: Language): Unit = {
    val localDeclaration: LocalDeclarationWithInitializer[NodePath] = node
    val field: Field[NodePath] = node
    val name: String = field.name

    val assignment = SimpleAssignmentDelta.neww(VariableDelta.neww(name), localDeclaration.initializer)
    val assignmentStatement = ExpressionAsStatementDelta.create(assignment)
    initializerStatements += assignmentStatement
    field.node.shape = FieldDeclarationDelta.Shape
    field.node.removeField(LocalDeclarationWithInitializerDelta.Initializer)
  }

  override def transformProgram(program: Node, compilation: Compilation): Unit = {
    val initializerStatements = new ArrayBuffer[Node]()
    val clazz: JavaClass[Node] = program
    PathRoot(program).visitShape(Shape, obj => transformDeclarationWithInitializer(obj, initializerStatements, compilation))

    if (initializerStatements.isEmpty)
      return

    val reversedInitializerStatements = initializerStatements.view.reverse //TODO: hack to fix the reverse hack in NodeLike.
    val fieldInitializerMethod = MethodDelta.neww(getFieldInitializerMethodName,VoidTypeDelta.voidType, Seq.empty,
      BlockDelta.neww(reversedInitializerStatements.toSeq))
    clazz.members = Seq(fieldInitializerMethod) ++ program.members

    for(constructor <- ConstructorDelta.getConstructors(program)) {
      val body = constructor.body.statements
      if (statementIsSuperCall(body.head)) {
        val bodyAfterHead = body.drop(1)
        val head = body.head
        val callToFieldInitialiser = ExpressionAsStatementDelta.create(CallDelta.neww(VariableDelta.neww(getFieldInitializerMethodName)))
        constructor.body.statements = Seq(head, callToFieldInitialiser) ++ bodyAfterHead
      }
    }
  }

  def getFieldInitializerMethodName: String = { //TODO make sure this name doesn't collide with other method names.
    "initialiseFields"
  }

  def statementIsSuperCall(statement: Node): Boolean = {
    statement.shape == ExpressionAsStatementDelta.shape &&
      ExpressionAsStatementDelta.getExpression(statement).shape == SuperCallExpression.Shape
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy