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: copy structures implementation [fixes LNG-102] #646

Merged
merged 11 commits into from
Jan 20, 2023
Merged
Show file tree
Hide file tree
Changes from 8 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: 1 addition & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:

aqua-playground:
needs: aqua
uses: fluencelabs/aqua-playground/.github/workflows/tests.yml@master
uses: fluencelabs/aqua-playground/.github/workflows/tests.yml@object-copy
with:
aqua-version: "${{ needs.aqua.outputs.aqua-version }}"

Expand Down
36 changes: 29 additions & 7 deletions aqua-src/antithesis.aqua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
aqua FooBars declares wait
aqua FooBars declares getObjAssign

export wait
export getObjAssign

data Record:
relay_id: []string
Expand Down Expand Up @@ -83,16 +83,38 @@ data SomeObj:
num: u64
inner: InnerObj

func wait(i: []u32) -> SomeObj:
<- SomeObj(str = "some str",
num = 4,
inner = InnerObj(arr = ["a", "b", "c"], num = i[2])
)
-- func wait(i: []u32) -> SomeObj:
-- obj = SomeObj(str = "some str",
-- num = 4,
-- inner = InnerObj(arr = ["a", "b", "c"], num = i[2])
-- )
-- <- obj.copy(str = "ululu")

-- func a(nums: []u32) -> []u32:
-- <- nums
--
-- func some():
-- a([1,2,3,4])

func getObjAssign(arr: []string) -> string:
streamJ: *[]string
streamJ <<- ["111", "222"]
streamJ <<- ["333", "444"]
<- streamJ[arr.length][1]


-- func getObjAssign(arr: []string) -> string:
-- stream: *[]u32
-- stream <<- [0]
-- a = stream[arr.length - 1][0]
-- b = arr[a]
-- <- b
-- func getObjAssign() -> SomeObj, SomeObj, u32:
-- obj = SomeObj(str = "first str",
-- num = 5,
-- inner = InnerObj(arr = ["d", "e", "f"], num = 5)
-- )
-- copiedObj = obj.copy(str = "some str", inner = obj.inner.copy(arr = ["a", "b", "c"])).copy(num = 6)
-- <- obj, copiedObj, copiedObj.inner.copy(arr = ["g"]).arr.length


