Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(compiler): Generate empty calls to responseHandlerSrv [LNG-286] #979

Merged
merged 2 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions api/api-npm/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ type CommonArgs = {
targetType?: "ts" | "js" | "air" | undefined;
/** Compile aqua in tracing mode (for debugging purposes). Default: false */
tracing?: boolean | undefined;
/** Do not generate response call if there are no returned values */
noEmptyResponse?: boolean | undefined;
};

type CodeString = {
Expand Down
2 changes: 2 additions & 0 deletions api/api-npm/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ function getConfig({
noXor = false,
targetType = "air",
tracing = false,
noEmptyResponse = false,
}) {
return new AquaConfig(
logLevel,
Expand All @@ -19,6 +20,7 @@ function getConfig({
air: "air",
}[targetType],
tracing,
noEmptyResponse,
);
}

Expand Down
9 changes: 6 additions & 3 deletions api/api/.js/src/main/scala/api/types/InputTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import aqua.api.AquaAPIConfig
import aqua.api.TargetType.*
import aqua.js.{FunctionDefJs, ServiceDefJs}
import aqua.model.transform.TransformConfig

import cats.data.Validated.{invalidNec, validNec}
import cats.data.{Chain, NonEmptyChain, Validated, ValidatedNec}

import scala.scalajs.js
import scala.scalajs.js.JSConverters.*
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
Expand Down Expand Up @@ -47,7 +47,9 @@ class AquaConfig(
@JSExport
val targetType: js.UndefOr[String],
@JSExport
val tracing: js.UndefOr[Boolean]
val tracing: js.UndefOr[Boolean],
@JSExport
val noEmptyResponse: js.UndefOr[Boolean]
)

object AquaConfig {
Expand All @@ -69,7 +71,8 @@ object AquaConfig {
constants = cjs.constants.map(_.toList).getOrElse(Nil),
noXor = cjs.noXor.getOrElse(false),
noRelay = cjs.noRelay.getOrElse(false),
tracing = cjs.tracing.getOrElse(false)
tracing = cjs.tracing.getOrElse(false),
noEmptyResponse = cjs.noEmptyResponse.getOrElse(false)
)
}
}
Expand Down
6 changes: 4 additions & 2 deletions api/api/src/main/scala/aqua/api/AquaAPIConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ case class AquaAPIConfig(
constants: List[String] = Nil,
noXor: Boolean = false, // TODO: Remove
noRelay: Boolean = false,
tracing: Boolean = false
tracing: Boolean = false,
noEmptyResponse: Boolean = false
) {

def getTransformConfig: TransformConfig = {
val config = TransformConfig(
tracing = Option.when(tracing)(TransformConfig.TracingConfig.default)
tracing = Option.when(tracing)(TransformConfig.TracingConfig.default),
noEmptyResponse = noEmptyResponse
)

if (noRelay) config.copy(relayVarName = None)
Expand Down
21 changes: 11 additions & 10 deletions compiler/src/test/scala/aqua/compiler/AquaCompilerSpec.scala
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package aqua.compiler

import aqua.model.{CallModel, ForModel, FunctorModel, LiteralModel, ValueModel, VarModel}
import aqua.model.AquaContext
import aqua.model.CallServiceModel
import aqua.model.FlattenModel
import aqua.model.transform.ModelBuilder
import aqua.model.transform.TransformConfig
import aqua.model.transform.Transform
import aqua.parser.ParserError
import aqua.model.transform.TransformConfig
import aqua.model.{CallModel, ForModel, FunctorModel, LiteralModel, ValueModel, VarModel}
import aqua.parser.Ast
import aqua.parser.Parser
import aqua.parser.ParserError
import aqua.parser.lift.Span
import aqua.parser.lift.Span.S
import aqua.raw.ConstantRaw
Expand All @@ -18,15 +21,12 @@ import aqua.types.{ArrayType, CanonStreamType, LiteralType, ScalarType, StreamTy
import cats.Id
import cats.data.{Chain, NonEmptyChain, NonEmptyMap, Validated, ValidatedNec}
import cats.instances.string.*
import cats.syntax.show.*
import cats.syntax.option.*
import cats.syntax.either.*
import cats.syntax.option.*
import cats.syntax.show.*
import org.scalatest.Inside
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalatest.Inside
import aqua.model.AquaContext
import aqua.model.FlattenModel
import aqua.model.CallServiceModel

class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
import ModelBuilder.*
Expand Down Expand Up @@ -358,7 +358,8 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers with Inside {
join(VarModel(streamName, streamType), arg),
decrement
)
)
),
emptyRespCall(transformCfg, initPeer)
),
errorCall(transformCfg, 0, initPeer)
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
package aqua.model.transform

import aqua.model.*
import aqua.model.inline.ArrowInliner
import aqua.model.inline.state.InliningState
import aqua.model.transform.TransformConfig.TracingConfig
import aqua.model.transform.funcop.*
import aqua.model.transform.pre.*
import aqua.model.transform.pre.{CallbackErrorHandler, ErrorHandler}
import aqua.model.transform.topology.Topology
import aqua.model.*
import aqua.raw.ops.RawTag
import aqua.raw.value.VarRaw
import aqua.res.*
import aqua.types.ScalarType
import aqua.model.transform.TransformConfig.TracingConfig
import aqua.model.transform.pre.{CallbackErrorHandler, ErrorHandler}

import cats.Eval
import cats.data.Chain
import cats.free.Cofree
import cats.instances.list.*
import cats.syntax.option.*
import cats.syntax.show.*
import cats.syntax.traverse.*
import cats.instances.list.*
import scribe.Logging

// API for transforming RawTag to Res
Expand Down Expand Up @@ -90,7 +90,8 @@ object Transform extends Logging {

val resultsHandler: ResultsHandler = CallbackResultsHandler(
callbackSrvId = conf.callbackSrvId,
funcName = conf.respFuncName
funcName = conf.respFuncName,
noEmptyResponse = conf.noEmptyResponse
)

val errorHandler: ErrorHandler = CallbackErrorHandler(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
package aqua.model.transform

import aqua.model.{AquaContext, LiteralModel, ValueModel, VarModel}
import aqua.raw.{ConstantRaw, RawContext, RawPart}
import aqua.raw.value.{LiteralRaw, ValueRaw, VarRaw}
import aqua.raw.{ConstantRaw, RawContext, RawPart}
import aqua.types.ScalarType

import cats.data.Chain
import cats.kernel.Monoid

// TODO docs
/**
* Configuration for function pre transformer
*
* @param getDataService - name of the service that provides arguments
* @param callbackService - name of the service that provides callbacks
* @param errorHandlingService - name of the service that handles errors
* @param errorFuncName - name of the function that handles errors (in errorHandlingService)
* @param respFuncName - name of the function that handles responses (in getDataService)
* @param noEmptyResponse - if true, do not generate response call if there is no return values
* @param relayVarName - name of the relay variable
* @param tracing - tracing configuration
* @param constants - list of constants
*/
case class TransformConfig(
getDataService: String = "getDataSrv",
callbackService: String = "callbackSrv",
errorHandlingService: String = "errorHandlingSrv",
errorFuncName: String = "error",
respFuncName: String = "response",
noEmptyResponse: Boolean = false,
relayVarName: Option[String] = Some("-relay-"),
tracing: Option[TransformConfig.TracingConfig] = None,
constants: List[ConstantRaw] = Nil
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
package aqua.model.transform.pre

import aqua.types.Type
import aqua.raw.ops.{Call, CallArrowRawTag, RawTag}
import aqua.raw.value.{ValueRaw, VarRaw}
import aqua.types.Type

import cats.syntax.option.*

trait ResultsHandler {
def handleResults(results: List[(String, Type)]): Option[RawTag.Tree]
}

case class CallbackResultsHandler(callbackSrvId: ValueRaw, funcName: String)
extends ResultsHandler {
case class CallbackResultsHandler(
callbackSrvId: ValueRaw,
funcName: String,
noEmptyResponse: Boolean
) extends ResultsHandler {

override def handleResults(results: List[(String, Type)]): Option[RawTag.Tree] =
if (results.isEmpty) none
if (results.isEmpty && noEmptyResponse) none
else {
val resultVars = results.map(VarRaw.apply.tupled)
val call = Call(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package aqua.model.transform

import aqua.model.*
import aqua.model.FailModel
import aqua.model.IntoIndexModel
import aqua.model.OnModel
import aqua.model.inline.raw.StreamGateInliner
import aqua.raw.ops.Call
import aqua.raw.value.{LiteralRaw, ValueRaw, VarRaw}
import aqua.{model, res}
import aqua.res.ResolvedOp
import aqua.res.{CallRes, CallServiceRes, MakeRes}
import aqua.types.{ArrayType, LiteralType, ScalarType}
import aqua.types.StreamType
import aqua.model.IntoIndexModel
import aqua.model.inline.raw.StreamGateInliner
import aqua.model.OnModel
import aqua.model.FailModel
import aqua.res.ResolvedOp
import aqua.types.{ArrayType, LiteralType, ScalarType}
import aqua.{model, res}

import scala.language.implicitConversions
import cats.data.Chain
import cats.data.Chain.==:
import cats.syntax.option.*
import scala.language.implicitConversions

object ModelBuilder {
implicit def rawToValue(raw: ValueRaw): ValueModel = ValueModel.fromRaw(raw)
Expand Down Expand Up @@ -88,15 +88,24 @@ object ModelBuilder {
)
.leaf

def respCall(bc: TransformConfig, value: ValueModel, on: ValueModel = initPeer) =
res
.CallServiceRes(
ValueModel.fromRaw(bc.callbackSrvId),
bc.respFuncName,
CallRes(value :: Nil, None),
on
)
.leaf
def respCallImpl(
config: TransformConfig,
arguments: List[ValueModel],
on: ValueModel = initPeer
) = res
.CallServiceRes(
ValueModel.fromRaw(config.callbackSrvId),
config.respFuncName,
CallRes(arguments, None),
on
)
.leaf

def respCall(config: TransformConfig, value: ValueModel, on: ValueModel = initPeer) =
respCallImpl(config, value :: Nil, on)

def emptyRespCall(config: TransformConfig, on: ValueModel = initPeer) =
respCallImpl(config, Nil)

def dataCall(bc: TransformConfig, name: String, on: ValueModel = initPeer) =
res
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import aqua.model.transform.ModelBuilder
import aqua.model.transform.{Transform, TransformConfig}
import aqua.model.{CallModel, FuncArrow, LiteralModel, VarModel}
import aqua.raw.ops.{Call, CallArrowRawTag, FuncOp, OnTag, RawTag, SeqTag}
import aqua.raw.value.{LiteralRaw, VarRaw}
import aqua.types.{ArrowType, NilType, ProductType, ScalarType}
import aqua.raw.value.{LiteralRaw, ValueRaw, VarRaw}
import aqua.raw.value.{LiteralRaw, VarRaw}
import aqua.res.{CallRes, CallServiceRes, MakeRes, SeqRes, XorRes}
import aqua.types.{ArrowType, NilType, ProductType, ScalarType}

import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import cats.data.Chain
import cats.syntax.show.*
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class TransformSpec extends AnyFlatSpec with Matchers {

Expand Down
Loading