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

com.wavesplatform.lang.v1.CTX.scala Maven / Gradle / Ivy

package com.wavesplatform.lang.v1

import cats.{Id, Monad, Monoid}
import com.wavesplatform.lang.v1.FunctionHeader.Native
import com.wavesplatform.lang.v1.compiler.CompilerContext.{FunctionInfo, VariableInfo}
import com.wavesplatform.lang.v1.compiler.Types.FINAL
import com.wavesplatform.lang.v1.compiler.{CompilerContext, DecompilerContext}
import com.wavesplatform.lang.v1.evaluator.Contextful.NoContext
import com.wavesplatform.lang.v1.evaluator.ctx.{BaseFunction, EvaluationContext, LazyVal}
import com.wavesplatform.lang.v1.evaluator.ctx.impl.PureContext
import com.wavesplatform.lang.v1.evaluator.{Contextful, ContextfulVal}
import com.wavesplatform.lang.v1.parser.BinaryOperation
import com.wavesplatform.lang.v1.parser.Expressions.Pos.AnyPos

import scala.annotation.meta.field
import scala.scalajs.js.annotation.*

@JSExportTopLevel("CTX")
case class CTX[C[_[_]]](
  @(JSExport @field) types: Seq[FINAL],
  @(JSExport @field) vars: Map[String, (FINAL, ContextfulVal[C])],
  @(JSExport @field) functions: Array[BaseFunction[C]]
) {
  lazy val typeDefs = types.view.map(t => t.name -> t).toMap
  lazy val functionMap = functions.view.map(f => f.header -> f).toMap

  def evaluationContext[F[_]: Monad](env: C[F]): EvaluationContext[C, F] = {

    if (functionMap.size != functions.length) {
      val dups = functions.groupBy(_.header).filter(_._2.length != 1)
      throw new Exception(s"Duplicate runtime functions names: $dups")
    }
    EvaluationContext(
      env,
      typeDefs,
      vars.map { case (k, v) => k -> LazyVal.fromEval(v._2(env)) },
      functionMap
    )
  }

  def evaluationContext[F[_]: Monad](implicit ev: NoContext[F] =:= C[F]): EvaluationContext[C, F] =
    evaluationContext[F](Contextful.empty[F])

  def withEnvironment[D[_[_]]](implicit ev: C[Id] =:= NoContext[Id]): CTX[D] =
    asInstanceOf[CTX[D]]

  lazy val compilerContext: CompilerContext = CompilerContext(
    typeDefs,
    vars.view.mapValues(v => VariableInfo(AnyPos, v._1)).toMap,
    functions.groupBy(_.name).map { case (k, v) => k -> FunctionInfo(AnyPos, v.map(_.signature).toList) },
    provideRuntimeTypeOnCastError = functions.exists(_ == PureContext._getType)
  )

  val opsNames = BinaryOperation.opsByPriority
    .flatMap({
      case Left(l)  => l
      case Right(l) => l
    })
    .map(x => BinaryOperation.opsToFunctions(x))
    .toSet

  lazy val decompilerContext: DecompilerContext = DecompilerContext(
    opCodes = compilerContext.functionDefs
      .view.mapValues(_.fSigList.map(_.header).filter(_.isInstanceOf[Native]).map(_.asInstanceOf[Native].name))
      .toList
      .flatMap { case (name, codes) => codes.map((_, name)) }
      .toMap,
    binaryOps = compilerContext.functionDefs
      .view.filterKeys(opsNames(_))
      .mapValues(
        _.fSigList.map(_.header)
          .filter(_.isInstanceOf[Native])
          .map(_.asInstanceOf[Native].name))
      .toList
      .flatMap { case (name, codes) => codes.map((_, name)) }
      .toMap,
    ident = 0
  )
}

object CTX {
  val empty: CTX[NoContext] = CTX[NoContext](Seq.empty, Map.empty, Array.empty)

  implicit def monoid[C[_[_]]]: Monoid[CTX[C]] = new Monoid[CTX[C]] {
    override val empty: CTX[C] = CTX.empty.withEnvironment[C]

    override def combine(x: CTX[C], y: CTX[C]): CTX[C] =
      CTX[C](x.types ++ y.types, x.vars ++ y.vars, x.functions ++ y.functions)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy