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

miksilo.modularLanguages.deltas.solidity.SolidityContractDelta.scala Maven / Gradle / Ivy

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

import miksilo.modularLanguages.core.bigrammar.BiGrammar
import miksilo.modularLanguages.core.deltas.DeltaWithGrammar
import miksilo.modularLanguages.core.deltas.grammars.LanguageGrammars
import miksilo.modularLanguages.core.deltas.path.NodePath
import miksilo.editorParser.document.BlankLine
import miksilo.modularLanguages.core.node.{NodeField, NodeLike, NodeShape}
import miksilo.languageServer.core.language.{Compilation, Language}
import miksilo.languageServer.core.smarts.ConstraintBuilder
import miksilo.languageServer.core.smarts.scopes.objects.Scope
import miksilo.languageServer.core.smarts.types.DeclarationHasType
import miksilo.languageServer.core.smarts.types.objects.{Type, TypeFromDeclaration}
import miksilo.modularLanguages.deltas.ConstraintSkeleton
import miksilo.modularLanguages.deltas.HasNameDelta.{HasName, Name}
import miksilo.modularLanguages.deltas.bytecode.types.{TypeSkeleton, UnqualifiedObjectTypeDelta}
import miksilo.modularLanguages.deltas.classes.ClassDelta
import miksilo.modularLanguages.deltas.classes.ClassDelta.ClassImports
import miksilo.modularLanguages.deltas.expression.ExpressionDelta
import miksilo.modularLanguages.deltas.classes.HasConstraintsDelta

object SolidityContractDelta extends DeltaWithGrammar with HasConstraintsDelta {

  object ContractType extends NodeField
  object SuperContracts extends NodeField

  object SuperShape extends NodeShape
  object SuperName extends NodeField
  object SuperArguments extends NodeField

  implicit class ContractLike[T <: NodeLike](val node: T) extends HasName[T] {
    def imports = node(ClassImports).asInstanceOf[Seq[T]]
    def imports_=(value: Seq[T]): Unit = node(ClassImports) = value

    def members = node(ClassDelta.Members).asInstanceOf[Seq[T]]
    def members_=(value: Seq[T]): Unit = node(ClassDelta.Members) = value

    def parents: Seq[T] = node(SuperContracts).asInstanceOf[Seq[T]]
    def parents_=(value: Seq[T]): Unit = node(SuperContracts) = value

    def contractType: String = node.getValue(ContractType).asInstanceOf[String]
  }

  override def transformGrammars(grammars: LanguageGrammars, language: Language): Unit = {
    import grammars._

    val contractType = ("contract" | "interface" | "library").as(ContractType)
    val objectType = find(UnqualifiedObjectTypeDelta.AnyObjectTypeGrammar)
    val expression = find(ExpressionDelta.FirstPrecedenceGrammar)
    val inheritanceSpecifier: BiGrammar = objectType.as(SuperName) ~
      (expression.someSeparated("," ~ printSpace).inParenthesis | value(Seq.empty)).as(SuperArguments) asNode SuperShape
    val inheritance = (printSpace ~ "is" ~~ inheritanceSpecifier.someSeparated("," ~ printSpace) | value(Seq.empty)).as(SuperContracts)
    val member = create(ClassDelta.Members)
    val members = member.manySeparatedVertical(BlankLine).as(ClassDelta.Members)
    val contract = contractType ~~ identifier.as(Name) ~ inheritance ~ "{" % members % "}" asNode ClassDelta.Shape
    find(FileWithMembersDelta.Members).addAlternative(contract)
  }

  override def description = "Adds the contract/interface/library"

  override def dependencies = Set(FileWithMembersDelta, UnqualifiedObjectTypeDelta)

  override def shape = ClassDelta.Shape

  override def collectConstraints(compilation: Compilation, builder: ConstraintBuilder, path: NodePath, parentScope: Scope): Unit = {
    val contractLike: ContractLike[NodePath] = path
    val contractDeclaration = builder.declare(contractLike.name, parentScope, path.getField(Name))
    val contractStaticType = TypeFromDeclaration(contractDeclaration)
    val contractInstanceType = TypeFromDeclaration(contractDeclaration) // TODO fix this
    builder.add(DeclarationHasType(contractDeclaration, contractStaticType))
    builder.assignSubType(TypeSkeleton.typeKind, contractStaticType)
    val contractScope = builder.declareScope(contractDeclaration, parentScope, s"contract '${contractLike.name}'")

    if (Set("interface", "contract").contains(contractLike.contractType)) {
      val addressDeclaration = SolidityLibraryDelta.addressDeclaration(compilation)
      val fromAddressMethod = SolidityFunctionTypeDelta.createType(
        Seq[Type](TypeFromDeclaration(addressDeclaration)),
        Seq[Type](contractInstanceType))
      builder.declare(contractLike.name, parentScope, _type = Some(fromAddressMethod))
    }

    for(member <- contractLike.members) {
      ConstraintSkeleton.constraints(compilation, builder, member, contractScope)
    }
  }
}







© 2015 - 2024 Weber Informatics LLC | Privacy Policy