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

miksilo.modularLanguages.deltas.method.MethodDelta.scala Maven / Gradle / Ivy

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

import miksilo.modularLanguages.core.bigrammar.BiGrammar
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._
import miksilo.languageServer.core.language.{Compilation, CompilationField, Language}
import miksilo.languageServer.core.smarts.ConstraintBuilder
import miksilo.languageServer.core.smarts.objects.Declaration
import miksilo.languageServer.core.smarts.scopes.objects.{ConcreteScope, Scope}
import miksilo.modularLanguages.deltas.ConstraintSkeleton
import miksilo.modularLanguages.deltas.bytecode.extraConstants.TypeConstant
import miksilo.modularLanguages.deltas.bytecode.types.{TypeSkeleton, VoidTypeDelta}
import miksilo.modularLanguages.deltas.classes.ClassDelta.JavaClass
import miksilo.modularLanguages.deltas.classes.HasConstraintsDelta
import miksilo.modularLanguages.deltas.javac.classes.{ClassCompiler, MethodInfo}
import miksilo.modularLanguages.deltas.javac.classes.skeleton.{ClassSignature, HasDeclarationDelta, JavaClassDelta, MethodClassKey}
import miksilo.modularLanguages.deltas.javac.methods.{AccessibilityFieldsDelta, MethodCompiler, MethodParameters}
import miksilo.modularLanguages.deltas.javac.methods.AccessibilityFieldsDelta.{HasAccessibility, PrivateVisibility}
import miksilo.modularLanguages.deltas.javac.methods.MethodParameters.MethodParameter
import miksilo.modularLanguages.deltas.javac.types.{MethodTypeDelta, TypeAbstraction}
import miksilo.modularLanguages.deltas.statement.{BlockDelta, LabelStatementDelta}
import miksilo.modularLanguages.deltas.statement.BlockDelta.BlockStatement

