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

fix(compiler): Return ability arrow [LNG-258] #935

Merged
merged 10 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
48 changes: 28 additions & 20 deletions aqua-src/antithesis.aqua
Original file line number Diff line number Diff line change
@@ -1,26 +1,34 @@
aqua M
aqua A

export getObj
export test

service OpNum("op"):
identity(n: u32) -> u32
ability InnerAb:
arrow() -> i8, i8

service OpStr("op"):
identity(n: string) -> string
ability TestAb:
inner: InnerAb

service OpArr("op"):
identity(arr: []string) -> []string
-- func create(a: i8, b: i8) -> TestAb:
-- arrow = () -> i8, i8:
-- <- a, b
-- <- TestAb(inner = InnerAb(arrow = arrow))
--
-- func test() -> i8, i8, i8, i8, i8, i8:
-- Ab <- create(1, 2)
-- ab <- create(3, 4)
-- AB <- create(5, 6)
-- res1, res2 <- ab.inner.arrow()
-- res3, res4 <- Ab.inner.arrow()
-- res5, res6 <- AB.inner.arrow()
-- <- res1, res2, res3, res4, res5, res6

data InnerObj:
arr: []string
num: u32
func create(a: i8, b: i8) -> i8 -> i8, i8:
arrow = (c: i8) -> i8, i8:
<- a, b
<- arrow

data SomeObj:
str: string
num: u64
inner: InnerObj

func getObj() -> SomeObj:
b = SomeObj(str = OpStr.identity("some str"), num = 5, inner = InnerObj(arr = ["a", "b", "c"], num = 6))
c = b.copy(str = "new str", inner = b.inner.copy(num = 3))
<- c
func test() -> i8, i8, i8, i8, i8, i8:
Ab <- create(1, 2)
ab <- create(3, 4)
AB <- create(5, 6)
<- res1, res2, res3, res4, res5, res6
36 changes: 33 additions & 3 deletions integration-tests/aqua/examples/abilities.aqua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ aqua Main

use DECLARE_CONST, decl_bar from "imports_exports/declare.aqua" as Declare

export handleAb, SomeService, bug214, checkAbCalls
export handleAb, SomeService, bug214, checkAbCalls, bugLNG258_1, bugLNG258_2, bugLNG258_3

service SomeService("wed"):
getStr(s: string) -> string
Expand Down Expand Up @@ -77,11 +77,41 @@ ability CCCC:
arrow(x: i8) -> bool
simple: SSS

func checkAbCalls() -> bool, bool:
func checkAbCalls() -> bool, bool, bool:
closure = (x: i8) -> bool:
<- x > 20

MySSS = SSS(arrow = closure)
MyCCCC = CCCC(simple = MySSS, arrow = MySSS.arrow)
res1 <- MySSS.arrow(42)
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this test the bug fix?
Let's create a separate test with:

  • Abilities returned from func
  • Abilities with names ab, Ab, AB (or similar in terms of case)

res2 = MyCCCC.arrow(12)

<- res1, res2, MySSS.arrow(50)

ability InnerAb:
arrow() -> i8, i8

ability TestAb:
inner: InnerAb

func create(a: i8, b: i8) -> TestAb:
arrow = () -> i8, i8:
<- a, b
<- TestAb(inner = InnerAb(arrow = arrow))

func bugLNG258_1() -> i8, i8:
ab <- create(1, 2)
res1, res2 <- ab.inner.arrow()
<- res1, res2

func bugLNG258_2() -> i8, i8:
AB <- create(3, 4)
res1, res2 <- AB.inner.arrow()
<- res1, res2

func bugLNG258_3() -> i8, i8:
aB <- create(5, 6)
res1, res2 <- aB.inner.arrow()
<- res1, res2


<- MySSS.arrow(42), MyCCCC.arrow(12)
15 changes: 13 additions & 2 deletions integration-tests/src/__test__/examples.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
import {
abilityCall,
complexAbilityCall,
checkAbCallsCall,
checkAbCallsCall, bugLNG258Call1, bugLNG258Call2, bugLNG258Call3,
} from "../examples/abilityCall.js";
import {
nilLengthCall,
Expand Down Expand Up @@ -550,7 +550,18 @@ describe("Testing examples", () => {

it("ability.aqua ability calls", async () => {
let result = await checkAbCallsCall();
expect(result).toStrictEqual([true, false]);
expect(result).toStrictEqual([true, false, true]);
});

it("ability.aqua bug LNG-258", async () => {
let result1 = await bugLNG258Call1();
expect(result1).toStrictEqual([1, 2]);

let result2 = await bugLNG258Call2();
expect(result2).toStrictEqual([3, 4]);

let result3 = await bugLNG258Call3();
expect(result3).toStrictEqual([5, 6]);
});

it("functors.aqua LNG-119 bug", async () => {
Expand Down
17 changes: 16 additions & 1 deletion integration-tests/src/examples/abilityCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import {
registerSomeService,
bug214,
checkAbCalls,
bugLNG258_1,
bugLNG258_2,
bugLNG258_3,
} from "../compiled/examples/abilities";

export async function abilityCall(): Promise<[string, string, string, number]> {
Expand All @@ -19,6 +22,18 @@ export async function complexAbilityCall(): Promise<[boolean, boolean]> {
return await bug214();
}

export async function checkAbCallsCall(): Promise<[boolean, boolean]> {
export async function checkAbCallsCall(): Promise<[boolean, boolean, boolean]> {
return await checkAbCalls();
}

export async function bugLNG258Call1(): Promise<[number, number]> {
return await bugLNG258_1();
}

export async function bugLNG258Call2(): Promise<[number, number]> {
return await bugLNG258_2();
}

export async function bugLNG258Call3(): Promise<[number, number]> {
return await bugLNG258_3();
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ object ArrowInliner extends Logging {
call: CallModel,
outsideDeclaredStreams: Set[String]
): State[S, InlineResult] = for {
callableFuncBodyNoTopology <- TagInliner.handleTree(fn.body, fn.funcName)
callableFuncBodyNoTopology <- TagInliner.handleTree(fn.body)
callableFuncBody =
fn.capturedTopology
.fold(SeqModel)(ApplyTopologyModel.apply)
Expand Down
6 changes: 6 additions & 0 deletions model/inline/src/main/scala/aqua/model/inline/Inline.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ private[inline] case class Inline(
case Some(tree) => copy(predo = predo :+ tree)
}

def prepend(tree: Option[OpModel.Tree]): Inline =
tree match {
case None => this
case Some(tree) => copy(predo = tree +: predo)
}

def desugar: Inline = {
val desugaredPredo = predo match {
case Chain.nil | _ ==: Chain.nil => predo
Expand Down
55 changes: 36 additions & 19 deletions model/inline/src/main/scala/aqua/model/inline/TagInliner.scala
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
package aqua.model.inline

import aqua.errors.Errors.internalError
import aqua.model.inline.state.{Arrows, Exports, Mangler}
import aqua.model.*
import aqua.model.inline.RawValueInliner.collectionToModel
import aqua.model.inline.raw.{CallArrowRawInliner, CallServiceRawInliner}
import aqua.raw.value.ApplyBinaryOpRaw.Op as BinOp
import aqua.model.inline.state.{Arrows, Exports, Mangler}
import aqua.model.inline.tag.IfTagInliner
import aqua.raw.ops.*
import aqua.raw.value.*
import aqua.types.{BoxType, CanonStreamType, DataType, StreamType}
import aqua.model.inline.Inline.parDesugarPrefixOpt
import aqua.model.inline.tag.IfTagInliner
import aqua.types.{BoxType, CanonStreamType, StreamType}
DieMyst marked this conversation as resolved.
Show resolved Hide resolved

import cats.syntax.traverse.*
import cats.data.{Chain, State, StateT}
import cats.instances.list.*
import cats.syntax.applicative.*
import cats.syntax.flatMap.*
import cats.syntax.apply.*
import cats.syntax.bifunctor.*
import cats.syntax.functor.*
import cats.syntax.option.*
import cats.instances.list.*
import cats.data.{Chain, State, StateT}
import cats.syntax.show.*
import cats.syntax.bifunctor.*
import scribe.{log, Logging}
import cats.syntax.traverse.*
import scribe.Logging

/**
* [[TagInliner]] prepares a [[RawTag]] for futher processing by converting [[ValueRaw]]s into [[ValueModel]]s.
Expand All @@ -35,8 +31,7 @@ import scribe.{log, Logging}
*/
object TagInliner extends Logging {

import RawValueInliner.{callToModel, valueListToModel, valueToModel}

import RawValueInliner.{valueListToModel, valueToModel}
import aqua.model.inline.Inline.parDesugarPrefix

/**
Expand Down Expand Up @@ -178,8 +173,7 @@ object TagInliner extends Logging {
* @return Model (if any), and prefix (if any)
*/
def tagToModel[S: Mangler: Arrows: Exports](
tag: RawTag,
treeFunctionName: String
tag: RawTag
): State[S, TagInlined] =
tag match {
case OnTag(peerId, via, strategy) =>
Expand Down Expand Up @@ -324,6 +318,30 @@ object TagInliner extends Logging {
)
}

case CallArrowRawTag(
exportTo,
ApplyPropertyRaw(vr, IntoArrowRaw(name, at, args))
) =>
RawValueInliner.valueToModel(vr).flatMap {
// the name of VarModel was already converted to abilities full name
case (VarModel(n, _, _), prevInline) =>
CallArrowRawInliner.unfold(CallArrowRaw.ability(n, name, at, args), exportTo).flatMap {
case (_, inline) =>
RawValueInliner
.inlineToTree(inline.prepend(prevInline))
.map(tree =>
TagInlined.Empty(
prefix = SeqModel.wrap(tree).some
)
)
}
case _ =>
internalError(s"Unexpected. 'IntoArrowRaw' can be only used on variables")

}
case CallArrowRawTag(_, value) =>
internalError(s"Cannot inline 'CallArrowRawTag' with value '$value'")

case AssignmentTag(value, assignTo) =>
for {
modelAndPrefix <- value match {
Expand Down Expand Up @@ -429,8 +447,7 @@ object TagInliner extends Logging {
} yield headInlined.build(children)

def handleTree[S: Exports: Mangler: Arrows](
tree: RawTag.Tree,
treeFunctionName: String
tree: RawTag.Tree
): State[S, OpModel.Tree] =
traverseS(tree, tagToModel(_, treeFunctionName))
traverseS(tree, tagToModel(_))
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
abilityType: NamedType,
p: PropertyRaw
): State[S, (VarModel, Inline)] = p match {
case IntoArrowRaw(arrowName, t, arguments) =>
case IntoArrowRaw(arrowName, _, arguments) =>
val arrowType = abilityType.fields
.lookup(arrowName)
.collect { case at @ ArrowType(_, _) =>
Expand Down Expand Up @@ -82,9 +82,9 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
}
}
} yield result
case IntoFieldRaw(fieldName, at @ AbilityType(abName, fields)) =>
case IntoFieldRaw(fieldName, at @ AbilityType(_, _)) =>
(VarModel(AbilityType.fullName(varModel.name, fieldName), at), Inline.empty).pure
case IntoFieldRaw(fieldName, t) =>
case IntoFieldRaw(fieldName, _) =>
for {
abilityField <- Exports[S].getAbilityField(varModel.name, fieldName)
result <- abilityField match {
Expand All @@ -102,6 +102,18 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi

}
} yield result
case icr: IntoCopyRaw =>
internalError(
s"Inlining, cannot use 'copy' ($icr) in ability ($varModel)"
)
case fr: FunctorRaw =>
internalError(
s"Inlining, cannot use functor ($fr) in ability ($varModel)"
)
case iir: IntoIndexRaw =>
internalError(
s"Inlining, cannot use index ($iir) in ability ($varModel)"
)
}

private[inline] def unfoldProperty[S: Mangler: Exports: Arrows](
Expand Down Expand Up @@ -154,6 +166,10 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
mergeMode = SeqMode
)
}
case iar: IntoArrowRaw =>
internalError(
s"Inlining, cannot use arrow ($iar) in non-ability type ($varModel)"
)
}

// Helper for `optimizeProperties`
Expand Down Expand Up @@ -211,7 +227,7 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
State.pure((vm, prevInline.mergeWith(optimizationInline, SeqMode)))
) { case (state, property) =>
state.flatMap {
case (vm @ Ability(name, at, _), leftInline) =>
case (vm @ Ability(_, at, _), leftInline) =>
unfoldAbilityProperty(vm, at, property.raw).map { case (vm, inl) =>
(
vm,
Expand Down Expand Up @@ -317,8 +333,8 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
raw: ValueRaw,
properties: Chain[PropertyRaw],
propertiesAllowed: Boolean
): State[S, (ValueModel, Inline)] = {
((raw, properties.uncons) match {
): State[S, (ValueModel, Inline)] =
(raw, properties.uncons) match {
/**
* To inline
*/
Expand All @@ -338,7 +354,7 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
propertiesAllowed
)
} yield propsInlined
case l =>
case _ =>
internalError(
s"Unfolded stream ($vr) cannot be a literal"
)
Expand All @@ -362,9 +378,7 @@ object ApplyPropertiesRawInliner extends RawInliner[ApplyPropertyRaw] with Loggi
}
}
}
})

}
}

/**
* Remove properties from the var and return a new var without them
Expand Down
Loading
Loading