diff --git a/aqua-src/import.aqua b/aqua-src/import.aqua index e2cd7cb0..0e10769c 100644 --- a/aqua-src/import.aqua +++ b/aqua-src/import.aqua @@ -12,4 +12,4 @@ func invalid_append() -> *string: str: *string asdasd: *string GetStr.retStr(stream, nil) - <- streem \ No newline at end of file + <- stream \ No newline at end of file diff --git a/aqua-src/ret.aqua b/aqua-src/ret.aqua index 4df3f882..ff8e1dd5 100644 --- a/aqua-src/ret.aqua +++ b/aqua-src/ret.aqua @@ -1,31 +1,7 @@ -module Ret +module Ret declares * -import Service from "service" +export someFunc -use "error.aqua" -export GetStr, multiReturnFunc, Service as S - -service GetStr("multiret-test"): - retStr: string -> string - -service GetNum("multiret-num"): - retNum: -> u8 - -const SOME_NUM = 5 -const SOME_STR = "some-str" - -func tupleFunc() -> string, u8: - str <- GetStr.retStr(SOME_STR) - n <- GetNum.retNum() - Err.Peer.is_connected("Connected?") - <- str, n - -func multiReturnFunc(somethingToReturn: []u8, smthOption: ?string) -> []string, u8, string, []u8, ?string, u8: - res: *string - res <- GetStr.retStr(SOME_STR) - try: - res <- GetStr.retStr("random-str") - catch e: - GetStr.retStr(e.msg) - res, tNum <- tupleFunc() - <- res, 5, SOME_STR, somethingToReturn, smthOption, tNum +func someFunc(cb: []string -> ()): + ifaces: *string + cb(ifaces) diff --git a/model/src/main/scala/aqua/model/ValueModel.scala b/model/src/main/scala/aqua/model/ValueModel.scala index ce222a20..a979f222 100644 --- a/model/src/main/scala/aqua/model/ValueModel.scala +++ b/model/src/main/scala/aqua/model/ValueModel.scala @@ -97,8 +97,10 @@ case class VarModel(name: String, `type`: Type, lambda: Chain[LambdaModel] = Cha deriveFrom(vv) } - case Some(vv) => vv // TODO check that lambda is empty, otherwise error - case None => this // Should not happen + case Some(vv) => + vv // TODO check that lambda is empty, otherwise error + case None => + this // Should not happen } override def toString(): String = s"var{$name: " + `type` + s"}.${lambda.toList.mkString(".")}" diff --git a/model/src/main/scala/aqua/model/func/FuncCallable.scala b/model/src/main/scala/aqua/model/func/FuncCallable.scala index 8fffe63c..c15ccb2f 100644 --- a/model/src/main/scala/aqua/model/func/FuncCallable.scala +++ b/model/src/main/scala/aqua/model/func/FuncCallable.scala @@ -3,7 +3,7 @@ package aqua.model.func import aqua.model.ValueModel.varName import aqua.model.func.raw.* import aqua.model.{Model, ValueModel, VarModel} -import aqua.types.{ArrayType, ArrowType, ProductType, StreamType, Type} +import aqua.types.* import cats.Eval import cats.data.Chain import cats.free.Cofree @@ -64,6 +64,8 @@ case class FuncCallable( // Find all duplicates in arguments val argsShouldRename = findNewNames(forbiddenNames, (argsToDataRaw ++ argsToArrowsRaw).keySet) + // we shoudln't rename arguments that will be renamed by 'streamToRename' + .filter{case (k, _) => !streamToRename.contains(k)} val argsToData = argsToDataRaw.map { case (k, v) => argsShouldRename.getOrElse(k, k) -> v } val argsToArrows = argsToArrowsRaw.map { case (k, v) => argsShouldRename.getOrElse(k, k) -> v } @@ -72,7 +74,8 @@ case class FuncCallable( // Substitute arguments (referenced by name and optional lambda expressions) with values // Also rename all renamed arguments in the body - val treeWithValues = body.rename(argsShouldRename ++ streamToRename).resolveValues(argsToData) + val treeWithValues = + body.rename(argsShouldRename).resolveValues(argsToData).rename(streamToRename) // Function body on its own defines some values; collect their names // except stream arguments. They should be already renamed diff --git a/model/src/main/scala/aqua/model/func/raw/FuncOp.scala b/model/src/main/scala/aqua/model/func/raw/FuncOp.scala index 7cf91c86..050f3d86 100644 --- a/model/src/main/scala/aqua/model/func/raw/FuncOp.scala +++ b/model/src/main/scala/aqua/model/func/raw/FuncOp.scala @@ -5,10 +5,10 @@ import aqua.model.{Model, ValueModel, VarModel} import cats.Eval import cats.data.Chain import cats.free.Cofree +import cats.instances.tuple.* import cats.kernel.Semigroup import cats.syntax.apply.* import cats.syntax.functor.* -import cats.instances.tuple.* case class FuncOp(tree: Cofree[Chain, RawTag]) extends Model { def head: RawTag = tree.head diff --git a/model/src/main/scala/aqua/model/func/raw/RawTag.scala b/model/src/main/scala/aqua/model/func/raw/RawTag.scala index 711f6bd8..2c23ed43 100644 --- a/model/src/main/scala/aqua/model/func/raw/RawTag.scala +++ b/model/src/main/scala/aqua/model/func/raw/RawTag.scala @@ -34,6 +34,8 @@ sealed trait RawTag { ) case AssignmentTag(value, assignTo) => AssignmentTag(f(value), assignTo) + case DeclareStreamTag(value) => + DeclareStreamTag(f(value)) case AbilityIdTag(value, ability) => AbilityIdTag(f(value), ability) case _ => this @@ -74,6 +76,10 @@ case class CallArrowTag( call: Call ) extends RawTag +case class DeclareStreamTag( + value: ValueModel +) extends NoExecTag + case class AssignmentTag( value: ValueModel, assignTo: String diff --git a/semantics/src/main/scala/aqua/semantics/expr/DeclareStreamSem.scala b/semantics/src/main/scala/aqua/semantics/expr/DeclareStreamSem.scala index 95c24173..bdfe62eb 100644 --- a/semantics/src/main/scala/aqua/semantics/expr/DeclareStreamSem.scala +++ b/semantics/src/main/scala/aqua/semantics/expr/DeclareStreamSem.scala @@ -1,11 +1,13 @@ package aqua.semantics.expr -import aqua.model.Model +import aqua.model.func.raw.{DeclareStreamTag, FuncOp} +import aqua.model.{Model, VarModel} import aqua.parser.expr.DeclareStreamExpr import aqua.semantics.Prog import aqua.semantics.rules.names.NamesAlgebra import aqua.semantics.rules.types.TypesAlgebra -import aqua.types.{ArrayType, OptionType, StreamType} +import aqua.types.{ArrayType, OptionType, StreamType, Type} +import cats.data.Chain import cats.free.Free class DeclareStreamSem[F[_]](val expr: DeclareStreamExpr[F]) { @@ -18,19 +20,24 @@ class DeclareStreamSem[F[_]](val expr: DeclareStreamExpr[F]) { T.resolveType(expr.`type`) .flatMap { case Some(t: StreamType) => - N.define(expr.name, t) + N.define(expr.name, t).map(b => Option.when(b)(t)) case Some(t: OptionType) => - N.define(expr.name, StreamType(t.element)) + val streamType = StreamType(t.element) + N.define(expr.name, streamType).map(b => Option.when(b)(streamType)) case Some(at @ ArrayType(t)) => - T.ensureTypeMatches(expr.`type`, StreamType(t), at) + val streamType = StreamType(t) + T.ensureTypeMatches(expr.`type`, streamType, at).map(b => Option.when(b)(streamType)) case Some(t) => - T.ensureTypeMatches(expr.`type`, StreamType(t), t) + val streamType = StreamType(t) + T.ensureTypeMatches(expr.`type`, streamType, t).map(b => Option.when(b)(streamType)) case None => - Free.pure[Alg, Boolean](false) + Free.pure[Alg, Option[Type]](None) } .map { - case true => Model.empty(s"Name `${expr.name.value}` defined successfully") - case false => Model.error(s"Name `${expr.name.value}` not defined") + case Some(streamType) => + val valueModel = VarModel(expr.name.value, streamType, Chain.empty) + FuncOp.leaf(DeclareStreamTag(valueModel)): Model + case None => Model.error(s"Name `${expr.name.value}` not defined") } )