4 changes: 0 additions & 4 deletions compiler/src/test/scala/aqua/compiler/AquaCompilerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,6 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers {
)
),
join(results, LiteralModel.fromRaw(LiteralRaw.number(2))),
ApRes(
VarModel("results_gate", ArrayType(ScalarType.string), Chain(IntoIndexModel("2", ScalarType.string))),
CallModel.Export("results_gate-0", ScalarType.string)
).leaf,
CanonRes(results, init, CallModel.Export(canonResult.name, canonResult.`type`)).leaf,
ApRes(
canonResult,
Expand Down
6 changes: 4 additions & 2 deletions model/inline/src/main/scala/aqua/model/inline/Inline.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import aqua.raw.value.ValueRaw
import cats.Monoid
import cats.data.Chain

import scala.collection.immutable.ListMap

sealed trait MergeMode
object SeqMode extends MergeMode
object ParMode extends MergeMode
Expand All @@ -17,7 +19,7 @@ object ParMode extends MergeMode
* @param mergeMode how `flattenValues` and `predo` must be merged
*/
private[inline] case class Inline(
flattenValues: Map[String, ValueRaw] = Map.empty,
flattenValues: ListMap[String, ValueRaw] = ListMap.empty,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why ListMap? Comment plz

predo: Chain[OpModel.Tree] = Chain.empty,
mergeMode: MergeMode = ParMode
)
Expand All @@ -26,7 +28,7 @@ private[inline] case class Inline(
private[inline] object Inline {
val empty: Inline = Inline()

def preload(pairs: (String, ValueRaw)*): Inline = Inline(pairs.toMap)
def preload(pairs: (String, ValueRaw)*): Inline = Inline(ListMap.from(pairs))

def tree(tr: OpModel.Tree): Inline = Inline(predo = Chain.one(tr))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ object RawValueInliner extends Logging {
case alr: ApplyPropertyRaw =>
ApplyPropertiesRawInliner(alr, propertiesAllowed)

case alr: ApplyFunctorRaw =>
ApplyFunctorRawInliner(alr, propertiesAllowed)

case agr: ApplyGateRaw =>
ApplyGateRawInliner(agr, propertiesAllowed)

Expand Down Expand Up @@ -91,7 +88,8 @@ object RawValueInliner extends Logging {
}
}.map{ predo =>
inline.mergeMode match
case SeqMode => SeqModel.wrap((inline.predo.toList ++ predo):_*) :: Nil
case SeqMode =>
SeqModel.wrap((inline.predo.toList ++ predo):_*) :: Nil
case ParMode => inline.predo.toList ::: predo
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,29 @@ import aqua.model.{
ValueModel,
VarModel
}
import aqua.model.inline.Inline
import aqua.model.inline.{Inline, SeqMode}
import aqua.model.inline.state.{Arrows, Exports, Mangler}
import aqua.raw.value.ApplyFunctorRaw
import aqua.raw.value.{FunctorRaw, ValueRaw}
import cats.data.State
import cats.data.Chain
import aqua.model.inline.RawValueInliner.unfold
import aqua.types.{BoxType, CanonStreamType, StreamType, ArrayType}
import aqua.types.{ArrayType, BoxType, CanonStreamType, StreamType}
import cats.syntax.monoid.*
import scribe.Logging

object ApplyFunctorRawInliner extends RawInliner[ApplyFunctorRaw] with Logging {
object ApplyFunctorRawInliner extends Logging {

override def apply[S: Mangler: Exports: Arrows](
afr: ApplyFunctorRaw,
propertyAllowed: Boolean
): State[S, (ValueModel, Inline)] = {
val functorModel = FunctorModel(afr.functor.name, afr.functor.`type`)
def apply[S: Mangler: Exports: Arrows](
value: ValueModel,
functor: FunctorRaw
): State[S, (VarModel, Inline)] = {
val functorModel = FunctorModel(functor.name, functor.`type`)

unfold(afr.value).flatMap {
case (v @ VarModel(name, bt, _), inl) =>
value match {
case v @ VarModel(name, bt, _) =>
for {
apName <- Mangler[S].findAndForbidName(name + "_to_functor")
resultName <- Mangler[S].findAndForbidName(s"${name}_${afr.functor.name}")
resultName <- Mangler[S].findAndForbidName(s"${name}_${functor.name}")
(apVar, flat) = {
bt match {
case StreamType(el) =>
Expand All @@ -46,21 +46,23 @@ object ApplyFunctorRawInliner extends RawInliner[ApplyFunctorRaw] with Logging {
}
}
} yield {
val tree = inl |+| Inline.tree(
SeqModel.wrap(
val tree = Inline(
predo = Chain.one(SeqModel.wrap(
flat,
FlattenModel(apVar, resultName).leaf
)
)),
mergeMode = SeqMode
)

VarModel(resultName, afr.functor.`type`) -> tree
VarModel(resultName, functor.`type`) -> tree
}
case (l @ LiteralModel(_, _), inl) =>
ApplyPropertiesRawInliner.flatLiteralWithProperties(l, inl, Chain.one(functorModel), afr.functor.`type`)
case v =>
// unexpected, properties are prohibited for literals
logger.error(s"Unexpected. Properties are prohibited for literals. Literal: '$v'")
State.pure(v)
case l @ LiteralModel(_, _) =>
ApplyPropertiesRawInliner.flatLiteralWithProperties(
l,
Inline.empty,
Chain.one(functorModel),
functor.`type`
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package aqua.model.inline.raw

import aqua.model.{CallModel, CallServiceModel, LiteralModel, OpModel, SeqModel, ValueModel, VarModel}
import aqua.model.inline.{Inline, SeqMode}
import aqua.model.inline.MakeStructRawInliner.createObj
import aqua.model.inline.RawValueInliner.unfold
import aqua.model.inline.state.{Arrows, Exports, Mangler}
import aqua.raw.value.{IntoCopyRaw, LiteralRaw}
import aqua.types.ScalarType
import cats.data.{Chain, NonEmptyMap, State}
import scribe.Logging
import cats.syntax.traverse.*
import cats.syntax.monoid.*
import cats.syntax.functor.*
import cats.syntax.flatMap.*
import cats.syntax.apply.*

object ApplyIntoCopyRawInliner extends Logging {

private def copyObj(value: VarModel, fields: NonEmptyMap[String, ValueModel], result: VarModel): OpModel.Tree = {
val args = fields.toSortedMap.toList.flatMap { case (name, value) =>
LiteralModel.fromRaw(LiteralRaw.quote(name)) :: value :: Nil
}
CallServiceModel(
LiteralModel("\"json\"", ScalarType.string),
"puts",
CallModel(
value +: args,
CallModel.Export(result.name, result.`type`) :: Nil
)
).leaf
}

def apply[S: Mangler: Exports: Arrows](
value: VarModel, intoCopy: IntoCopyRaw
): State[S, (VarModel, Inline)] = {
value match {
case v @ VarModel(name, _, _) =>
for {
name <- Mangler[S].findAndForbidName(name + "_obj_copy")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Pattern matching seems unnecessary there
  • Variable shadowing looks overcomplicated, not sure which name is used where

foldedFields <- intoCopy.fields.nonEmptyTraverse(unfold(_))
} yield {
val varModel = VarModel(name, v.baseType)
val valsInline = foldedFields.toSortedMap.values.map(_._2).fold(Inline.empty)(_ |+| _)
val fields = foldedFields.map(_._1)
val objCreation = copyObj(v, fields, varModel)
(
varModel,
Inline(
valsInline.flattenValues,
Chain.one(SeqModel.wrap((valsInline.predo :+ objCreation).toList: _*)),
SeqMode
)
)
}
}

}
}
Loading