Generate callbacks in top-level functions

This commit is contained in:
dmitry 2021-03-17 18:28:46 +03:00
parent 76b37430e8
commit c9b3e04a7f
5 changed files with 74 additions and 18 deletions

View File

@ -17,4 +17,11 @@ func generateComplex(value: string) -> bool:
Local.onIn("Should be on other")
Local.onIn("Should be on root")
Local.onBoolean(b)
<- b
<- b
func genArrows(arr: string -> bool):
arr("hi there")
--func wrapGenArrows():
-- on "some peer":
-- genArrows(generateComplex)

View File

@ -6,7 +6,8 @@ import aqua.ast.{Expr, Indent, Prog}
import aqua.ast.algebra.abilities.AbilitiesAlgebra
import aqua.ast.algebra.names.NamesAlgebra
import aqua.ast.algebra.scope.PeerIdAlgebra
import aqua.ast.algebra.types.{ArrowType, Type, TypesAlgebra}
import aqua.ast.algebra.types.{ArrowType, DataType, Type, TypesAlgebra}
import aqua.ast.gen.DataView.InitPeerId
import aqua.ast.gen.{AirContext, AirGen, ArrowGen, DataView, FuncBodyGen, FuncGen, Gen}
import aqua.parser.lexer.Token._
import aqua.parser.lexer.{Arg, DataTypeToken, Name, Value, VarLambda}
@ -43,7 +44,7 @@ case class FuncExpr[F[_]](name: Name[F], args: List[Arg[F]], ret: Option[DataTyp
f.flatMap(acc =>
T.resolveType(argType).flatMap {
case Some(t: ArrowType) =>
N.defineArrow(argName, ArrowGen.arg(t), isRoot = false).as(acc.enqueue(t))
N.defineArrow(argName, ArrowGen.arg(argName.value, t), isRoot = false).as(acc.enqueue(t))
case Some(t) =>
N.define(argName, t).as(acc.enqueue(t))
case None =>
@ -76,11 +77,26 @@ case class FuncExpr[F[_]](name: Name[F], args: List[Arg[F]], ret: Option[DataTyp
ArrowGen.func(funcArrow, argNames, retValue.map(ArrowGen.valueToData), FuncBodyGen(bg)),
isRoot = true
) as FuncGen(
name.value, // TODO: handle return value
name.value,
Eval.later {
// TODO distinguish arrows, create services!
bg.generate(
AirContext(data = argNames.map(a => a -> DataView.Variable(a)).toMap, vars = argNames.toSet)
AirContext(
data = argNames
.zip(funcArrow.args)
.collect { //TODO preload these variables
case (an, _: DataType) =>
an -> DataView.Variable(an)
}
.toMap,
arrows = argNames
.zip(funcArrow.args)
.collect {
case (an, _: ArrowType) =>
an -> new ArrowGen.SrvCallableOnPeer(InitPeerId, DataView.StringScalar("callback"), an)
}
.toMap,
vars = argNames.toSet
)
)
._2
},

View File

@ -4,6 +4,7 @@ import DataView.InitPeerId
case class AirContext(
data: Map[String, DataView] = Map.empty,
arrows: Map[String, ArrowGen.Callable] = Map.empty,
peerId: DataView = InitPeerId,
vars: Set[String] = Set.empty,
instrCounter: Int = 0

View File

@ -31,6 +31,34 @@ object ArrowGen {
private def argsToData[F[_]](args: List[Value[F]]): List[DataView] = args.map(valueToData)
trait Callable {
def toCallGen(args: List[DataView], result: Option[String]): AirGen
}
class FuncCallable(argNames: List[String], retValue: Option[DataView], bodyGen: FuncBodyGen) extends Callable {
override def toCallGen(args: List[DataView], result: Option[String]): AirGen =
bodyGen.op
.wrap(c =>
(
c.copy(data = c.data ++ argNames.zip(args)),
_.copy(data = c.data ++ result.zip(retValue))
)
)
}
class SrvCallable(srvId: DataView, fnName: String) extends Callable {
override def toCallGen(args: List[DataView], result: Option[String]): AirGen =
ServiceCallGen(srvId, fnName, args, result)
}
class SrvCallableOnPeer(peerId: DataView, srvId: DataView, fnName: String) extends Callable {
override def toCallGen(args: List[DataView], result: Option[String]): AirGen =
ServiceCallGen(srvId, fnName, args, result).wrap(ctx => (ctx.copy(peerId = peerId), _.copy(peerId = ctx.peerId)))
}
def func(`type`: ArrowType, argNames: List[String], retValue: Option[DataView], bodyGen: FuncBodyGen): ArrowGen =
new ArrowGen(`type`) {
@ -38,13 +66,7 @@ object ArrowGen {
A: AbilitiesAlgebra[F, Alg]
): Free[Alg, AirGen] =
Free.pure[Alg, AirGen](
bodyGen.op
.wrap(c =>
(
c.copy(data = c.data ++ argNames.zip(argsToData(args))),
_.copy(data = c.data ++ result.map(_.value).zip(retValue))
)
)
new FuncCallable(argNames, retValue, bodyGen).toCallGen(argsToData(args), result.map(_.value))
)
}
@ -56,18 +78,27 @@ object ArrowGen {
): Free[Alg, AirGen] =
// TODO it's really weird that we're losing token here
A.getServiceId(name).map {
case Some(sid) => ServiceCallGen(valueToData(sid), fnName, argsToData(args), result.map(_.value))
case Some(sid) =>
new SrvCallable(valueToData(sid), fnName).toCallGen(argsToData(args), result.map(_.value))
case None =>
NullGen
}
}
def arg(`type`: ArrowType): ArrowGen =
def arg(name: String, `type`: ArrowType): ArrowGen =
new ArrowGen(`type`) {
override def gen[F[_], Alg[_]](args: List[Value[F]], result: Option[Name[F]])(implicit
A: AbilitiesAlgebra[F, Alg]
): Free[Alg, AirGen] = // TODO resolve generator from context!
Free.pure[Alg, AirGen](ServiceCallGen(InitPeerId, "arrow name?", Nil, result.map(_.value)))
): Free[Alg, AirGen] =
Free.pure[Alg, AirGen](
new AirGen {
override def generate(ctx: AirContext): (AirContext, Air) = {
println(Console.YELLOW + ctx + Console.RESET)
ctx.arrows(name).toCallGen(argsToData(args), result.map(_.value)).generate(ctx)
}
}
)
}
}

View File

@ -20,6 +20,7 @@ object Gen {
case (x: ScriptGen, y: ScriptGen) => y.copy(funcs = y.funcs.enqueueAll(x.funcs))
case (x: FuncGen, y: FuncGen) => ScriptGen(Queue(x, y))
case (x: FuncGen, y: ScriptGen) => y.copy(funcs = y.funcs.enqueue(x))
case (x: ScriptGen, y: FuncGen) => x.copy(funcs = x.funcs.enqueue(y))
case (x: AirGen, y: FuncBodyGen) => y.copy(op = SeqGen(x, y.op))
case (x: AirGen, y: ParGen) => ParGen(Some(x), y.right)
case (x: AirGen, y: AirGen) => SeqGen(x, y)
@ -38,7 +39,7 @@ object Gen {
def error: Gen = NoopGen
}
sealed trait AirGen extends Gen {
trait AirGen extends Gen {
self =>
def generate(ctx: AirContext): (AirContext, Air)