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

com.wavesplatform.lang.v1.parser.Expressions.scala Maven / Gradle / Ivy

package com.wavesplatform.lang.v1.parser

import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.lang.v1.compiler.CompilerContext
import com.wavesplatform.lang.v1.compiler.Types.*
import com.wavesplatform.lang.v1.parser.Parser.LibrariesOffset

object Expressions {

  sealed trait Pos {
    def end: Int
    def start: Int
    override def toString: String = ""
  }

  object Pos {
    def apply(start: Int, end: Int)(implicit offset: LibrariesOffset): Pos = RealPos(offset.shiftStart(start), offset.shiftEnd(end))
    def apply(pos: Pos): Pos                                               = RealPos(pos.start, pos.end)
    def fromShifted(start: Int, end: Int): Pos                             = RealPos(start, end)

    override def equals(obj: scala.Any): Boolean = super.equals(obj)

    final case class RealPos(start: Int, end: Int) extends Pos { self =>
      override def equals(obj: scala.Any): Boolean = obj match {
        case AnyPos        => true
        case RealPos(s, e) => s == start && e == end
        case _             => false
      }
    }
    case object AnyPos extends Pos {
      override def equals(obj: scala.Any): Boolean = obj match {
        case _: Pos => true
        case _      => false
      }

      override def start: Int = -1
      override def end: Int   = -1
    }
  }

  trait Positioned {
    def position: Pos
  }

  trait Typed {
    def resultType: Option[FINAL]
  }

  trait ContextContainer {
    def ctxOpt: CtxOpt
  }

  sealed trait PART[+T] extends Positioned
  object PART {
    case class VALID[T](position: Pos, v: T) extends PART[T] {
      override def equals(obj: Any): Boolean =
        obj match {
          case VALID(_, value) => value == this.v
          case _               => false
        }

      override def hashCode: Int    = v.hashCode
      override def toString: String = v.toString
    }
    case class INVALID(position: Pos, message: String) extends PART[Nothing]

    def toEither[T](part: PART[T]): Either[String, T] = part match {
      case Expressions.PART.VALID(_, x)         => Right(x)
      case Expressions.PART.INVALID(p, message) => Left(message)
    }

    def toOption[T](part: PART[T]): Option[T] = part match {
      case Expressions.PART.VALID(_, x)         => Some(x)
      case Expressions.PART.INVALID(p, message) => None
    }
  }

  sealed trait Declaration extends Positioned {
    def position: Pos
    def name: PART[String]
    def allowShadowing: Boolean
  }

  case class LET(
      position: Pos,
      name: PART[String],
      value: EXPR,
      types: Option[FINAL] = None,
      allowShadowing: Boolean = false
  ) extends Declaration

  sealed trait Type {
    def isEmpty: Boolean =
      this match {
        case _: Single    => false
        case AnyType(_)   => false
        case Union(types) => types.isEmpty
        case Tuple(types) => types.exists(_.isEmpty)
      }
  }
  object Type {
    val ListTypeName = "List"
  }
  case class Single(name: PART[String], parameter: Option[PART[Type]] = None) extends Type
  case class AnyType(position: Pos)                                           extends Type
  case class Union(types: Seq[Type])                                          extends Type
  object Union {
    def apply(types: Seq[Type]): Type = types match {
      case Seq(t) => t
      case _      => new Union(types)
    }
  }
  case class Tuple(types: Seq[Type]) extends Type

  type CtxOpt = Option[CompilerContext]

  case class FUNC(position: Pos, expr: EXPR, name: PART[String], args: Seq[(PART[String], Type)]) extends Declaration {
    val allowShadowing = false
  }

  case class ANNOTATION(position: Pos, name: PART[String], args: Seq[PART[String]]) extends Positioned
  case class ANNOTATEDFUNC(position: Pos, anns: Seq[ANNOTATION], f: FUNC) extends Positioned {
    def name: PART[String] = f.name
  }

  sealed trait EXPR extends Positioned with Typed with ContextContainer {
    def getName: String = this.getClass().getSimpleName
  }
  case class CONST_LONG(position: Pos, value: Long, ctxOpt: CtxOpt = None) extends EXPR {
    val resultType: Option[FINAL] = Some(LONG)
  }

  case class GETTER(
      position: Pos,
      ref: EXPR,
      field: PART[String],
      resultType: Option[FINAL] = None,
      ctxOpt: CtxOpt = None,
      checkObjectType: Boolean = true
  ) extends EXPR

