mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-12 17:55:33 +00:00
Return T | null
on optional results (#221)
This commit is contained in:
parent
b6989058fc
commit
2eb4598093
@ -1,21 +1,7 @@
|
||||
data DT:
|
||||
field: string
|
||||
service Op("op"):
|
||||
noop: -> ()
|
||||
|
||||
service DTGetter("get-dt"):
|
||||
get_dt(s: string) -> DT
|
||||
|
||||
func use_name1(name: string) -> string:
|
||||
results <- DTGetter.get_dt(name)
|
||||
<- results.field
|
||||
|
||||
func use_name2(name: string) -> []string:
|
||||
results: *string
|
||||
results <- use_name1(name)
|
||||
results <- use_name1(name)
|
||||
results <- use_name1(name)
|
||||
<- results
|
||||
|
||||
func use_name3(name: string) -> []string:
|
||||
DTGetter.get_dt("yoyo literal")
|
||||
results <- use_name2(name)
|
||||
<- results
|
||||
func return_none() -> ?string:
|
||||
result: *string
|
||||
Op.noop()
|
||||
<- result
|
@ -14,7 +14,7 @@ object JavaScriptBackend extends Backend {
|
||||
Seq(
|
||||
Compiled(
|
||||
ext,
|
||||
JavaScriptFile.Header + "\n\n" + funcs.map(_.generateTypescript(bc)).toList.mkString("\n\n")
|
||||
JavaScriptFile.Header + "\n\n" + funcs.map(_.generateJavascript(bc)).toList.mkString("\n\n")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ case class JavaScriptFile(context: AquaContext) {
|
||||
Chain.fromSeq(context.funcs.values.toSeq).map(JavaScriptFunc(_))
|
||||
|
||||
def generateJS(conf: BodyConfig = BodyConfig()): String =
|
||||
JavaScriptFile.Header + "\n\n" + funcs.map(_.generateTypescript(conf)).toList.mkString("\n\n")
|
||||
JavaScriptFile.Header + "\n\n" + funcs.map(_.generateJavascript(conf)).toList.mkString("\n\n")
|
||||
}
|
||||
|
||||
object JavaScriptFile {
|
||||
|
@ -4,7 +4,6 @@ import aqua.backend.air.FuncAirGen
|
||||
import aqua.model.func.{ArgDef, FuncCallable}
|
||||
import aqua.model.transform.BodyConfig
|
||||
import aqua.types._
|
||||
import cats.syntax.functor._
|
||||
import cats.syntax.show._
|
||||
|
||||
case class JavaScriptFunc(func: FuncCallable) {
|
||||
@ -14,18 +13,34 @@ case class JavaScriptFunc(func: FuncCallable) {
|
||||
def argsJavaScript: String =
|
||||
func.args.args.map(ad => s"${ad.name}").mkString(", ")
|
||||
|
||||
def generateTypescript(conf: BodyConfig = BodyConfig()): String = {
|
||||
|
||||
val tsAir = FuncAirGen(func).generateAir(conf)
|
||||
|
||||
val returnCallback = func.ret.as {
|
||||
s"""h.onEvent('${conf.callbackService}', '${conf.respFuncName}', (args) => {
|
||||
| const [res] = args;
|
||||
| resolve(res);
|
||||
|});
|
||||
|""".stripMargin
|
||||
// TODO: use common functions between TypeScript and JavaScript backends
|
||||
private def genReturnCallback(
|
||||
retType: Type,
|
||||
callbackService: String,
|
||||
respFuncName: String
|
||||
): String = {
|
||||
val body = retType match {
|
||||
case OptionType(_) =>
|
||||
""" let [opt] = args;
|
||||
| if (Array.isArray(opt)) {
|
||||
| if (opt.length === 0) { resolve(null); }
|
||||
| opt = opt[0];
|
||||
| }
|
||||
| return resolve(opt);""".stripMargin
|
||||
case _ =>
|
||||
""" const [res] = args;
|
||||
| resolve(res);""".stripMargin
|
||||
|
||||
}
|
||||
s"""h.onEvent('$callbackService', '$respFuncName', (args) => {
|
||||
| $body
|
||||
|});
|
||||
|""".stripMargin
|
||||
}
|
||||
|
||||
def generateJavascript(conf: BodyConfig = BodyConfig()): String = {
|
||||
|
||||
val tsAir = FuncAirGen(func).generateAir(conf)
|
||||
|
||||
val setCallbacks = func.args.args.map {
|
||||
case ArgDef.Data(argName, OptionType(_)) =>
|
||||
@ -40,10 +55,16 @@ case class JavaScriptFunc(func: FuncCallable) {
|
||||
s"""h.on('${conf.callbackService}', '$argName', (args) => {$expr;});"""
|
||||
}.mkString("\n")
|
||||
|
||||
val returnCallback = func.ret
|
||||
.map(_._2)
|
||||
.map(t => genReturnCallback(t, conf.callbackService, conf.respFuncName))
|
||||
.getOrElse("")
|
||||
|
||||
val returnVal =
|
||||
func.ret.fold("Promise.race([promise, Promise.resolve()])")(_ => "promise")
|
||||
|
||||
val configArgName ="config"
|
||||
// TODO: it could be non-unique
|
||||
val configArgName = "config"
|
||||
|
||||
s"""
|
||||
|export async function ${func.funcName}(client${if (func.args.isEmpty) ""
|
||||
@ -65,7 +86,7 @@ case class JavaScriptFunc(func: FuncCallable) {
|
||||
| });""".stripMargin
|
||||
}}
|
||||
| $setCallbacks
|
||||
| ${returnCallback.getOrElse("")}
|
||||
| $returnCallback
|
||||
| h.onEvent('${conf.errorHandlingService}', '${conf.errorFuncName}', (args) => {
|
||||
| // assuming error is the single argument
|
||||
| const [err] = args;
|
||||
|
@ -4,7 +4,6 @@ import aqua.backend.air.FuncAirGen
|
||||
import aqua.model.func.{ArgDef, FuncCallable}
|
||||
import aqua.model.transform.BodyConfig
|
||||
import aqua.types._
|
||||
import cats.syntax.functor._
|
||||
import cats.syntax.show._
|
||||
|
||||
case class TypeScriptFunc(func: FuncCallable) {
|
||||
@ -23,17 +22,42 @@ case class TypeScriptFunc(func: FuncCallable) {
|
||||
args.find(_ == name).map(_ => generateUniqueArgName(args, basis, attempt + 1)).getOrElse(name)
|
||||
}
|
||||
|
||||
private def genReturnCallback(
|
||||
retType: Type,
|
||||
callbackService: String,
|
||||
respFuncName: String
|
||||
): String = {
|
||||
val body = retType match {
|
||||
case OptionType(_) =>
|
||||
""" let [opt] = args;
|
||||
| if (Array.isArray(opt)) {
|
||||
| if (opt.length === 0) { resolve(null); }
|
||||
| opt = opt[0];
|
||||
| }
|
||||
| return resolve(opt);""".stripMargin
|
||||
case _ =>
|
||||
""" const [res] = args;
|
||||
| resolve(res);""".stripMargin
|
||||
|
||||
}
|
||||
s"""h.onEvent('$callbackService', '$respFuncName', (args) => {
|
||||
| $body
|
||||
|});
|
||||
|""".stripMargin
|
||||
}
|
||||
|
||||
def generateTypescript(conf: BodyConfig = BodyConfig()): String = {
|
||||
|
||||
val tsAir = FuncAirGen(func).generateAir(conf)
|
||||
|
||||
val returnCallback = func.ret.as {
|
||||
s"""h.onEvent('${conf.callbackService}', '${conf.respFuncName}', (args) => {
|
||||
| const [res] = args;
|
||||
| resolve(res);
|
||||
|});
|
||||
|""".stripMargin
|
||||
}
|
||||
val retType = func.ret
|
||||
.map(_._2)
|
||||
.fold("void")(typeToTs)
|
||||
|
||||
val returnCallback = func.ret
|
||||
.map(_._2)
|
||||
.map(t => genReturnCallback(t, conf.callbackService, conf.respFuncName))
|
||||
.getOrElse("")
|
||||
|
||||
val setCallbacks = func.args.args.map {
|
||||
case ArgDef.Data(argName, OptionType(_)) =>
|
||||
@ -48,10 +72,6 @@ case class TypeScriptFunc(func: FuncCallable) {
|
||||
s"""h.on('${conf.callbackService}', '$argName', (args) => {$expr;});"""
|
||||
}.mkString("\n")
|
||||
|
||||
val retType = func.ret
|
||||
.map(_._2)
|
||||
.fold("void")(typeToTs)
|
||||
|
||||
val returnVal =
|
||||
func.ret.fold("Promise.race([promise, Promise.resolve()])")(_ => "promise")
|
||||
|
||||
@ -80,7 +100,7 @@ case class TypeScriptFunc(func: FuncCallable) {
|
||||
| });""".stripMargin
|
||||
}}
|
||||
| $setCallbacks
|
||||
| ${returnCallback.getOrElse("")}
|
||||
| $returnCallback
|
||||
| h.onEvent('${conf.errorHandlingService}', '${conf.errorFuncName}', (args) => {
|
||||
| // assuming error is the single argument
|
||||
| const [err] = args;
|
||||
|
@ -6,7 +6,7 @@ import aqua.linker.Linker
|
||||
import aqua.model.AquaContext
|
||||
import aqua.model.transform.BodyConfig
|
||||
import aqua.parser.lift.FileSpan
|
||||
import aqua.semantics.{RulesViolated, SemanticError, Semantics}
|
||||
import aqua.semantics.{RulesViolated, SemanticError, Semantics, WrongAST}
|
||||
import cats.data._
|
||||
import cats.kernel.Monoid
|
||||
import cats.syntax.flatMap._
|
||||
@ -91,7 +91,7 @@ object AquaCompiler extends LogSupport {
|
||||
.focus(2)
|
||||
.map(_.toConsoleStr(hint, Console.CYAN))
|
||||
.getOrElse("(Dup error, but offset is beyond the script)") + "\n"
|
||||
case _ =>
|
||||
case WrongAST(_) =>
|
||||
"Semantic error"
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package aqua.semantics
|
||||
|
||||
import aqua.model.{AquaContext, Model, ScriptModel}
|
||||
import aqua.model.func.raw.FuncOp
|
||||
import aqua.model.{AquaContext, Model, ScriptModel}
|
||||
import aqua.parser.lexer.Token
|
||||
import aqua.parser.{Ast, Expr}
|
||||
import aqua.semantics.rules.ReportError
|
||||
@ -16,13 +16,13 @@ import aqua.semantics.rules.types.{TypeOp, TypesAlgebra, TypesInterpreter, Types
|
||||
import cats.Eval
|
||||
import cats.arrow.FunctionK
|
||||
import cats.data.Validated.{Invalid, Valid}
|
||||
import cats.data.{Chain, EitherK, NonEmptyChain, State, Validated, ValidatedNec}
|
||||
import cats.data._
|
||||
import cats.free.Free
|
||||
import cats.kernel.Monoid
|
||||
import monocle.Lens
|
||||
import monocle.macros.GenLens
|
||||
import cats.syntax.apply._
|
||||
import cats.syntax.semigroup._
|
||||
import monocle.Lens
|
||||
import monocle.macros.GenLens
|
||||
import wvlet.log.LogSupport
|
||||
|
||||
object Semantics extends LogSupport {
|
||||
@ -96,8 +96,11 @@ object Semantics extends LogSupport {
|
||||
NonEmptyChain
|
||||
.fromChain(state.errors)
|
||||
.fold[ValidatedNec[SemanticError[F], AquaContext]](Valid(ctx))(Invalid(_))
|
||||
case (_, _) =>
|
||||
Validated.invalidNec[SemanticError[F], AquaContext](WrongAST(ast))
|
||||
case (state, _) =>
|
||||
NonEmptyChain
|
||||
.fromChain(state.errors)
|
||||
.map(Invalid(_))
|
||||
.getOrElse(Validated.invalidNec[SemanticError[F], AquaContext](WrongAST(ast)))
|
||||
}
|
||||
.value
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user