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