  case class CONST_BYTESTR(position: Pos, value: PART[ByteStr], ctxOpt: CtxOpt = None) extends EXPR {
    val resultType: Option[FINAL] = Some(BYTESTR)
  }
  case class CONST_STRING(position: Pos, value: PART[String], ctxOpt: CtxOpt = None) extends EXPR {
    val resultType: Option[FINAL] = Some(STRING)
  }
  case class BINARY_OP(position: Pos, a: EXPR, kind: BinaryOperation, b: EXPR, resultType: Option[FINAL] = None, ctxOpt: CtxOpt = None) extends EXPR
  case class BLOCK(position: Pos, let: Declaration, body: EXPR, resultType: Option[FINAL] = None, ctxOpt: CtxOpt = None)                extends EXPR
  case class IF(position: Pos, cond: EXPR, ifTrue: EXPR, ifFalse: EXPR, resultType: Option[FINAL] = None, ctxOpt: CtxOpt = None)        extends EXPR
  case class REF(position: Pos, key: PART[String], resultType: Option[FINAL] = None, ctxOpt: CtxOpt = None)                             extends EXPR
  case class TRUE(position: Pos, ctxOpt: CtxOpt = None) extends EXPR {
    val resultType: Option[FINAL] = Some(BOOLEAN)
  }
  case class FALSE(position: Pos, ctxOpt: CtxOpt = None) extends EXPR {
    val resultType: Option[FINAL] = Some(BOOLEAN)
  }
  case class FUNCTION_CALL(position: Pos, name: PART[String], args: List[EXPR], resultType: Option[FINAL] = None, ctxOpt: CtxOpt = None) extends EXPR

  case class GENERIC_FUNCTION_CALL(
      position: Pos,
      expr: EXPR,
      name: PART[String],
      `type`: Type,
      resultType: Option[FINAL] = None,
      ctxOpt: CtxOpt = None
  ) extends EXPR

  case class FOLD(position: Pos, limit: Int, list: EXPR, acc: EXPR, func: REF, resultType: Option[FINAL] = None, ctxOpt: CtxOpt = None) extends EXPR

  sealed trait Pattern {
    def isRest: Boolean = false
    def subpatterns: Seq[(SimplePattern, Seq[(PART[String], Option[Single])])]
    def position: Pos
  }

  sealed trait SimplePattern extends Pattern {
    def subpatterns: Seq[(SimplePattern, Seq[(PART[String], Option[Single])])] = Seq((this, Seq()))
  }

  sealed trait CompositePattern extends Pattern {
    def caseType: Option[Single]
    val patternsWithFields: Seq[(String, Pattern)]

    def subpatterns: Seq[(SimplePattern, Seq[(PART[String], Option[Single])])] =
      for {
        (field, p) <- patternsWithFields
        (sp, path) <- p.subpatterns
        nextPath = Expressions.PART.VALID(p.position, field)
      } yield (sp, path :+ ((nextPath, caseType)))
  }

  case class TypedVar(newVarName: Option[PART[String]], caseType: Type) extends SimplePattern {
    override def isRest: Boolean = caseType.isEmpty || caseType.isInstanceOf[AnyType]
    def position: Pos            = newVarName.fold(Pos.AnyPos: Pos)(_.position)
  }

  case class ConstsPat(constants: Seq[EXPR], position: Pos) extends SimplePattern

  case class TuplePat(patterns: Seq[Pattern], position: Pos) extends CompositePattern {
    val patternsWithFields: Seq[(String, Pattern)] = patterns.zipWithIndex.map { case (p, i) => (s"_${i + 1}", p) }
    val caseType: Option[Single]                   = None
  }

  case class ObjPat(patterns: Map[String, Pattern], objType: Single, position: Pos) extends CompositePattern {
    val patternsWithFields: Seq[(String, Pattern)] = patterns.toSeq
    val caseType: Option[Single]                   = Some(objType)
  }

  case class MATCH_CASE(
      position: Pos,
      pattern: Pattern,
      expr: EXPR,
      resultType: Option[FINAL] = None,
      ctxOpt: CtxOpt = None
  )

  object MATCH_CASE {
    def apply(
        position: Pos,
        newVarName: Option[PART[String]],
        types: Seq[PART[String]],
        expr: EXPR
    ): MATCH_CASE =
      MATCH_CASE(position, TypedVar(newVarName, Union(types.map(Single(_, None)))), expr)
  }

  case class MATCH(position: Pos, expr: EXPR, cases: Seq[MATCH_CASE], resultType: Option[FINAL] = None, ctxOpt: CtxOpt = None) extends EXPR

  case class INVALID(position: Pos, message: String, resultType: Option[FINAL] = None, ctxOpt: CtxOpt = None) extends EXPR

  case class DAPP(position: Pos, decs: List[Declaration], fs: List[ANNOTATEDFUNC])

  case class SCRIPT(position: Pos, expr: EXPR)

  implicit class PartOps[T](val self: PART[T]) extends AnyVal {
    def toEither: Either[String, T] = self match {
      case Expressions.PART.VALID(_, x)         => Right(x)
      case Expressions.PART.INVALID(p, message) => Left(s"Can't compile an invalid instruction: $message in ${p.start}-${p.end}")
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy