Support for the new (ap instruction (#241)

This commit is contained in:
Dmitry Kurinskiy 2021-08-24 18:59:51 +03:00 committed by GitHub
parent 2124b88442
commit 7e0fe470ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 66 additions and 29 deletions

View File

@ -20,6 +20,8 @@ object Keyword {
case object Call extends Keyword("call")
case object Ap extends Keyword("ap")
case object Seq extends Keyword("seq")
case object Par extends Keyword("par")
@ -94,6 +96,8 @@ object Air {
case class Call(triplet: Triplet, args: List[DataView], result: Option[String])
extends Air(Keyword.Call)
case class Ap(op: DataView, result: String) extends Air(Keyword.Ap)
case class Comment(comment: String, air: Air) extends Air(Keyword.NA)
private def show(depth: Int, air: Air): String = {
@ -120,6 +124,7 @@ object Air {
case Air.Xor(l, r) s"\n${showNext(l)}${showNext(r)}$space"
case Air.Call(triplet, args, res)
s" ${triplet.show} [${args.map(_.show).mkString(" ")}]${res.fold("")(" " + _)}"
case Air.Ap(operand, result) s" ${operand.show} $result"
case Air.Comment(_, _) => ";; Should not be displayed"
}) + ")\n"
}

View File

@ -43,6 +43,11 @@ object AirGen extends Logging {
case list => list.reduceLeft(SeqGen(_, _))
}
def exportToString(exportTo: Call.Export): String = exportTo match {
case Call.Export(name, _: StreamType) => "$" + name
case Call.Export(name, _) => name
}
private def folder(op: ResolvedOp, ops: Chain[AirGen]): Eval[AirGen] =
op match {
// case mt: MetaTag =>
@ -87,13 +92,15 @@ object AirGen extends Logging {
valueToData(serviceId),
funcName,
args.map(valueToData),
exportTo.map {
case Call.Export(name, _: StreamType) => "$" + name
case Call.Export(name, _) => name
}
exportTo.map(exportToString)
)
)
case ApRes(operand, exportTo) =>
Eval.later(
ApGen(valueToData(operand), exportToString(exportTo))
)
case _: NoAir =>
Eval later NullGen
@ -122,6 +129,12 @@ case class CommentGen(comment: String, op: AirGen) extends AirGen {
Air.Comment(comment, op.generate)
}
case class ApGen(operand: DataView, result: String) extends AirGen {
override def generate: Air =
Air.Ap(operand, result)
}
case class MatchMismatchGen(
left: DataView,
right: DataView,

View File

@ -17,7 +17,7 @@ val declineV = "2.1.0"
name := "aqua-hll"
val commons = Seq(
baseAquaVersion := "0.1.14",
baseAquaVersion := "0.2.0",
version := baseAquaVersion.value + "-" + sys.env.getOrElse("BUILD_NUMBER", "SNAPSHOT"),
scalaVersion := dottyVersion,
libraryDependencies ++= Seq(

View File

@ -36,6 +36,11 @@ object LiteralModel {
def quote(str: String): LiteralModel = LiteralModel("\"" + str + "\"", ScalarType.string)
val initPeerId: LiteralModel = LiteralModel("%init_peer_id%", ScalarType.string)
val nil: LiteralModel = LiteralModel(
"[]",
StreamType(BottomType)
)
}
sealed trait LambdaModel {
@ -110,9 +115,4 @@ object VarModel {
)
)
)
val nil: VarModel = VarModel(
"nil",
StreamType(BottomType)
)
}

View File

@ -155,7 +155,7 @@ case class FuncCallable(
.map[(Option[FuncOp], ValueModel)] {
case (exp @ Call.Export(_, StreamType(_)), res) =>
// pass nested function results to a stream
Some(FuncOps.identity(res, exp)) -> exp.model
Some(FuncOps.ap(res, exp)) -> exp.model
case (_, res) =>
None -> res
}

View File

@ -25,6 +25,8 @@ case class FuncOp(tree: Cofree[Chain, RawTag]) extends Model {
def definesVarNames: Eval[Set[String]] = cata[Set[String]] {
case (CallArrowTag(_, Call(_, exportTo)), acc) if exportTo.nonEmpty =>
Eval.later(acc.foldLeft(exportTo.map(_.name).toSet)(_ ++ _))
case (ApTag(_, exportTo), acc) =>
Eval.later(acc.foldLeft(Set(exportTo.name))(_ ++ _))
case (CallServiceTag(_, _, Call(_, exportTo)), acc) if exportTo.nonEmpty =>
Eval.later(acc.foldLeft(exportTo.map(_.name).toSet)(_ ++ _))
case (NextTag(exportTo), acc) => Eval.later(acc.foldLeft(Set(exportTo))(_ ++ _))
@ -36,6 +38,8 @@ case class FuncOp(tree: Cofree[Chain, RawTag]) extends Model {
Eval.later(acc.foldLeft(exportTo.map(_.name).toSet)(_ ++ _))
case (CallServiceTag(_, _, Call(_, exportTo)), acc) if exportTo.nonEmpty =>
Eval.later(acc.foldLeft(exportTo.map(_.name).toSet)(_ ++ _))
case (ApTag(_, exportTo), acc) =>
Eval.later(acc.foldLeft(Set(exportTo.name))(_ ++ _))
case (_, acc) => Eval.later(acc.foldLeft(Set.empty[String])(_ ++ _))
}
@ -45,6 +49,8 @@ case class FuncOp(tree: Cofree[Chain, RawTag]) extends Model {
Eval.later(acc.foldLeft(call.argVarNames)(_ ++ _))
case (CallServiceTag(_, _, call), acc) =>
Eval.later(acc.foldLeft(call.argVarNames)(_ ++ _))
case (ApTag(operand, _), acc) =>
Eval.later(acc.foldLeft(ValueModel.varName(operand).toSet)(_ ++ _))
case (MatchMismatchTag(a, b, _), acc) =>
Eval.later(acc.foldLeft(ValueModel.varName(a).toSet ++ ValueModel.varName(b))(_ ++ _))
case (ForTag(_, VarModel(name, _, _)), acc) =>
@ -67,6 +73,7 @@ case class FuncOp(tree: Cofree[Chain, RawTag]) extends Model {
} match {
case c: CallArrowTag => c.copy(call = c.call.mapExport(n => vals.getOrElse(n, n)))
case c: CallServiceTag => c.copy(call = c.call.mapExport(n => vals.getOrElse(n, n)))
case a: ApTag => a.copy(exportTo = a.exportTo.mapName(n => vals.getOrElse(n, n)))
case a: AssignmentTag => a.copy(assignTo = vals.getOrElse(a.assignTo, a.assignTo))
case t: ForTag if vals.contains(t.item) => t.copy(item = vals(t.item))
case t: NextTag if vals.contains(t.item) => t.copy(item = vals(t.item))

View File

@ -10,9 +10,9 @@ object FuncOps {
def noop: FuncOp =
FuncOp.leaf(CallServiceTag(LiteralModel.quote("op"), "identity", Call(Nil, Nil)))
def identity(what: ValueModel, to: Call.Export): FuncOp =
def ap(what: ValueModel, to: Call.Export): FuncOp =
FuncOp.leaf(
CallServiceTag(LiteralModel.quote("op"), "identity", Call(what :: Nil, to :: Nil))
ApTag(what, to)
)
def callService(srvId: ValueModel, funcName: String, call: Call): FuncOp =

View File

@ -22,6 +22,11 @@ sealed trait RawTag {
funcName,
call.mapValues(f)
)
case ApTag(operand, exportTo) =>
ApTag(
f(operand),
exportTo
)
case AssignmentTag(value, assignTo) =>
AssignmentTag(f(value), assignTo)
case AbilityIdTag(value, ability) =>
@ -83,3 +88,7 @@ case class CallServiceTag(
) extends RawTag {
override def toString: String = s"(call _ ($serviceId $funcName) $call)"
}
case class ApTag(operand: ValueModel, exportTo: Call.Export) extends RawTag {
override def toString: String = s"(ap $operand $exportTo)"
}

View File

@ -36,7 +36,7 @@ case class TransformConfig(
.copy(values =
Map(
VarModel.lastError.name -> VarModel.lastError,
VarModel.nil.name -> VarModel.nil
"nil" -> LiteralModel.nil
) ++ constantsMap
)
)

View File

@ -26,7 +26,7 @@ case class ArgsFromService(dataServiceId: ValueModel, names: List[(String, DataT
item,
VarModel(iter, ArrayType(t.element), Chain.empty),
FuncOps.seq(
FuncOps.identity(VarModel(item, t.element), Call.Export(name, t)),
FuncOps.ap(VarModel(item, t.element), Call.Export(name, t)),
FuncOps.next(item)
)
)

View File

@ -41,6 +41,7 @@ object MakeRes {
case ParTag | ParTag.Detach => ParRes
case XorTag | XorTag.LeftBiased => XorRes
case NextTag(item) => NextRes(item)
case ApTag(operand, exportTo) => ApRes(operand, exportTo)
case CallServiceTag(serviceId, funcName, Call(args, exportTo)) =>
CallServiceRes(
serviceId,

View File

@ -1,6 +1,6 @@
package aqua.model.transform.res
import aqua.model.ValueModel
import aqua.model.{ValueModel, VarModel}
import aqua.model.func.Call
sealed trait ResolvedOp
@ -32,3 +32,14 @@ case class CallServiceRes(
) extends ResolvedOp {
override def toString: String = s"(call $peerId ($serviceId $funcName) $call)"
}
case class ApRes(operand: ValueModel, exportTo: Call.Export) extends ResolvedOp {
override def toString: String = s"(ap $operand $exportTo)"
def mapValues(f: ValueModel => ValueModel): ApRes =
ApRes(f(operand), exportTo)
def mapExport(f: String => String): ApRes = copy(exportTo = exportTo.mapName(f))
def argVarNames: Set[String] = ValueModel.varName(operand).toSet
}

View File

@ -1,7 +1,8 @@
package aqua.semantics.expr
import aqua.model.ValueModel.varName
import aqua.model.func.Call
import aqua.model.func.raw.{CallServiceTag, FuncOp}
import aqua.model.func.raw.{ApTag, FuncOp, FuncOps}
import aqua.model.{LiteralModel, Model}
import aqua.parser.expr.PushToStreamExpr
import aqua.parser.lexer.Token
@ -11,7 +12,7 @@ import aqua.semantics.rules.names.NamesAlgebra
import aqua.semantics.rules.types.TypesAlgebra
import aqua.types.{StreamType, Type}
import cats.free.Free
import cats.syntax.apply._
import cats.syntax.apply.*
class PushToStreamSem[F[_]](val expr: PushToStreamExpr[F]) extends AnyVal {
@ -52,17 +53,7 @@ class PushToStreamSem[F[_]](val expr: PushToStreamExpr[F]) extends AnyVal {
} yield {
if (ensure)
resolvedStreamTypeOp
.map(t =>
FuncOp
.leaf(
// TODO: replace with Apply
CallServiceTag(
LiteralModel.quote("op"),
"identity",
Call(vm :: Nil, Call.Export(expr.stream.value, t) :: Nil)
)
): Model
)
.map(t => FuncOps.ap(vm, Call.Export(expr.stream.value, t)): Model)
.getOrElse(Model.error("Cannot resolve stream type"))
else
Model.error("Stream and pushed element types are not matches")