object MethodDelta extends DeltaWithGrammar
  with HasDeclarationDelta with HasConstraintsDelta with HasShape {

  import miksilo.modularLanguages.deltas.HasNameDelta._

  override def description: String = "Enables Java classes to contain methods."

  implicit class Method[T <: NodeLike](val node: T) extends HasAccessibility[T] with HasName[T] {

    def returnType: T = node(ReturnType).asInstanceOf[T]
    def returnType_=(value: T): Unit = node(ReturnType) = value

    def parameters: Seq[MethodParameter[T]] = NodeWrapper.wrapList(node(Parameters).asInstanceOf[Seq[T]])
    def parameters_=(value: Seq[MethodParameter[T]]): Unit = node(Parameters) = NodeWrapper.unwrapList(value)

    def body: BlockStatement[T] = node(Body).asInstanceOf[T]
  }

  def bind(compilation: Compilation, signature: ClassSignature, method: Method[Node]): Unit = {
    val classCompiler = JavaClassDelta.getClassCompiler(compilation)
    val classInfo = classCompiler.currentClassInfo

    val methodName: String = MethodDelta.getMethodName(method)
    val parameters = method.parameters
    val parameterTypes = parameters.map(p => getParameterType(PathRoot(p), classCompiler))
    val _type = getMethodType(method)
    val key = MethodClassKey(methodName, parameterTypes.toVector)
    classInfo.methods(key) = MethodInfo(_type, method.isStatic)
  }

  def getMethodType[T <: NodeLike](method: Method[T]) = {
    val parameterTypes = method.parameters.map(p => p(MethodParameters.Type).asInstanceOf[T].asNode)
    MethodTypeDelta.neww(method.returnType.asNode, parameterTypes)
  }

  override def dependencies: Set[Contract] = Set(BlockDelta, AccessibilityFieldsDelta)

  def getParameterType(parameter: MethodParameter[NodePath], classCompiler: ClassCompiler): Node = {
    val result = parameter._type
    result
  }

  def getMethodDescriptor(method: Method[Node], classCompiler: ClassCompiler): Node = {
    TypeConstant.constructor(getMethodType(method))
  }


  def setMethodCompiler(method: Node, compilation: Compilation): Unit = {
    state(compilation) = MethodCompiler(compilation, method)
  }

  def getMethodCompiler(compilation: Compilation) = state(compilation)

  def getMethodName(method: Node) = {
    method(Name).asInstanceOf[String]
  }

  def getMethods[T <: NodeLike](javaClass: JavaClass[T]): Seq[Method[T]] =
    NodeWrapper.wrapList(javaClass.members.filter(member => member.shape == Shape))

  object ReturnTypeGrammar extends GrammarKey

  override def transformGrammars(grammars: LanguageGrammars, state: Language): Unit =  {
    val _grammars = grammars
    import grammars._
    val block = find(BlockDelta.BlockGrammar)

    val parseType = find(TypeSkeleton.JavaTypeGrammar)
    val parseReturnType = create(ReturnTypeGrammar, parseType)

    val parseParameter = MethodParameters.getGrammar(_grammars)
    val parseParameters = create(Parameters, "(" ~> parseParameter.manySeparated(",") ~< ")")

    val typeParametersGrammar: BiGrammar = find(TypeAbstraction.TypeParametersGrammar)

    val methodUnmapped: BiGrammar = find(AccessibilityFieldsDelta.VisibilityField) ~
      find(AccessibilityFieldsDelta.Static) ~ typeParametersGrammar.as(TypeParameters) ~
      parseReturnType.as(ReturnType) ~~ find(Name) ~ parseParameters.as(Parameters) % block.as(Body)
    create(Shape, methodUnmapped.asNode(Shape))
  }

  def neww(name: String, _returnType: Any, _parameters: Seq[Node], _body: Node,
           static: Boolean = false,
           visibility: AccessibilityFieldsDelta.Visibility = PrivateVisibility,
           typeParameters: Seq[Node] = Seq.empty): Node = {
    new Node(Shape,
      Name -> name,
      ReturnType -> _returnType,
      Parameters -> _parameters,
      Body -> _body,
      AccessibilityFieldsDelta.Static -> static,
      AccessibilityFieldsDelta.VisibilityField -> visibility,
      TypeParameters -> typeParameters)
  }

  val state = new CompilationField[MethodCompiler](null)

  object Shape extends NodeShape

  object Body extends NodeField

  object ReturnType extends NodeField

  object Parameters extends NodeField

  object TypeParameters extends NodeField

  override def getDeclaration(compilation: Compilation, builder: ConstraintBuilder, path: NodePath, parentScope: Scope): Declaration = {
    val method: Method[NodePath] = path
    val parameterTypes = method.parameters.map(p => p(MethodParameters.Type).asInstanceOf[NodePath])
    val returnType = method.returnType
    val methodType = MethodTypeDelta.getType(compilation, builder, parentScope, parameterTypes, returnType)

    builder.declare(method.name, parentScope, path.getField(Name), Some(methodType))
  }

  override def collectConstraints(compilation: Compilation, builder: ConstraintBuilder, path: NodePath, parentScope: Scope): Unit = {
    getBodyScope(compilation, builder, path, parentScope)
  }

  def getBodyScope(compilation: Compilation, builder: ConstraintBuilder, path: NodePath, parentScope: Scope): ConcreteScope = {
    val method: Method[NodePath] = path
    val bodyScope = builder.newScope(parentScope, "methodBody")
    method.parameters.foreach(parameter => {
      MethodParameters.declare(compilation, builder, parameter, parentScope, bodyScope)
    })
    ConstraintSkeleton.constraints(compilation, builder, method.body, bodyScope)
    bodyScope
  }

  override def shape: NodeShape = Shape

  override def inject(language: Language): Unit = {
    LabelStatementDelta.isLabelScope.add(language, Shape, ())
    super.inject(language)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy