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

miksilo.modularLanguages.deltas.bytecode.ByteCodeSkeleton.scala Maven / Gradle / Ivy

The newest version!
package miksilo.modularLanguages.deltas.bytecode

import miksilo.modularLanguages.core.bigrammar.BiGrammar
import miksilo.editorParser.document.Empty
import miksilo.modularLanguages.core.deltas._
import miksilo.modularLanguages.core.deltas.grammars.{BodyGrammar, LanguageGrammars}
import miksilo.modularLanguages.core.node._
import miksilo.languageServer.core.language.{Compilation, Language}
import miksilo.modularLanguages.deltas.bytecode.ByteCodeFieldInfo.FieldInfoWrapper
import miksilo.modularLanguages.deltas.bytecode.ByteCodeMethodInfo.MethodInfo
import miksilo.modularLanguages.deltas.bytecode.attributes.{AttributeNameKey, ByteCodeAttribute}
import miksilo.modularLanguages.deltas.bytecode.constants.{ClassInfoConstant, ConstantPoolEntry}
import miksilo.modularLanguages.deltas.bytecode.coreInstructions.ConstantPoolIndexGrammar
import miksilo.modularLanguages.deltas.javac.classes.ConstantPool

import scala.collection.mutable

object ByteCodeSkeleton extends DeltaWithGrammar {

  implicit class ClassFile[T <: NodeLike](val node: T) extends NodeWrapper[T] {
    def constantPool: ConstantPool = node(ClassConstantPool).asInstanceOf[ConstantPool]
    def constantPool_=(constantPool: ConstantPool): Unit = node(ClassConstantPool) = constantPool

    def parentIndex: Int = node(ClassParentIndex).asInstanceOf[Int]
    def parentIndex_=(index: Int): Unit = node(ClassParentIndex) = index

    def classInfoIndex: Int = node(ClassNameIndexKey).asInstanceOf[Int]
    def classInfoIndex_=(index: Int): Unit = node(ClassNameIndexKey) = index

    def interfaceIndices: Seq[Int] = node(ClassInterfaces).asInstanceOf[Seq[Int]]
    def interfaceIndices_=(indices: Seq[Int]): Unit = node(ClassInterfaces) = indices

    def fields: Seq[FieldInfoWrapper[T]] = NodeWrapper.wrapList(node(ClassFields).asInstanceOf[Seq[T]])

    def attributes: Seq[T] = node(ClassAttributes).asInstanceOf[Seq[T]]
    def attributes_=(value: Seq[T]) = node(ClassAttributes) = value

    def methods: Seq[MethodInfo[T]] = NodeWrapper.wrapList(node(Methods).asInstanceOf[Seq[T]])
  }

  def getAttributeNameIndex(attribute: Node) = attribute(AttributeNameKey).asInstanceOf[Int]

  def neww(name: Int, parent: Int, constantPool: ConstantPool, methods: Seq[Node], interfaces: Seq[Int] = Seq(),
           classFields: Seq[Node] = Seq(), attributes: Seq[Node] = Seq()) = new Node(Shape,
    Methods ->  methods,
    ClassNameIndexKey ->  name,
    ClassParentIndex ->  parent,
    ClassConstantPool ->  constantPool,
    ClassInterfaces ->  interfaces,
    ClassFields ->  classFields,
    ClassAttributes ->  attributes
  )

  override def dependencies: Set[Contract] = Set.empty

  trait HasBytes {
    def getBytes(compilation: Compilation, node: Node): Seq[Byte]
  }

  def getBytes(compilation: Compilation, node: Node): Seq[Byte] = hasBytes(compilation, node.shape).getBytes(compilation, node)

  val hasBytes = new ShapeProperty[HasBytes]
  val constantEntries = new ShapeProperty[ConstantPoolEntry]
  val attributesByName = new Property[mutable.HashMap[String, ByteCodeAttribute]](mutable.HashMap.empty)
  val constantReferences = new ShapeProperty[Map[NodeField, NodeShape]]

  override def inject(language: Language): Unit = {
    super.inject(language)
    constantReferences.add(language, Shape, Map(
      //TODO add with seq support //ClassInterfaces -> ClassRefConstant.key,
      ClassParentIndex -> ClassInfoConstant.shape,
      ClassNameIndexKey -> ClassInfoConstant.shape))
  }

  object Shape extends NodeShape

  object Methods extends NodeField

  object ClassNameIndexKey extends NodeField

  object ClassParentIndex extends NodeField

  object ClassConstantPool extends NodeField

  object ClassInterfaces extends NodeField

  object ClassFields extends NodeField

  object ClassAttributes extends NodeField

  object ConstantPoolItemContentGrammar extends GrammarKey

  object AttributeGrammar extends GrammarKey
  object MembersGrammar extends GrammarKey
  object AttributesGrammar extends GrammarKey
  override def transformGrammars(grammars: LanguageGrammars, state: Language): Unit = {
    val constantPool: BiGrammar = getConstantPoolGrammar(grammars)
    import grammars._

    val constantIndexGrammar = create(ConstantPoolIndexGrammar, integer)
    val attributeGrammar: BiGrammar = create(AttributeGrammar)
    val interfacesGrammar: BiGrammar = "with" ~ ":" ~~> (constantIndexGrammar *).inParenthesis
    val classIndexGrammar: BiGrammar = "class" ~~> constantIndexGrammar
    val parseIndexGrammar: BiGrammar = "extends" ~~> constantIndexGrammar
    val attributesGrammar = create(AttributesGrammar, attributeGrammar.manyVertical)
    val membersGrammar = create(MembersGrammar, print(Empty))
    val bodyGrammar = "{" % (membersGrammar % attributesGrammar.as(ClassAttributes)).indent() % "}"
    val classGrammar = create(Shape,
      (classIndexGrammar.as(ClassNameIndexKey) ~~ parseIndexGrammar.as(ClassParentIndex) ~~ interfacesGrammar.as(ClassInterfaces) %
        constantPool % bodyGrammar).asNode(Shape))

    find(BodyGrammar).inner = classGrammar
  }

  object ConstantPoolGrammar extends GrammarKey

  def getConstantPoolGrammar(grammars: LanguageGrammars): BiGrammar = {
    import grammars._
    val constantPoolItemContent = create(ConstantPoolItemContentGrammar)
    val entries = constantPoolItemContent.manyVertical.indent()
    val result = "ConstantPool" ~ ":" %> entries.map[Seq[Any], ConstantPool] (
      entries => new ConstantPool(entries),
      constantPool => constantPool.constants.toSeq)
    create(ConstantPoolGrammar, result.as(ClassConstantPool))
  }

  override def description: String = "Defines a skeleton for bytecode."
}








© 2015 - 2024 Weber Informatics LLC | Privacy Policy