From 9c284d9f29818e0b238f44cd45f111a852083dae Mon Sep 17 00:00:00 2001 From: Akim Mamedov Date: Mon, 18 Sep 2023 08:02:32 +0700 Subject: [PATCH] Implement wrapper compiler --- packages/core/aqua-wrapper/package.json | 27 ++++ packages/core/aqua-wrapper/src/common.ts | 98 ++++++++++++++ packages/core/aqua-wrapper/src/constants.ts | 17 +++ .../src/generate/__test__/generate.spec.ts | 21 +++ .../generate/__test__/sources/abilities.aqua | 87 ++++++++++++ .../generate/__test__/sources/aliases.aqua | 24 ++++ .../generate/__test__/sources/assignment.aqua | 13 ++ .../__test__/sources/boolAlgebra.aqua | 65 +++++++++ .../generate/__test__/sources/callArrow.aqua | 16 +++ .../src/generate/__test__/sources/canon.aqua | 14 ++ .../__test__/sources/closureReturnRename.aqua | 18 +++ .../generate/__test__/sources/closures.aqua | 73 ++++++++++ .../src/generate/__test__/sources/co.aqua | 13 ++ .../__test__/sources/collectionSugar.aqua | 43 ++++++ .../generate/__test__/sources/complex.aqua | 40 ++++++ .../generate/__test__/sources/constants.aqua | 33 +++++ .../generate/__test__/sources/dataAlias.aqua | 17 +++ .../generate/__test__/sources/example.aqua | 20 +++ .../src/generate/__test__/sources/fold.aqua | 24 ++++ .../generate/__test__/sources/foldJoin.aqua | 19 +++ .../src/generate/__test__/sources/func.aqua | 6 + .../src/generate/__test__/sources/funcs.aqua | 39 ++++++ .../generate/__test__/sources/functors.aqua | 6 + .../generate/__test__/sources/helloWorld.aqua | 6 + .../src/generate/__test__/sources/if.aqua | 36 +++++ .../sources/imports_exports/declare.aqua | 15 +++ .../sources/imports_exports/export2.aqua | 16 +++ .../sources/imports_exports/export3.aqua | 8 ++ .../sources/imports_exports/exports.aqua | 18 +++ .../sources/imports_exports/gen/OneMore.aqua | 2 + .../sources/imports_exports/import2.aqua | 18 +++ .../sources/imports_exports/import3.aqua | 12 ++ .../imports_exports/imports-empty.aqua | 6 + .../sources/imports_exports/imports.aqua | 23 ++++ .../sources/imports_exports/subImport.aqua | 13 ++ .../src/generate/__test__/sources/join.aqua | 26 ++++ .../src/generate/__test__/sources/math.aqua | 79 +++++++++++ .../__test__/sources/multiReturn.aqua | 22 +++ .../generate/__test__/sources/nestedData.aqua | 18 +++ .../__test__/sources/nestedFuncs.aqua | 12 ++ .../src/generate/__test__/sources/object.aqua | 40 ++++++ .../src/generate/__test__/sources/on.aqua | 12 ++ .../__test__/sources/onErrorPropagation.aqua | 39 ++++++ .../src/generate/__test__/sources/option.aqua | 25 ++++ .../__test__/sources/options/option_gen.aqua | 21 +++ .../src/generate/__test__/sources/par.aqua | 34 +++++ .../src/generate/__test__/sources/parseq.aqua | 26 ++++ .../generate/__test__/sources/passArgs.aqua | 24 ++++ .../generate/__test__/sources/println.aqua | 5 + .../__test__/sources/pushToStream.aqua | 9 ++ .../__test__/sources/recursiveStreams.aqua | 13 ++ .../generate/__test__/sources/renameVars.aqua | 25 ++++ .../__test__/sources/returnArrow.aqua | 33 +++++ .../__test__/sources/returnLiteral.aqua | 2 + .../src/generate/__test__/sources/stream.aqua | 69 ++++++++++ .../generate/__test__/sources/streamArgs.aqua | 10 ++ .../__test__/sources/streamCallback.aqua | 7 + .../generate/__test__/sources/streamCan.aqua | 46 +++++++ .../__test__/sources/streamRestriction.aqua | 10 ++ .../__test__/sources/streamResults.aqua | 16 +++ .../__test__/sources/streamScopes.aqua | 83 ++++++++++++ .../__test__/sources/structuraltyping.aqua | 35 +++++ .../__test__/sources/subImportUsage.aqua | 11 ++ .../generate/__test__/sources/topbottom.aqua | 12 ++ .../generate/__test__/sources/topology.aqua | 53 ++++++++ .../generate/__test__/sources/tryCatch.aqua | 25 ++++ .../__test__/sources/tryOtherwise.aqua | 19 +++ .../src/generate/__test__/sources/via.aqua | 17 +++ .../aqua-wrapper/src/generate/function.ts | 46 +++++++ .../core/aqua-wrapper/src/generate/header.ts | 32 +++++ .../core/aqua-wrapper/src/generate/index.ts | 40 ++++++ .../aqua-wrapper/src/generate/interfaces.ts | 125 ++++++++++++++++++ .../core/aqua-wrapper/src/generate/service.ts | 64 +++++++++ packages/core/aqua-wrapper/src/index.ts | 123 +++++++++++++++++ packages/core/aqua-wrapper/src/utils.ts | 60 +++++++++ packages/core/aqua-wrapper/tsconfig.json | 9 ++ .../compilerSupport/aquaTypeDefinitions.ts | 54 ++++---- pnpm-lock.yaml | 72 +++++++++- 78 files changed, 2378 insertions(+), 31 deletions(-) create mode 100644 packages/core/aqua-wrapper/package.json create mode 100644 packages/core/aqua-wrapper/src/common.ts create mode 100644 packages/core/aqua-wrapper/src/constants.ts create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/generate.spec.ts create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/abilities.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/aliases.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/assignment.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/boolAlgebra.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/callArrow.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/canon.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/closureReturnRename.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/closures.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/co.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/collectionSugar.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/complex.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/constants.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/dataAlias.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/example.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/fold.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/foldJoin.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/func.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/funcs.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/functors.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/helloWorld.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/if.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/declare.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/export2.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/export3.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/exports.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/gen/OneMore.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/import2.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/import3.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/imports-empty.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/imports.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/subImport.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/join.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/math.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/multiReturn.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/nestedData.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/nestedFuncs.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/object.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/on.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/onErrorPropagation.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/option.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/options/option_gen.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/par.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/parseq.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/passArgs.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/println.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/pushToStream.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/recursiveStreams.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/renameVars.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/returnArrow.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/returnLiteral.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/stream.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/streamArgs.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/streamCallback.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/streamCan.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/streamRestriction.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/streamResults.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/streamScopes.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/structuraltyping.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/subImportUsage.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/topbottom.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/topology.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/tryCatch.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/tryOtherwise.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/__test__/sources/via.aqua create mode 100644 packages/core/aqua-wrapper/src/generate/function.ts create mode 100644 packages/core/aqua-wrapper/src/generate/header.ts create mode 100644 packages/core/aqua-wrapper/src/generate/index.ts create mode 100644 packages/core/aqua-wrapper/src/generate/interfaces.ts create mode 100644 packages/core/aqua-wrapper/src/generate/service.ts create mode 100644 packages/core/aqua-wrapper/src/index.ts create mode 100644 packages/core/aqua-wrapper/src/utils.ts create mode 100644 packages/core/aqua-wrapper/tsconfig.json diff --git a/packages/core/aqua-wrapper/package.json b/packages/core/aqua-wrapper/package.json new file mode 100644 index 00000000..419b093a --- /dev/null +++ b/packages/core/aqua-wrapper/package.json @@ -0,0 +1,27 @@ +{ + "name": "@fluencelabs/aqua-wrapper", + "type": "module", + "version": "0.1.0", + "description": "Tool for generating aqua wrapper", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "Fluence Labs", + "license": "Apache-2.0", + "dependencies": { + "@fluencelabs/aqua-api": "0.12.0", + "@fluencelabs/aqua-lib": "0.7.3", + "@fluencelabs/interfaces": "workspace:*", + "@fluencelabs/js-client": "*", + "@fluencelabs/registry": "0.8.7", + "@fluencelabs/spell": "0.5.20", + "@fluencelabs/trust-graph": "0.4.7", + "ts-pattern": "5.0.5" + }, + "devDependencies": { + "typescript": "5.1.6", + "vitest": "0.29.7" + } +} diff --git a/packages/core/aqua-wrapper/src/common.ts b/packages/core/aqua-wrapper/src/common.ts new file mode 100644 index 00000000..a8903558 --- /dev/null +++ b/packages/core/aqua-wrapper/src/common.ts @@ -0,0 +1,98 @@ +/* + * Copyright 2023 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ArrowType, NonArrowType, ProductType } from '@fluencelabs/interfaces'; +import { match, P } from 'ts-pattern'; +import { getFuncArgs } from './utils.js'; + +export function genTypeName(t: NonArrowType, name: string): readonly [string | undefined, string] { + const genType = typeToTs(t); + return match(t) + .with( + { tag: 'nil' }, + () => [undefined, 'void'] as const + ).with( + { tag: 'struct' }, + () => [`export type ${name} = ${genType}`, name] as const + ).with( + { tag: P.union('labeledProduct', 'unlabeledProduct') }, + (item) => { + const args = item.tag === 'labeledProduct' + ? Object.values(item.fields) + : item.items; + + if (args.length === 1) { + return genTypeName(args[0], name); + } + + return [`export type ${name} = ${genType}`, name] as const; + }, + ).otherwise(() => [undefined, genType] as const); +} + +export function typeToTs(t: NonArrowType | ArrowType | ProductType): string { + return match(t) + .with( + { tag: 'nil' }, + () => 'null' + ).with( + { tag: 'option' }, + ({ type }) => typeToTs(type) + ' | null' + ).with( + { tag: 'scalar' }, + ({ name }) => match(name) + .with(P.union('u8', 'u16', 'u32', 'u64', 'i8', 'i16', 'i32', 'i64', 'f32', 'f64'), () => 'number') + .with('bool', () => 'boolean') + .with('string', () => 'string') + .with(P._, () => 'any').exhaustive() + ).with( + { tag: 'array' }, + ({ type }) => typeToTs(type) + '[]' + ).with( + { tag: 'struct' }, + ({ fields }) => `{ ${Object.entries(fields).map(([field, type]) => `${field}: ${typeToTs(type)};`).join(' ')} }` + ).with( + { tag: 'labeledProduct' }, + ({ fields }) => `{ ${Object.entries(fields).map(([field, type]) => `${field}: ${typeToTs(type)};`).join(' ')} }` + ).with( + { tag: 'unlabeledProduct' }, + ({ items }) => `[${items.map(item => typeToTs(item)).join(', ')}]` + ).with( + { tag: 'arrow' }, + ({ tag, domain, codomain }) => { + const retType = codomain.tag === 'nil' + ? 'void' + : codomain.items.length === 1 + ? typeToTs(codomain.items[0]) + : typeToTs(codomain); + + const args = getFuncArgs(domain).map(([name, type]) => ([name, typeToTs(type)])); + + const generic = args.length === 0 ? 'null' : args.map(([name]) => `'${name}'`).join(' | '); + args.push(['callParams', `CallParams$$<${generic}>`]); + + const funcArgs = args.map(([name, type]) => `${name}: ${type}`).join(', '); + + return `(${funcArgs}) => ${retType} | Promise<${retType}>`; + } + ).with( + { tag: 'topType' }, + () => 'unknown' + ).with( + { tag: 'bottomType' }, + () => 'never' + ).exhaustive(); +} \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/constants.ts b/packages/core/aqua-wrapper/src/constants.ts new file mode 100644 index 00000000..f6126517 --- /dev/null +++ b/packages/core/aqua-wrapper/src/constants.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const CLIENT = 'IFluenceClient$$'; \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/generate.spec.ts b/packages/core/aqua-wrapper/src/generate/__test__/generate.spec.ts new file mode 100644 index 00000000..0a852439 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/generate.spec.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2023 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe } from 'vitest'; + +describe('Aqua to js/ts compiler', () => { + +}); \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/abilities.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/abilities.aqua new file mode 100644 index 00000000..f7752f3e --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/abilities.aqua @@ -0,0 +1,87 @@ +aqua Main + +use DECLARE_CONST, decl_bar from "imports_exports/declare.aqua" as Declare + +export handleAb, SomeService, bug214, checkAbCalls + +service SomeService("wed"): + getStr(s: string) -> string + +ability SomeAb: + someArrow(s: string) -> string, string + str: string + +ability SecondAb: + arrow(s: string) -> string + num: u32 + +func funcStr(s: string) -> string, string: + strInFunc <- SomeService.getStr(Declare.DECLARE_CONST) + strInFunc2 <- SomeService.getStr(s) + <- strInFunc, strInFunc2 + +func handleSecAb {SomeAb, SecondAb}() -> string, string, string, u32: + SomeAb.someArrow("eferfrfrf") + b, c <- SomeAb.someArrow("efre") + d <- SecondAb.arrow(SomeAb.str) + <- b, c, d, SecondAb.num + +func returnAb(s: string) -> SomeAb: + SomeAb = SomeAb(someArrow = funcStr, str = s) + <- SomeAb + +func handleAb(fff: string) -> string, string, string, u32: + SomeAb = returnAb(fff) + SecondAb = SecondAb(arrow = funcStr, num = 12) + res1, res2, res3, res4 <- handleSecAb{SomeAb, SecondAb}() + <- res1, res2, res3, res4 + +data Struct: + int: i8 + +ability Simple: + st: Struct + arrow(x: i8) -> bool + +ability Complex: + simple: Simple + field: string + +func foo{Complex, Simple}() -> bool, bool: + closure = () -> bool: + <- Simple.st.int >= 0 + res <- closure() + <- Complex.simple.arrow( + Complex.simple.st.int + ), res + +func bug214() -> bool, bool: + closure = (x: i8) -> bool: + <- x > 0 + + MyComplex = Complex( + simple = Simple( + st = Struct(int = 0), + arrow = closure + ), + field = "complex" + ) + + res1, res2 <- foo{MyComplex, MyComplex.simple}() + <- res1, res2 + +ability SSS: + arrow(x: i8) -> bool + +ability CCCC: + arrow(x: i8) -> bool + simple: SSS + +func checkAbCalls() -> bool, bool: + closure = (x: i8) -> bool: + <- x > 20 + + MySSS = SSS(arrow = closure) + MyCCCC = CCCC(simple = MySSS, arrow = MySSS.arrow) + + <- MySSS.arrow(42), MyCCCC.arrow(12) diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/aliases.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/aliases.aqua new file mode 100644 index 00000000..e34d3bb2 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/aliases.aqua @@ -0,0 +1,24 @@ +data SomeData: + value: string + otherValue: u64 + +data SubData: + someStr: string + someNum: i32 + +data SecondData: + value: string + complex: SubData + +data ThirdData: + value: string + complex: SomeData + +service ComplexService("op-ha"): + call(d: SomeData, sd: SecondData) -> SubData + identity() -> SecondData + +func doSmth(d: SomeData, d2: SomeData, sd: SecondData, c: SubData, SecondData -> ThirdData) -> ThirdData: + res <- ComplexService.call(d, sd) + res2 <- c(res, sd) + <- res2 \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/assignment.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/assignment.aqua new file mode 100644 index 00000000..2ba91de6 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/assignment.aqua @@ -0,0 +1,13 @@ +data Prod: + value: string + +service OpHa("op"): + array(a: string, b: string) -> []string + identity(a: string) -> string + +func doSmth(arg: Prod) -> []string: + v = arg.value + a <- OpHa.identity(v) + b = "hello" + res <- OpHa.array(a, b) + <- res \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/boolAlgebra.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/boolAlgebra.aqua new file mode 100644 index 00000000..02f891e0 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/boolAlgebra.aqua @@ -0,0 +1,65 @@ +aqua Bool + +export main, compareStreams, compareStructs, Effector + +service Effector("effector"): + effect(name: string) -> bool + +func foo(x: i8) -> bool: + y = x + 1 + <- y < 5 + +func bar(x: i8) -> i8: + y = x - 1 + <- y + +func compareStreams(peer: string) -> bool: + s1: *i8 + s2: *i8 + + on peer: + s1 <<- bar(43) + s2 <<- bar(43) + + <- s1 == s2 + +data Struct: + field: i8 + str: string + +func compareStructs(peer: string, str: string) -> bool: + on peer: + st1 = Struct(field = 42, str = str) + st2 = Struct(field = 24, str = str) + + <- st1 == st2 + +func main(peer: string) -> []bool: + res: *bool + + on peer: + a = 1 + 2 + b = 2 - 1 + res <<- true || false && true -- true + res <<- (true || false) && true -- true + res <<- foo(3) && b > 0 || a > 4 -- true + res <<- bar(a) > 2 || true -- true + res <<- foo(4) && bar(2) < 2 -- false + res <<- !foo(10) && !!true -- true + res <<- !(bar(2) < 1) || !!(a < 2) -- true + res <<- bar(42) == bar(40 + 2) && foo(10) -- false + res <<- bar(2) < 5 || bar(2) != 1 -- true + + -- Effector is only registered on init_peer + res <<- true || Effector.effect("impossible") -- true + res <<- !!false && Effector.effect("impossible") -- false + res <<- foo(0) || Effector.effect("impossible") -- true + res <<- foo(10) && Effector.effect("impossible") -- false + res <<- Effector.effect("true") || true -- true + res <<- Effector.effect("true") && false -- false + res <<- !foo(10) || Effector.effect("impossible") -- true + res <<- !(1 < 2) && !Effector.effect("impossible") -- false + res <<- !(bar(5) == 5) || Effector.effect("impossible") -- true + res <<- bar(5) != 4 && Effector.effect("impossible") -- false + + <- res \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/callArrow.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/callArrow.aqua new file mode 100644 index 00000000..fce3f0d4 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/callArrow.aqua @@ -0,0 +1,16 @@ +import "println.aqua" +import "@fluencelabs/aqua-lib/builtin.aqua" + +-- functions like `c` are called an 'arrow function' in Aqua +-- `c` passed to a function from a client, so, it could be called only on a client +func passFunctionAsArg(node: string, str: string, c: string -> string): + on node: + Peer.identify() + -- we go here back on a client + res <- c(str) + -- then return on a node + Peer.identify() + print(res) + +func reproArgsBug426(log: string -> (), arg: string): + log(arg) diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/canon.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/canon.aqua new file mode 100644 index 00000000..2f2c7d09 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/canon.aqua @@ -0,0 +1,14 @@ +data Record: + relay_id: []string + peer_id: string + +service Ser("ser"): + getRecord: -> Record + +func bugLng79(log: string -> ()) -> u32: + stream: *Record + stream <- Ser.getRecord() + someone = stream[0] + on someone.peer_id via someone.relay_id: + a = 1 + 1 + <- a \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/closureReturnRename.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/closureReturnRename.aqua new file mode 100644 index 00000000..a86b0d12 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/closureReturnRename.aqua @@ -0,0 +1,18 @@ +aqua ClosureReturnRename + +export lng193Bug + +func getClosure(arg: u16, peer: string) -> u16 -> u16: + on peer: + closure = (x: u16) -> u16: + <- arg + x + <- closure + +func lng193Bug(peer: string, closurePeer: string) -> u16: + on peer: + c = getClosure(42, closurePeer) + b = c + a = b + res1 = a(1) + a(2) -- Call two times for + res2 = b(3) + b(4) -- bug to appear + <- res1 + res2 diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/closures.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/closures.aqua new file mode 100644 index 00000000..d21da611 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/closures.aqua @@ -0,0 +1,73 @@ +module Closure declares * + +import "@fluencelabs/aqua-lib/builtin.aqua" + +export LocalSrv, closureIn, closureOut, closureBig, closureOut2, lng58Bug + +service MyOp("op"): + identity(s: string) -> string + +service LocalSrv("local_srv"): + inside: -> () + +func closureIn(peer1: string) -> string: + variable = "const" + co on peer1: + p1Id <- MyOp.identity("co on") + closure = (s: string) -> string: + if s == "in": + LocalSrv.inside() + p2Id <- MyOp.identity(s) + <- p2Id + p <- closure("in") + <- p + +func closureOut(peer2: string) -> Info: + on peer2: + closure = (s: string) -> Info: + if s == "in": + LocalSrv.inside() + p2Id <- Peer.identify() + <- p2Id + p2Id <- closure("on") + <- p2Id + +func closureOut2(peer2: string) -> Info: + closure = func (s: string) -> Info: + if s == "in": + LocalSrv.inside() + p2Id <- Peer.identify() + <- p2Id + on peer2: + p2Id <- closure("on") + <- p2Id + + +func closureBig(peer1: string, peer2: string) -> string, string: + variable = "const" + co on peer1: + p1Id <- MyOp.identity("co on") + closure = func (s: string) -> string: + p2Id: *string + if s == "in": + p2 <- MyOp.identity(s) + p2Id <<- p2 + else: + p2Info <- Peer.identify() + p2Id <<- p2Info.external_addresses!0 + <- p2Id! + p <- closure("in") + on peer2: + p2Id <- closure("on") + <- p, p2Id + +func lng58Bug() -> string: + status: *string + waiting = (): + avava: *string + avava <<- "frerf" + status <<- "ok" + + waiting() + + <- status! \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/co.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/co.aqua new file mode 100644 index 00000000..0bf82cc0 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/co.aqua @@ -0,0 +1,13 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" + +service CoService("coservice-id"): + call: -> string + +-- here we go to another node and not waiting for execution there +-- all `ParService.call()` will be executed instantly +func coFunc( node: string, c: Info -> () ): + y <- CoService.call() + on node: + t <- Peer.identify() + co c(t) + x <- CoService.call() diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/collectionSugar.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/collectionSugar.aqua new file mode 100644 index 00000000..75f862c0 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/collectionSugar.aqua @@ -0,0 +1,43 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" + +func arraySugar(n: u32, m: u32) -> []u32, []u32: + arr = [1,2,n] + str: *u32 + for i <- [4,5,m]: + str <<- i + <- arr, str + +func streamSugar(n: u32, m: u32) -> []u32, []u32: + arr = *[1,2,n] + str: *u32 + for i <- *[4,5,m]: + str <<- i + <- arr, str + +func optionSugar(numSome: ?u32, strSome: ?string, numNone: ?u32, strNone: ?string) -> []u32, []string, []string: + arr = ?[numNone!, numSome!] + str: *string + str2 = ?[strNone!, strNone!, strNone!, strNone!, strNone!] + for i <- ?[strSome!,strNone!, "random string"]: + str <<- i + + for i <- ?[strNone!,strNone!]: + str <<- i + <- arr, str, str2 + +service OpO("op"): + identity: string -> string + +service GetArr("getArr"): + getArr: -> []string + +func getNeighbours() -> []string: + nodes <- GetArr.getArr() + <- nodes + +func bugLNG59() -> string: + nodes <- getNeighbours() + n = nodes[1] + on n via [HOST_PEER_ID]: + res <- OpO.identity("some str") + <- res diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/complex.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/complex.aqua new file mode 100644 index 00000000..1634b558 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/complex.aqua @@ -0,0 +1,40 @@ +import "helloWorld.aqua" +import "println.aqua" +import "@fluencelabs/aqua-lib/builtin.aqua" +import "func.aqua" + +service TestS("some-id"): + t: string -> string + multiline( -- comments + a: string, -- comments + b: string, -- comments + c: bool -- comments + ) -> string -- comments + +-- just a lot of imports and calls +func doStuff( -- comments + a: string, -- comments + b: string, -- comments + c: bool, + d: bool, e: []string, g: []string, str: string -- comments + ) -> []string: -- comments + stream: *string + stream <- TestS.t(str) + par Println.print(a) + par on a: + Peer.identify() + on a: + on b: + if c: + if d: + for eEl <- e: + for gEl <- g: + stream <- TestS.t(gEl) -- comments + stream <- TestS.t(eEl) + stream <- TestS.t(eEl) + stream <- TestS.multiline( -- comments + a, -- comments + b, -- comments + c -- comments + ) -- comments + <- stream diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/constants.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/constants.aqua new file mode 100644 index 00000000..116dc2e6 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/constants.aqua @@ -0,0 +1,33 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" + +service Getter("test"): + createStr: u32 -> string + +service OpO("op"): + identity: string -> string + +service OpN("op"): + identity: i32 -> i32 + +-- a question mark means that this constant could be rewritten before this definition +const ANOTHER_CONST ?= "default-str" +const UNIQUE_CONST ?= 5 + +func callConstant() -> []string: + res: *string + res <- Getter.createStr(UNIQUE_CONST) + res <- OpO.identity(ANOTHER_CONST) + <- res + +func timestampAndTtl() -> u32, u64: + Op.noop() + <- PARTICLE_TTL, PARTICLE_TIMESTAMP + +const A = 2 +const B = -3 + +func compareConstants(): + if A == B: + OpN.identity(A) + else: + OpN.identity(B) diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/dataAlias.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/dataAlias.aqua new file mode 100644 index 00000000..ea2e94e6 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/dataAlias.aqua @@ -0,0 +1,17 @@ +-- set `PeerId` name to be a type alias for `string` type +alias PeerId : string + +-- define data structure (ADT) +data NodeId: + peerId: PeerId + name: string + +-- define service `NodeIdGetter` that will be callable on local client via `somesrv` service id +service NodeIdGetter("somesrv"): + get: -> NodeId + +-- showcases a function that gets data structure from a local service, +-- and then retrieves aliased data type from that structure +func getAliasedData() -> PeerId: + res <- NodeIdGetter.get() + <- res.peerId diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/example.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/example.aqua new file mode 100644 index 00000000..3a8d6221 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/example.aqua @@ -0,0 +1,20 @@ +service Peer("peer"): + is_connected: string -> bool + +service Op("op"): + identity: -> () + +data User: + peer_id: string + relay_id: string + name: string + +service Test("test"): + getUserList: -> []User + doSomething: -> bool + +func betterMessage(relay: string): + on relay: + isOnline <- Peer.is_connected(relay) + if isOnline: + Test.doSomething() \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/fold.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/fold.aqua new file mode 100644 index 00000000..848b6957 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/fold.aqua @@ -0,0 +1,24 @@ +import "println.aqua" +import "@fluencelabs/aqua-lib/builtin.aqua" + +-- showcases `for` instruction that compiles to `fold` in AIR +func iterateAndPrint(strings: []string): + for s <- strings: + print(s) + +func iterateAndPrintParallel(nodes: []string, c: Info -> ()): + for s <- nodes par: + on s: + ads <- Peer.identify() + c(ads) + +func to_i_64(i: u32) -> i64: + <- i + +func forBug499() -> []i64: + num = 5 + numbers: *i64 + for i <- [""]: + ali64 <- to_i_64(num) + numbers <<- ali64 + <- numbers diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/foldJoin.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/foldJoin.aqua new file mode 100644 index 00000000..3548e058 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/foldJoin.aqua @@ -0,0 +1,19 @@ +module FoldJoin + +import "@fluencelabs/aqua-lib/builtin.aqua" + +export getTwoResults + +service Op2("op"): + identity(s: u64) + +func getTwoResults(node: string) -> []u64: + on node: + nodes <- Kademlia.neighborhood(%init_peer_id%, nil, nil) + res: *u64 + for n <- nodes par: + on n: + try: + res <- Peer.timestamp_sec() + join res!2 + <- res \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/func.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/func.aqua new file mode 100644 index 00000000..68df4566 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/func.aqua @@ -0,0 +1,6 @@ +service TestSrv("test-service-id"): + str: -> string + +func testFunc() -> string: + res <- TestSrv.str() + <- res diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/funcs.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/funcs.aqua new file mode 100644 index 00000000..c28652dd --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/funcs.aqua @@ -0,0 +1,39 @@ +module Funcs declares main, A, calc + +export main, A, calc, calc2, ifCalc + +service A("a"): + getJ(i: u32) -> u32 + +func main(log: string, []u32 -> ()) -> u32: + closure = (i: []u32, j: u32) -> u32: + some <- A.getJ(i[j]) + <- some + closure2 = func (i: []u32, j: u32) -> u32: + some <- A.getJ(i[j]) + <- some + arr = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19] + idx1 <- A.getJ(arr[A.getJ(3) + 2]) -- 5 + idx2 <- A.getJ(arr[A.getJ(3) + 3] + arr[A.getJ(1) - 1] - 3) -- 3 + <- A.getJ(arr[(idx1 + idx2) + closure(arr, 2) + closure2(arr, 3)]) -- should be 13 + + +func calc(log: string, []u32 -> ()) -> u32: + arr = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19] + num <- A.getJ((5-2)*3-3) -- 6 + log("calc 2", [num]) + <- arr[num] -- should be 6 + +func calc2(log: string, []u32 -> ()) -> u32: + arr = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19] + num <- A.getJ((5-2) * 3 - 3 ** (A.getJ(5 + 5) - A.getJ(3 ** (3 - 1)))) -- 6 + <- arr[num + num - A.getJ(num) - 3] -- should be 3 + +func ifCalc() -> u64: + arr = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19] + res: *u64 + if A.getJ(8 - 2) + A.getJ(4 % 2) > arr[5 - 3 + A.getJ(3)] - 2: + res <<- 1 + else: + res <<- 2 + <- res!0 diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/functors.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/functors.aqua new file mode 100644 index 00000000..fc6f35d4 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/functors.aqua @@ -0,0 +1,6 @@ +func lng119Bug() -> []u32: + nums = [1,2,3,4,5] + results: *u32 + results <<- 1 + join results[nums.length-5] + <- results \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/helloWorld.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/helloWorld.aqua new file mode 100644 index 00000000..6831cfbb --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/helloWorld.aqua @@ -0,0 +1,6 @@ +service StringExtra("service-id"): + addNameToHello: string -> string + +func helloWorld(name: string) -> string: + res <- StringExtra.addNameToHello(name) + <- res diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/if.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/if.aqua new file mode 100644 index 00000000..e186c37c --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/if.aqua @@ -0,0 +1,36 @@ +import "println.aqua" +import "@fluencelabs/aqua-lib/builtin.aqua" + +service OpR("op"): + identity(s: string) -> string + +func ifElseCall(condition: bool): + if condition: + Println.print("it is true") + else: + Println.print("it is false") + +func ifElseNumCall(condition: u32): + if condition == 1: + Println.print("it is 1") + else: + Println.print("it is not 1") + +func ifCorrectXorWrap(node: string) -> string: + service_id: *string + on node: + res <- OpR.identity("1234") + if res == "": + service_id <<- "0x" + else: + service_id <<- "1x" + <- service_id! + +func bugLNG69(other_node: PeerId) -> bool: + on other_node: + Op.noop() + + if false: + Op.noop() + + <- true \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/declare.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/declare.aqua new file mode 100644 index 00000000..cbe72676 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/declare.aqua @@ -0,0 +1,15 @@ +module FooBars declares decl_foo, decl_bar, SuperFoo, DECLARE_CONST, DECLARE_CONST2 +export SuperFoo + +const DECLARE_CONST = "declare_const" +const DECLARE_CONST2 = "declare_const2" + +service SuperFoo("super_foo"): + small_foo() -> string + +func decl_foo() -> string: + res1 <- SuperFoo.small_foo() + <- res1 + +func decl_bar() -> string: + <- "declare all bar" \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/export2.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/export2.aqua new file mode 100644 index 00000000..abb06d02 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/export2.aqua @@ -0,0 +1,16 @@ +module Export declares foobar, foo + +import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua" + +func bar() -> string: + <- " I am MyFooBar bar" + +func foo() -> string: + <- "I am MyFooBar foo" + +func foobar() -> []string: + Noop.noop() + res: *string + res <- foo() + res <- bar() + <- res diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/export3.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/export3.aqua new file mode 100644 index 00000000..0d117675 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/export3.aqua @@ -0,0 +1,8 @@ +-- exports3.aqua +module Export3 declares * + +import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua" + +func foo() -> string: + Noop.noop() + <- "I am MyFooBar foo" \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/exports.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/exports.aqua new file mode 100644 index 00000000..c2d3ea4b --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/exports.aqua @@ -0,0 +1,18 @@ +module Exports declares some_string, MyExportSrv, EXPORT_CONST, some_random_func + +import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua" + +export some_string as string_from_lib +export MyExportSrv + +const EXPORT_CONST = "export_const" + +service MyExportSrv("my_export_srv"): + another_str() -> string + +func some_string() -> string: + Noop.noop() + <- "some_string_func" + +func some_random_func() -> string: + <- "wow, so random" \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/gen/OneMore.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/gen/OneMore.aqua new file mode 100644 index 00000000..6582acb8 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/gen/OneMore.aqua @@ -0,0 +1,2 @@ +service OneMore: + more_call() \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/import2.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/import2.aqua new file mode 100644 index 00000000..ca74cb25 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/import2.aqua @@ -0,0 +1,18 @@ +module Import +import foobar from "export2.aqua" + +use foo as f from "export2.aqua" as Exp + +import "gen/OneMore.aqua" + +import OneMore as OM from "gen/OneMore.aqua" + +export foo_wrapper as wrap, foobar as barfoo + +func foo_wrapper() -> string: + z <- Exp.f() + OneMore "hello" + OneMore.more_call() + OM "ohmygod" + OM.more_call() + <- z \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/import3.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/import3.aqua new file mode 100644 index 00000000..9c3dafab --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/import3.aqua @@ -0,0 +1,12 @@ +-- imports3.aqua +module Import3 declares * +import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua" + +export foo_wrapper + +use "export3.aqua" + +func foo_wrapper() -> string: + Noop.noop() + z <- Export3.foo() + <- z \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/imports-empty.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/imports-empty.aqua new file mode 100644 index 00000000..bf2f26a3 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/imports-empty.aqua @@ -0,0 +1,6 @@ +import decl_foo, decl_bar from "declare.aqua" +use DECLARE_CONST, SuperFoo, DECLARE_CONST2 as DC2 from "declare.aqua" as Declare +import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua" +import some_string, MyExportSrv, EXPORT_CONST, some_random_func from "exports.aqua" + +export some_string as some_str, some_random_func, MyExportSrv, EXPORT_CONST \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/imports.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/imports.aqua new file mode 100644 index 00000000..2d7e6785 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/imports.aqua @@ -0,0 +1,23 @@ +import decl_foo, decl_bar from "declare.aqua" +use DECLARE_CONST, SuperFoo, DECLARE_CONST2 as DC2 from "declare.aqua" as Declare +import Op as Noop from "@fluencelabs/aqua-lib/builtin.aqua" +import some_string, MyExportSrv, EXPORT_CONST from "exports.aqua" +use "export3.aqua" + +service StringService("string_service"): + concat(a: string, b: string) -> string + +func concat_foobars() -> string: + Noop.noop() + Export3.foo() + res1 <- decl_foo() + res2 <- decl_bar() + res3 <- StringService.concat(res1, res2) + res4 <- Declare.SuperFoo.small_foo() + Noop.noop() + res5 <- StringService.concat(res3, res4) + res6 <- StringService.concat(res5, EXPORT_CONST) + res7 <- StringService.concat(res6, Declare.DECLARE_CONST) + Noop.noop() + res8 <- StringService.concat(res7, Declare.DC2) + <- res8 \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/subImport.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/subImport.aqua new file mode 100644 index 00000000..e7f060b4 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/imports_exports/subImport.aqua @@ -0,0 +1,13 @@ + +alias SomeString : string + +data SomeResult: + one: SomeString + two: u32 + +service SubService("sub_service"): + sub(s: SomeString) -> SomeResult + +func subImport() -> SomeResult: + res <- SubService.sub("some thing") + <- res diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/join.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/join.aqua new file mode 100644 index 00000000..63ab8577 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/join.aqua @@ -0,0 +1,26 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" + +func joinIdxLocal(idx: i16, nodes: []string) -> []string: + nodes2: *string + for node <- nodes par: + nodes2 <<- node + join nodes2[idx], nodes + <- nodes2 + +func joinIdxRelay(idx: i16, nodes: []string) -> []string: + on HOST_PEER_ID: + nodes2: *string + for node <- nodes par: + nodes2 <<- node + join nodes2[idx], nodes + <- nodes2 + +func joinIdx(idx: i16, nodes: []string) -> []Info: + infos: *Info + nodes2: *string + for node <- nodes par: + on node: + infos <- Peer.identify() + nodes2 <<- node + join infos[idx-1+1], nodes2[idx-1+1] + <- infos diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/math.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/math.aqua new file mode 100644 index 00000000..544e8a83 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/math.aqua @@ -0,0 +1,79 @@ +aqua Math + +export test1, test2, testI16, testI32, testI64, testU64 + +func test1() -> u64: + res = 1 + 2 - 3 * 5 - 2 * 3 / 2 + 5 + <- res + +func test2() -> u64: + res = 2 ** 2 ** (2 * 2 - 2) + 2 - 3 * 5 - 2 * 3 / 2 + 5 + (4 % 2 - 2) + <- res + +func getI8() -> i8: + <- -8 + +func getI16() -> i16: + <- -16 + +func getI32() -> i32: + <- -32 + +func getI64() -> i64: + <- -64 + +func getU8() -> u8: + <- 8 + +func getU16() -> u16: + <- 16 + +func getU32() -> u32: + <- 32 + +func getU64() -> u64: + <- 64 + +func testI16(peer: string) -> []i16: + res: *i16 + + on peer: + res <<- getI16() + getI16() + res <<- getI8() * getU8() + res <<- getI8() % getI16() + res <<- getI16() - getI8() + + <- res + +func testI32(peer: string) -> []i32: + res: *i32 + + on peer: + res <<- getI32() + getU16() + res <<- getI16() * getU16() + res <<- getI8() % getU16() + res <<- getI16() - getI32() + + <- res + +func testI64(peer: string) -> []i64: + res: *i64 + + on peer: + res <<- getI32() + getU32() + res <<- getI16() * getU32() + res <<- getI64() % getI64() + res <<- getU8() - getI64() + + <- res + +func testU64(peer: string) -> []u64: + res: *u64 + + on peer: + res <<- getU32() + getU64() + res <<- getU64() * getU64() + res <<- getU64() % getU16() + res <<- getU8() - getU64() + + <- res \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/multiReturn.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/multiReturn.aqua new file mode 100644 index 00000000..1164af6d --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/multiReturn.aqua @@ -0,0 +1,22 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" + +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() + <- str, n + +func multiReturnFunc(somethingToReturn: []u8, smthOption: ?string) -> []string, u8, string, []u8, ?string, u8 : + res: *string + res <- GetStr.retStr(SOME_STR) + res <- GetStr.retStr("random-str") + res, tNum <- tupleFunc() + <- res, SOME_NUM, SOME_STR, somethingToReturn, smthOption, tNum diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/nestedData.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/nestedData.aqua new file mode 100644 index 00000000..1fe58f09 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/nestedData.aqua @@ -0,0 +1,18 @@ +data NestedType: + val: string + +data NestedStruct: + one: NestedType + +service Test("service"): + test1() -> NestedStruct + test2(arg1: NestedType, arg2: string) -> NestedStruct + +func test3() -> NestedType: + res <- Test.test1() + <- res.one + +func test() -> NestedStruct: + struct <- test3() + res <- Test.test2(struct, struct.val) + <- res \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/nestedFuncs.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/nestedFuncs.aqua new file mode 100644 index 00000000..55ed03de --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/nestedFuncs.aqua @@ -0,0 +1,12 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" + +service OpH("opa"): + identity(s: string) -> string + +func a(b: string) -> string: + c <- OpH.identity(b) + <- c + +func d(e: string) -> string: + f <- a(e) + <- f \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/object.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/object.aqua new file mode 100644 index 00000000..ee41a3fe --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/object.aqua @@ -0,0 +1,40 @@ +aqua StructCreation declares getObj, getObjRelay, getObjAssign + +export getObj, getObjRelay, getObjAssign + +import "@fluencelabs/aqua-lib/builtin.aqua" + +data InnerObj: + arr: []string + num: u32 + +data SomeObj: + str: string + num: u64 + inner: InnerObj + +service OpNum("op"): + identity(n: u32) -> u32 + +service OpStr("op"): + identity(n: string) -> string + +service OpArr("op"): + identity(arr: []string) -> []string + +func getObj() -> SomeObj: + <- SomeObj(str = OpStr.identity("some str"), num = 5, inner = InnerObj(arr = ["a", "b", "c"], num = 6)) + +func getObjRelay() -> SomeObj: + on HOST_PEER_ID: + obj = SomeObj(str = "diff str", num = 5, inner = InnerObj(arr = OpArr.identity(["a", "b", "c"]), num = 6)) + Op.noop() + <- obj.copy(str = "some str") + +func getObjAssign() -> SomeObj, SomeObj, u32: + obj = SomeObj(str = "first str", + num = OpNum.identity(5), + inner = InnerObj(arr = ["d", "e", "f"], num = 7) + ) + 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 \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/on.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/on.aqua new file mode 100644 index 00000000..0bc01ccc --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/on.aqua @@ -0,0 +1,12 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" + +func getPeerExternalAddresses(otherNodePeerId: string) -> []string: + on otherNodePeerId: + res <- Peer.identify() + <- res.external_addresses + +-- it is possible to use `via` to built complex routes +func getDistantAddresses(target: string, viaNode: string) -> []string: + on target via viaNode: + res <- Peer.identify() + <- res.external_addresses diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/onErrorPropagation.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/onErrorPropagation.aqua new file mode 100644 index 00000000..f0a67a35 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/onErrorPropagation.aqua @@ -0,0 +1,39 @@ +service Test("test-service"): + fail(err: string) + +func onPropagate(peer: string, relay: string) -> u16: + res: *u16 + on peer via relay: + res <<- 0 + 1 + Test.fail("propagated error") + res <<- 0 + 2 + + join res[3] -- Unreachable + + <- res[3] + +func nestedOnPropagate(peer: string, relay: string, iPeer: string, iRelay: string, friend: string) -> u16: + res: *u16 + on iPeer via iRelay: + res <<- 40 + 2 + on friend: + res <<- 2 + 40 + on peer via relay: + Test.fail("propagated error") + res <<- 30 + 7 + + join res[3] -- Unreachable + + <- res[3] + +func seqOnPropagate(peer: string, relay: string, iPeer: string, iRelay: string) -> u16: + res: *u16 + on iPeer via iRelay: + res <<- 40 + 2 + on peer via relay: + Test.fail("propagated error") + res <<- 30 + 7 + + join res[2] -- Unreachable + + <- res[2] \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/option.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/option.aqua new file mode 100644 index 00000000..8b178c8e --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/option.aqua @@ -0,0 +1,25 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" + +service SomeS("test2"): + getStr: ?string -> ?string + getStr1: -> ?string + getStr2: string -> string + checkU32(u: ?u32) + +func checkU32AndU8(a: ?u8): + SomeS.checkU32(a) + +func useOptional(opt: ?string) -> string: + res <- SomeS.getStr(opt) + for i <- opt: + SomeS.getStr2(i) + <- res! + +func returnOptional() -> ?string: + res <- SomeS.getStr1() + <- res + +func returnNone() -> ?string: + result: *string + Op.noop() + <- result \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/options/option_gen.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/options/option_gen.aqua new file mode 100644 index 00000000..394e96c2 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/options/option_gen.aqua @@ -0,0 +1,21 @@ +service OptionString("opt_str"): + checkOption(str: ?string) -> string + +func emptyString() -> ?string: + valueEmpty: ?string + <- valueEmpty + +func checkEmpty() -> string: + empty <- emptyString() + res <- OptionString.checkOption(empty) + <- res + +func stringAsOption(str: string) -> ?string: + valueEmpty: ?string + valueEmpty <<- str + <- valueEmpty + +func checkNoneEmpty(str: string) -> string: + nonEmpty <- stringAsOption(str) + res <- OptionString.checkOption(nonEmpty) + <- res diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/par.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/par.aqua new file mode 100644 index 00000000..dc19a4ba --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/par.aqua @@ -0,0 +1,34 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" + +service ParService("parservice-id"): + call: -> string + +-- here we go to another node and not waiting for execution there +-- all `ParService.call()` will be executed instantly +func parFunc( node: string, c: Info -> () ): + y <- ParService.call() + par on node: + t <- Peer.identify() + c(t) + par x <- ParService.call() + +func testTimeout(nodes: []string) -> string: + on HOST_PEER_ID: + + results: *Info + + for node <- nodes par: + on node: + results <- Peer.identify() + + timeout: *string + join results[999] + par timeout <- Peer.timeout(400, "timeout") + + status: *string + if timeout == nil: + status <<- "ok" + else: + status <<- timeout! + + <- status! diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/parseq.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/parseq.aqua new file mode 100644 index 00000000..8ab129b5 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/parseq.aqua @@ -0,0 +1,26 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" + +service NumOp("op"): + identity(n: u64) -> u64 + +data PeerRelay: + peer: string + relay: string + +func testParSeq(peer1: string, peer2: string, peer3: string, relay1: string, relay2: string, relay3: string) -> string: + pr1 = PeerRelay(peer = peer1, relay = relay1) + pr2 = PeerRelay(peer = peer2, relay = relay2) + pr3 = PeerRelay(peer = peer3, relay = relay3) + peers = [pr1, pr2, pr3] + stream: *u64 + stream2: *u64 + parseq p <- peers on p.peer via p.relay: + stream <- Peer.timestamp_ms() + + for p <- peers par: + on p.peer via p.relay: + join stream[peers.length - 1] + stream2 <<- Peer.timestamp_ms() + + join stream2[peers.length - 1] + <- "ok" \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/passArgs.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/passArgs.aqua new file mode 100644 index 00000000..21536682 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/passArgs.aqua @@ -0,0 +1,24 @@ +import Op from "@fluencelabs/aqua-lib/builtin.aqua" + +service AquaDHT("test-dht"): + put_host_value(key: string, value: string, service_id: []string) -> string + +func putHostValue(key: string, value: string, service_id: ?string) -> string: + res <- AquaDHT.put_host_value(key, value, service_id) + <- res + +func create_client_util(service_id: string) -> string: + res <- putHostValue("client-util", service_id, nil) + <- res + +func wait(successful: *bool, n: i16): + join successful[n - 1] + +func bugLNG60(node: string) -> bool: + successful: *bool + nodes = [node] + for n <- nodes: + successful <<- true + + wait(successful, 1) + <- true \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/println.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/println.aqua new file mode 100644 index 00000000..1a5f47af --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/println.aqua @@ -0,0 +1,5 @@ +service Println("println-service-id"): + print: string -> () + +func print(str: string): + Println.print(str) diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/pushToStream.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/pushToStream.aqua new file mode 100644 index 00000000..e34ea74f --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/pushToStream.aqua @@ -0,0 +1,9 @@ +service OpA("pop"): + get_str() -> string + +func get_results() -> []string: + results: *string + results <<- "hello" + str <- OpA.get_str() + results <<- str + <- results \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/recursiveStreams.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/recursiveStreams.aqua new file mode 100644 index 00000000..fb8f8da5 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/recursiveStreams.aqua @@ -0,0 +1,13 @@ + +service YesNoService("yesno"): + get() -> string + +func recursiveStream() -> []string, []string: + result: *string + loop: *string + loop <<- "yes" + for l <- loop: + if l == "yes": + loop <- YesNoService.get() + result <<- "success" + <- result, loop diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/renameVars.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/renameVars.aqua new file mode 100644 index 00000000..15750f06 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/renameVars.aqua @@ -0,0 +1,25 @@ +aqua RenameVars + +export rename_s + +func append_func(s: *string): + s <<- "ok" + +func append(s: string, closure: *string -> ()) -> *string: + status: *string + + append_func(status) + closure(status) + + <- status + +func rename_s() -> []string: + on HOST_PEER_ID: + append_closure = (s: *string): + s <<- "ok" + -- s inside append_func and append_closure + -- are not related to this s and should be + -- renamed to `status` and not `s-` + s = "s" + res <- append(s, append_closure) + <- res \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/returnArrow.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/returnArrow.aqua new file mode 100644 index 00000000..73112dcf --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/returnArrow.aqua @@ -0,0 +1,33 @@ +aqua ReturnArrow + +import "@fluencelabs/aqua-lib/builtin.aqua" + +export callReturnedArrow, callReturnedChainArrow + +func returnCall(arg: string) -> string -> string, string: + str <- Op.concat_strings(arg, " literal") + closure = (s: string) -> string, string: + <- s, Op.concat_strings(s, str) + <- closure + +func callReturnedArrow(argForFunc: string, argForClosure: string) -> string, string: + a = returnCall(argForFunc) + b, c <- a(argForClosure) + <- b, c + +func secondReturnCall(arg: string) -> (string -> string, string), (string -> string, string), (string -> string, string): + str <- Op.concat_strings(arg, " second literal") + closure = (s: string) -> string, string: + <- s, Op.concat_strings(s, str) + b = closure + a = returnCall(" from second") + <- b, closure, a + +func callReturnedChainArrow(argForFirst: string, argForSecond: string) -> string, string, string, string, string, string, string, string: + first = returnCall(argForFirst) + second, third, fourth <- secondReturnCall(argForSecond) + a, b <- first("first") + c, d <- second("second") + e, f <- third("third") + g, h <- fourth("fourth") + <- a, b, c, d, e, f, g, h \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/returnLiteral.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/returnLiteral.aqua new file mode 100644 index 00000000..5fd54049 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/returnLiteral.aqua @@ -0,0 +1,2 @@ +func returnLiteral() -> string: + <- "some literal" \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/stream.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/stream.aqua new file mode 100644 index 00000000..e678c06f --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/stream.aqua @@ -0,0 +1,69 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" +import "println.aqua" + +service Stringer("stringer-id"): + returnString: string -> string + +func checkStreams(ch: []string) -> []string: + stream: *string + stream <- Stringer.returnString("first") + stream <- Stringer.returnString("second") + for b <- ch: + stream <- Stringer.returnString(b) + <- stream + +func getStream() -> *u32: + nums = *[1,2,3,4] + <- nums + +func returnStreamFromFunc() -> *u32: + nums <- getStream() + <- nums + +func stringNil() -> *string: + valueNil: *string + <- valueNil + +func returnNil() -> *string: + relayNil <- stringNil() + <- relayNil + +func returnNilLiteral() -> *string: + <- nil + +func returnNilLength() -> u32: + arr = nil + <- arr.length + +func stringNone() -> ?string: + valueNone: ?string + <- valueNone + +func returnNone() -> ?string: + relayNone <- stringNone() + <- relayNone + +func streamFunctor(arr: []string) -> string: + stream: *[]string + stream <<- ["123"] + a = stream[arr.length - 1][0] + <- a + +func streamAssignment(arr: []string) -> string: + stream: *[]u32 + stream <<- [0] + a = stream[arr.length - 1][0] + b = arr[a] + <- b + +func streamIntFunctor(arr: []u32) -> string: + stream: *[]string + stream <<- ["123"] + a = stream[arr[0]][arr[0]] + <- a + +func streamJoin(arr: []string) -> string: + streamJ: *[]string + streamJ <<- ["111", "222"] + streamJ <<- ["333", "444"] + <- streamJ[arr.length][1] diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/streamArgs.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/streamArgs.aqua new file mode 100644 index 00000000..b1cd9b98 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/streamArgs.aqua @@ -0,0 +1,10 @@ +service TestService("test-service"): + get_records(key: string) -> []string + +func append_records(peer: string, srum: *[]string): + srum <- TestService.get_records(peer) + +func retrieve_records(peer: string) -> [][]string: + records: *[]string + append_records(peer, records) + <- records \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/streamCallback.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/streamCallback.aqua new file mode 100644 index 00000000..ff8e1dd5 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/streamCallback.aqua @@ -0,0 +1,7 @@ +module Ret declares * + +export someFunc + +func someFunc(cb: []string -> ()): + ifaces: *string + cb(ifaces) diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/streamCan.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/streamCan.aqua new file mode 100644 index 00000000..3ea38651 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/streamCan.aqua @@ -0,0 +1,46 @@ +export accumRes, bugLNG63, bugLNG63_2 + +func toOpt(s: string) -> ?string: + str: *string + str <<- s + <- str + +func accumRes() -> *?string: + res_accum: *?string + a <- toOpt("a") + res_accum <<- a + res_accum <- toOpt("b") + res_accum <<- nil + <- res_accum + +func returnCanStream() -> string: + status: *string + status <<- "ok" + stat = status! + <- stat + +service Op1("op"): + array_length(array: []string) -> u32 + +func bugLNG63() -> string: + res <- returnCanStream() + <- res + +func returnMultipleStreamResults() -> string, []string, []string, []string: + status: *string + status <<- "ok" + stat = status! + <- stat, status, [status!, stat], [status!, "no", status!] + +func bugLNG63_2() -> string, []string, []string: + res, res2, res3, res4 <- returnMultipleStreamResults() + <- res, res2, res4 + +func bugLNG63_3() -> string, u32, []u32: + status: *string + status <<- "ok" + stat = status! + num: *u32 + num <<- 2 + res = [Op1.array_length(status), num!] + <- status!, Op1.array_length(status), [Op1.array_length(status), 3, num!] diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/streamRestriction.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/streamRestriction.aqua new file mode 100644 index 00000000..279d72ef --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/streamRestriction.aqua @@ -0,0 +1,10 @@ +func streamFold(arr: []string) -> []string: + res: *string + for n <- arr: + res <<- n + <- res + +func streamRes(arr: []string) -> []string, []string: + res: *string + res2 <- streamFold(arr) + <- res, res2 \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/streamResults.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/streamResults.aqua new file mode 100644 index 00000000..087e40c7 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/streamResults.aqua @@ -0,0 +1,16 @@ +data DT: + field: string + +service DTGetter("get-dt"): + get_dt(s: string) -> DT + +func use_name1(name: string) -> string: + results <- DTGetter.get_dt(name) + <- results.field + +func use_name2(name: string) -> []string: + results: *string + results <- use_name1(name) + results <- use_name1(name) + results <- use_name1(name) + <- results \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/streamScopes.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/streamScopes.aqua new file mode 100644 index 00000000..a8f81bbe --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/streamScopes.aqua @@ -0,0 +1,83 @@ +aqua StreamExports + +export FailureSrv, streamIf, streamTry, streamFor, streamComplex + +service FailureSrv("failure"): + fail(msg: string) + +func streamIf() -> i8: + on HOST_PEER_ID: + if true: + stream: *i8 + stream <<- 1 + else: + stream: *i8 + stream <<- 2 + + if false: + stream: *i8 + stream <<- 3 + else: + stream: *i8 + stream <<- 4 + + stream: *i8 + stream <<- 5 + + <- stream! + +func streamTry() -> i8: + on HOST_PEER_ID: + try: + stream: *i8 + stream <<- 1 + FailureSrv.fail("try") + catch e: + stream: *i8 + stream <<- 2 + FailureSrv.fail("catch") + otherwise: + stream: *i8 + stream <<- 3 + + stream: *i8 + stream <<- 4 + + <- stream! + +func streamFor() -> i8: + on HOST_PEER_ID: + for i <- [1, 2, 3]: + stream: *i8 + stream <<- i + + stream: *i8 + stream <<- 4 + + <- stream! + +func streamComplex() -> i8: + on HOST_PEER_ID: + for i <- [1, 2, 3]: + try: + if i == 2: + stream: *i8 + stream <<- i + FailureSrv.fail("if") + else: + stream: *i8 + stream <<- i + + stream: *i8 + stream <<- i + 3 + catch e: + stream: *i8 + stream <<- i + 6 + + stream: *i8 + stream <<- i + 9 + + stream: *i8 + stream <<- 13 + + <- stream! diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/structuraltyping.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/structuraltyping.aqua new file mode 100644 index 00000000..0d7aa54e --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/structuraltyping.aqua @@ -0,0 +1,35 @@ +aqua Aaa + +import "@fluencelabs/aqua-lib/builtin.aqua" + +export structuralTypingTest + +data WideData: + s: string + n: u32 + +data ExactData: + s: string + +ability ExactAbility: + s: string + arr(s: string, s2: string, s3: string, s4: string) -> string + exact: ExactData + +ability WideAbility: + s: string + arr(s: string, s2: string, s3: string, s4: string) -> string + g: string + exact: WideData + +func ss(s1: string, s2: string, s3: string, s4: string) -> string: + <- Op.concat_strings(Op.concat_strings(Op.concat_strings(s1, s2), s3), s4) + +func main{ExactAbility}(someData: ExactData, secondData: ExactData) -> string: + <- ExactAbility.arr(someData.s, ExactAbility.exact.s, secondData.s, ExactAbility.s) + +func structuralTypingTest() -> string: + wd = WideData(s = "some_string", n = 32) + + WAbility = WideAbility(s = "ab_string", g = "", arr = ss, exact = wd) + <- main{WAbility}(wd, WAbility.exact) diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/subImportUsage.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/subImportUsage.aqua new file mode 100644 index 00000000..413ab00d --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/subImportUsage.aqua @@ -0,0 +1,11 @@ +import "imports_exports/subImport.aqua" + +service ConcatSubs("concat_subs"): + get_some(s: SomeString, sr: SomeResult) -> SomeResult + +func subImportUsage(s: SomeString) -> SomeResult: + sr1 <- SubService.sub(s) + sr2 <- subImport() + result <- ConcatSubs.get_some(sr1.one, sr2) + <- result + diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/topbottom.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/topbottom.aqua new file mode 100644 index 00000000..d0f2231a --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/topbottom.aqua @@ -0,0 +1,12 @@ +aqua TopBottom + +export S, topBottom + +-- this file should just compile + +service S(""): + top(t: ⊤) -> ⊤ + bottom(b: ⊥) -> ⊥ + +func topBottom(t: ⊤, b: ⊥) -> ⊤, ⊥: + <- S.top(t), S.bottom(b) \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/topology.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/topology.aqua new file mode 100644 index 00000000..90af3191 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/topology.aqua @@ -0,0 +1,53 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" + +service Testo("testo"): + getString: string -> string + +service LocalPrint("lp"): + print: string -> () + +service Opop("op"): + identity(s: string) -> string + + +func topologyTest(me: string, myRelay: string, friend: string, friendRelay: string) -> string: + on friend via friendRelay: + str2 <- Testo.getString("friends string via") + par LocalPrint.print("my string in par") + LocalPrint.print(str2) + <- "finish" + +func topologyBug205(node_id: string, n2: ?string) -> []string: + nodes: *PeerId + on node_id: + a <- Op.identity(n2) + nodes <<- a! + on node_id: + for n <- nodes par: + on n: + Peer.identify() + <- nodes + +service IOp("op"): + identity: string -> string + +func topologyBug394(peer: string, peer2: string, peer3: string) -> string: + -- execute computation on a Peer in the network + on peer: + comp <- IOp.identity(%init_peer_id%) + + -- send the result to target browser in the background + co on peer2 via peer3: + res <- IOp.identity(%init_peer_id%) + + -- send the result to the initiator + <- comp + +func topologyBug427(peers: []string) -> []string: + results: *string + for peer <- peers par: + on peer: + results <- Opop.identity("some string") + + join results[1] + <- results \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/tryCatch.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/tryCatch.aqua new file mode 100644 index 00000000..577ef622 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/tryCatch.aqua @@ -0,0 +1,25 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" + +service Unexisted("unex"): + getStr() -> string + +data LastError: + instruction: string + message: string + peer_id: string + +service OpA("op"): + identity(s: string) -> string + +func tryCatchTest(node_id: string) -> []string: + on node_id: + f: *string + try: + f <- Unexisted.getStr() + catch err: + c: *string + f <- OpA.identity(err.message) + -- check if the call takes place on the node + i <- Peer.identify() + f <- OpA.identity(i.external_addresses!) + <- f \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/tryOtherwise.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/tryOtherwise.aqua new file mode 100644 index 00000000..0624e55d --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/tryOtherwise.aqua @@ -0,0 +1,19 @@ +service Unexisted("unex"): + getStr() -> string + +data LastError: + instruction: string + msg: string + peer_id: string + +service OpE("op"): + identity(s: string) -> string + +func tryOtherwiseTest(node_id: string) -> string: + on node_id: + f: *string + try: + f <- Unexisted.getStr() + otherwise: + f <- OpE.identity("error") + <- f! \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/__test__/sources/via.aqua b/packages/core/aqua-wrapper/src/generate/__test__/sources/via.aqua new file mode 100644 index 00000000..a04f0b09 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/__test__/sources/via.aqua @@ -0,0 +1,17 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" + +func viaArr(node_id: string, viaAr: []string) -> Info: + on node_id via viaAr: + p <- Peer.identify() + <- p + + +func viaStream(node_id: string, viaStr: *string) -> Info: + on node_id via viaStr: + p <- Peer.identify() + <- p + +func viaOpt(relay: string, node_id: string, viaOpt: ?string) -> Info: + on node_id via viaOpt: + p <- Peer.identify() + <- p \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/function.ts b/packages/core/aqua-wrapper/src/generate/function.ts new file mode 100644 index 00000000..15d584c3 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/function.ts @@ -0,0 +1,46 @@ +/* + * Copyright 2023 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AquaFunction } from '@fluencelabs/aqua-api/aqua-api.js'; +import { capitalize, getFuncArgs, recursiveRenameLaquaProps } from '../utils.js'; +import { genTypeName } from '../common.js'; +import { CLIENT } from '../constants.js'; +import { TypeGenerator } from './interfaces.js'; + +export class FunctionGenerator { + constructor( + private typeGenerator: TypeGenerator + ) {} + + generate(functions: Record) { + return Object.values(functions).map(func => this.generateFunction(func)).join('\n\n'); + } + + private generateFunction(func: AquaFunction) { + const scriptConstName = func.funcDef.functionName + '_script'; + return `export const ${scriptConstName} = \` +${func.script}\` + +${this.typeGenerator.funcType(func)} +export function ${func.funcDef.functionName}(${this.typeGenerator.type('...args', 'any[]')}) { + return callFunction$$( + args, + ${JSON.stringify(recursiveRenameLaquaProps(func.funcDef), null, 4)}, + ${scriptConstName} + ) +}` + } +} \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/header.ts b/packages/core/aqua-wrapper/src/generate/header.ts new file mode 100644 index 00000000..fe03e276 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/header.ts @@ -0,0 +1,32 @@ +/* + * Copyright 2023 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default function(isJs: boolean, aquaVersion: string) { + return `/** + * + * This file is auto-generated. Do not edit manually: changes may be erased. + * Generated by Aqua compiler: https://github.com/fluencelabs/aqua/. + * If you find any bugs, please write an issue on GitHub: https://github.com/fluencelabs/aqua/issues + * Aqua version: ${aquaVersion} + * + */ +${!isJs ? 'import type { IFluenceClient as IFluenceClient$$, CallParams as CallParams$$ } from \'@fluencelabs/js-client\';' : ''} + +import { + v5_callFunction as callFunction$$, + v5_registerService as registerService$$, +} from '@fluencelabs/js-client';`; +} \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/index.ts b/packages/core/aqua-wrapper/src/generate/index.ts new file mode 100644 index 00000000..f9a0b41d --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/index.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2023 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import header from './header.js'; +import { getAquaApiVersion } from '../utils.js'; +import { FunctionGenerator } from './function.js'; +import { CompilationResult } from '@fluencelabs/aqua-api/aqua-api.js'; +import { JSTypeGenerator, TSTypeGenerator } from './interfaces.js'; +import { ServiceGenerator } from './service.js'; + +type OutputType = 'js' | 'ts'; + +export default function ({ services, functions }: CompilationResult, outputType: OutputType) { + const typeGenerator = outputType === 'js' ? new JSTypeGenerator() : new TSTypeGenerator(); + return `/* eslint-disable */ +// @ts-nocheck +${header(outputType === 'js', getAquaApiVersion())} + +// Services +${new ServiceGenerator(typeGenerator).generate(services)} + +// Functions +${new FunctionGenerator(typeGenerator).generate(functions)} + +/* eslint-enable */ +` +}; \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/interfaces.ts b/packages/core/aqua-wrapper/src/generate/interfaces.ts new file mode 100644 index 00000000..561465e2 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/interfaces.ts @@ -0,0 +1,125 @@ +/* + * Copyright 2023 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AquaFunction, CompilationResult } from '@fluencelabs/aqua-api/aqua-api.js'; +import { CLIENT } from '../constants.js'; +import { FunctionCallDef, ServiceDef } from '@fluencelabs/interfaces'; +import { genTypeName, typeToTs } from '../common.js'; +import { capitalize, getFuncArgs } from '../utils.js'; + +export interface TypeGenerator { + type(field: string, type: string): string; + generic(field: string, type: string): string; + bang(field: string): string; + funcType(funcDef: AquaFunction): string; + serviceType(srvName: string, srvDef: ServiceDef): string; +} + +export class TSTypeGenerator implements TypeGenerator { + bang(field: string): string { + return `${field}!`; + } + + generic(field: string, type: string): string { + return `${field}<${type}>`; + } + + type(field: string, type: string): string { + return `${field}: ${type}`; + } + + funcType({ funcDef }: AquaFunction): string { + const args = getFuncArgs(funcDef.arrow.domain).map(([name, type]) => { + const [typeDesc, t] = genTypeName(type, capitalize(funcDef.functionName) + 'Arg' + capitalize(name)); + return [typeDesc, `${name}: ${t}`] as const; + }); + args.push([undefined, `config?: {ttl?: number}`]); + + const argsDefs = args.map(([, def]) => " " + def); + const argsDesc = args.filter(([desc]) => desc !== undefined).map(([desc]) => desc); + + const functionOverloads = [ + argsDefs.join(',\n'), + [` peer: ${CLIENT}`, ...argsDefs].join(',\n') + ]; + + const [resTypeDesc, resType] = genTypeName(funcDef.arrow.codomain, capitalize(funcDef.functionName) + "Result"); + + return [ + argsDesc.join('\n'), + resTypeDesc || "", + functionOverloads.flatMap(fo => [ + `export function ${funcDef.functionName}(`, + fo, + `): Promise<${resType}>;`, + '' + ]).join('\n') + ].filter(s => s !== '').join('\n\n'); + } + + serviceType(srvName: string, srvDef: ServiceDef): string { + const members = srvDef.functions.tag === 'nil' ? [] : Object.entries(srvDef.functions.fields); + + const interfaceDefs = members + .map(([name, arrow]) => { + return ` ${name}: ${typeToTs(arrow)};`; + }) + .join('\n'); + + const interfaces = [`export interface ${srvName}Def {`, interfaceDefs, '}'].join('\n'); + + const peerDecl = `peer: ${CLIENT}`; + const serviceDecl = `service: ${srvName}Def`; + const serviceIdDecl = `serviceId: string`; + const registerServiceArgs = [ + [serviceDecl], + [serviceIdDecl, serviceDecl], + [peerDecl, serviceDecl], + [peerDecl, serviceIdDecl, serviceDecl] + ]; + + return [interfaces, ...registerServiceArgs.map(registerServiceArg => { + const args = registerServiceArg.join(', '); + return `export function register${srvName}(${args}): void;` + })].join('\n'); + } +} + +export class JSTypeGenerator implements TypeGenerator { + bang(field: string): string { + return field; + } + + generic(field: string, type: string): string { + return field; + } + + type(field: string, type: string): string { + return field; + } + + funcType(): string { + return ''; + } + + serviceType(): string { + return ''; + } +} + +export interface EntityGenerator { + generate(compilationResult: CompilationResult): string; +} \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/generate/service.ts b/packages/core/aqua-wrapper/src/generate/service.ts new file mode 100644 index 00000000..e52cf6b2 --- /dev/null +++ b/packages/core/aqua-wrapper/src/generate/service.ts @@ -0,0 +1,64 @@ +/* + * Copyright 2023 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ServiceDef } from '@fluencelabs/interfaces'; +import { recursiveRenameLaquaProps } from '../utils.js'; +import { TypeGenerator } from './interfaces.js'; + +interface DefaultServiceId { + s_Some__f_value?: string +} + +export class ServiceGenerator { + constructor( + private typeGenerator: TypeGenerator + ) {} + + generate(services: Record): string { + const generated = Object.entries(services).map(([srvName, srvDef]) => this.generateService(srvName, srvDef)).join('\n\n'); + + return generated + '\n'; + } + + private generateService(srvName: string, srvDef: ServiceDef) { + return [ + this.typeGenerator.serviceType(srvName, srvDef), + this.generateRegisterServiceOverload(srvName, srvDef) + ].join('\n'); + } + + private generateRegisterServiceOverload(srvName: string, srvDef: ServiceDef) { + return [ + `export function register${srvName}(${this.typeGenerator.type('...args', 'any[]')}) {`, + ' registerService$$(', + ' args,', + ` ${this.serviceToJson(srvDef)}`, + ' );', + '}' + ].join('\n'); + } + + private serviceToJson(service: ServiceDef): string { + return JSON.stringify({ + ...( + (service.defaultServiceId as DefaultServiceId)?.s_Some__f_value + ? { defaultServiceId: (service.defaultServiceId as DefaultServiceId).s_Some__f_value } + : {} + ), + functions: recursiveRenameLaquaProps(service.functions) + }, null, 4); + } +} \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/index.ts b/packages/core/aqua-wrapper/src/index.ts new file mode 100644 index 00000000..5c044510 --- /dev/null +++ b/packages/core/aqua-wrapper/src/index.ts @@ -0,0 +1,123 @@ +/* + * Copyright 2023 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-nocheck + +import { compileFromPath } from '@fluencelabs/aqua-api'; +import type { ArrowType, LabeledProductType, ProductType, ServiceDef } from '@fluencelabs/interfaces'; +import assert from 'assert'; +import { match, P } from 'ts-pattern'; +import { + ArrayType, + BottomType, + NilType, + NonArrowType, + OptionType, + ScalarType, + StructType, + TopType, + UnlabeledProductType +} from '@fluencelabs/interfaces'; +import * as fs from 'fs'; +import generate from './generate/index.js'; + +const res = await compileFromPath({ + filePath: './src/generate/__test__/sources/abilities.aqua', + imports: ['./node_modules'], + targetType: 'ts' +}); + +// const data = generate(res, 'ts'); + +fs.writeFileSync('./src/generate/__test__/snapshots/abilities.ts', res.generatedSources[0].tsSource); + + +process.exit(); + + +type GetTsTypeFromScalar = T['name'] extends 'u8' | 'u16' | 'u32' | 'u64' | 'i8' | 'i16' | 'i32' | 'i64' | 'f32' | 'f64' + ? number + : T['name'] extends 'bool' + ? boolean + : T['name'] extends 'string' + ? string + : never; + +type MapTuple = { [K in keyof T]: T[K] extends NonArrowType ? GetTsType : never } + +type GetTsType = T extends NilType + ? null + : T extends ArrayType + ? GetTsType[] + : T extends StructType + ? { [K in keyof T]: GetTsType } + : T extends OptionType + ? GetTsType | null + : T extends ScalarType + ? GetTsTypeFromScalar + : T extends TopType + ? unknown + : T extends BottomType + ? never + : T extends Exclude, NilType> + ? MapTuple + : T extends Exclude, NilType> + ? H extends NonArrowType + ? { [K in keyof T['fields']]: GetTsType } + : never + : never; + + + +const struct = { + "tag" : "unlabeledProduct", + "items" : [ + { + "tag" : "struct", + "name" : "RemoveResult", + "fields" : { + "error" : { + "tag" : "option", + "type" : { + "tag" : "scalar", + "name" : "string" + } + }, + "success" : { + "tag" : "scalar", + "name" : "bool" + } + } + } + ] as Array +} as const; + +type tt = GetTsType; + +const services = res.services as Record + +const service = services['Srv']; + +if (service.functions.tag === 'nil') { + throw new Error('nil'); +} + +const codomain = service.functions.fields['reload'].domain; +console.log(service.functions); +console.log(service); +// console.log(codomain); +// assert(codomain.tag === 'labeledProduct'); +console.log(JSON.stringify(codomain)); \ No newline at end of file diff --git a/packages/core/aqua-wrapper/src/utils.ts b/packages/core/aqua-wrapper/src/utils.ts new file mode 100644 index 00000000..0922e43d --- /dev/null +++ b/packages/core/aqua-wrapper/src/utils.ts @@ -0,0 +1,60 @@ +/* + * Copyright 2023 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import pkg from '../package.json' assert { type: 'json' }; +import { ArrowType, NonArrowType, ProductType } from '@fluencelabs/interfaces'; + +export function getAquaApiVersion() { + return pkg.dependencies['@fluencelabs/aqua-api']; +} + +export function getFuncArgs(domain: ProductType): [string, NonArrowType][] { + if (domain.tag === 'labeledProduct') { + return Object.entries(domain.fields).map(([label, type]) => [label, type]); + } else if (domain.tag === 'unlabeledProduct') { + return domain.items.map((type, index) => ['arg' + index, type]); + } else { + return []; + } +} + +export function recursiveRenameLaquaProps(obj: unknown): unknown { + if (typeof obj !== 'object' || obj === null) return obj; + + if (Array.isArray(obj)) { + return obj.map(item => recursiveRenameLaquaProps(item)); + } + + return Object.getOwnPropertyNames(obj).reduce((acc, prop) => { + let accessProp = prop; + if (prop.includes('Laqua_js')) { + // Last part of the property separated by "_" is a correct name + const refinedProperty = prop.split('_').pop()!; + if (refinedProperty in obj) { + accessProp = refinedProperty; + } + } + + return { + ...acc, + [accessProp]: recursiveRenameLaquaProps(obj[accessProp as keyof typeof obj]) + }; + }, {}); +} + +export function capitalize(str: string) { + return str.slice(0, 1).toUpperCase() + str.slice(1); +} \ No newline at end of file diff --git a/packages/core/aqua-wrapper/tsconfig.json b/packages/core/aqua-wrapper/tsconfig.json new file mode 100644 index 00000000..a4642cf0 --- /dev/null +++ b/packages/core/aqua-wrapper/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "esModuleInterop": true, + "resolveJsonModule": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"], +} diff --git a/packages/core/interfaces/src/compilerSupport/aquaTypeDefinitions.ts b/packages/core/interfaces/src/compilerSupport/aquaTypeDefinitions.ts index fa7822fc..ac59ed91 100644 --- a/packages/core/interfaces/src/compilerSupport/aquaTypeDefinitions.ts +++ b/packages/core/interfaces/src/compilerSupport/aquaTypeDefinitions.ts @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -type SomeNonArrowTypes = ScalarType | OptionType | ArrayType | StructType | TopType | BottomType; +type SimpleTypes = ScalarType | OptionType | ArrayType | StructType | TopType | BottomType | NilType; -export type NonArrowType = SomeNonArrowTypes | ProductType; +export type NonArrowType = SimpleTypes | ProductType; export type TopType = { /** @@ -108,35 +108,31 @@ export type StructType = { fields: { [key: string]: NonArrowType }; }; -export type LabeledProductType = - | { - /** - * Type descriptor. Used for pattern-matching - */ - tag: 'labeledProduct'; +export type LabeledProductType = { + /** + * Type descriptor. Used for pattern-matching + */ + tag: 'labeledProduct'; - /** - * Labelled product fields - */ - fields: { [key: string]: T }; - } - | NilType; + /** + * Labelled product fields + */ + fields: { [key: string]: T }; +}; -export type UnlabeledProductType = - | { - /** - * Type descriptor. Used for pattern-matching - */ - tag: 'unlabeledProduct'; +export type UnlabeledProductType = { + /** + * Type descriptor. Used for pattern-matching + */ + tag: 'unlabeledProduct'; - /** - * Items in unlabelled product - */ - items: Array; - } - | NilType; + /** + * Items in unlabelled product + */ + items: Array; +}; -export type ProductType = UnlabeledProductType | LabeledProductType; +export type ProductType = UnlabeledProductType | LabeledProductType | NilType; /** * ArrowType is a profunctor pointing its domain to codomain. @@ -233,12 +229,12 @@ export interface ServiceDef { /** * Default service id. If the service has no default id the value should be undefined */ - defaultServiceId?: string; + defaultServiceId?: {}; /** * List of functions which the service consists of */ - functions: LabeledProductType; + functions: LabeledProductType | NilType; } /** diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ef12523c..8ce61327 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -126,6 +126,40 @@ importers: specifier: 6.1.1 version: 6.1.1 + packages/core/aqua-wrapper: + dependencies: + '@fluencelabs/aqua-api': + specifier: 0.12.0 + version: 0.12.0 + '@fluencelabs/aqua-lib': + specifier: 0.7.3 + version: 0.7.3 + '@fluencelabs/interfaces': + specifier: workspace:* + version: link:../interfaces + '@fluencelabs/js-client': + specifier: '*' + version: link:../js-client + '@fluencelabs/registry': + specifier: 0.8.7 + version: 0.8.7 + '@fluencelabs/spell': + specifier: 0.5.20 + version: 0.5.20 + '@fluencelabs/trust-graph': + specifier: 0.4.7 + version: 0.4.7 + ts-pattern: + specifier: 5.0.5 + version: 5.0.5 + devDependencies: + typescript: + specifier: 5.1.6 + version: 5.1.6 + vitest: + specifier: 0.29.7 + version: 0.29.7 + packages/core/interfaces: devDependencies: '@fluencelabs/avm': @@ -3792,7 +3826,6 @@ packages: /@fluencelabs/aqua-api@0.12.0: resolution: {integrity: sha512-8D1SfmBDm0mmg3tuYrlpU8L6+bRlCSVRkhlU4CXMJFSMiVMrSF2WV+KFTP4GcOB3N4pNOONEwHMQo4xNWwzGhg==} - dev: true /@fluencelabs/aqua-api@0.9.3: resolution: {integrity: sha512-ieM2e7qMXgm9BPSSd2fxVbqLlYkR/a/aVTAQXO8gdx2rKKFqnTgFX4gpSOTxrrCMshi8OnXfd2OZi1hsJHTnKA==} @@ -3812,6 +3845,14 @@ packages: resolution: {integrity: sha512-ifjtCM93KO3LhzPkMxqmXhwLmrg/scjOiyTihEVg7ns5N+BVzaK1eWzdOdqGdl9ZVoah43pdlQUepEo7VdRmsw==} dev: true + /@fluencelabs/aqua-lib@0.7.0: + resolution: {integrity: sha512-mJEaxfAQb6ogVM4l4qw7INK6kvLA2Y161ErwL7IVeVSkKXIeYq/qio2p2au35LYvhBNsKc7XP2qc0uztCmxZzA==} + dev: false + + /@fluencelabs/aqua-lib@0.7.3: + resolution: {integrity: sha512-+JVbWmHeGB+X/BSqmk6/B0gwWJ4bEAxkepVTN8l0mVrJ5zRRmYaCKVplWy6Z3W012m3VVK3A1o3rm/fgfVrQkw==} + dev: false + /@fluencelabs/aqua@0.9.1-374(jest@27.5.1)(node-fetch@3.3.2)(typescript@4.7.2): resolution: {integrity: sha512-jF6oVE4h7bP/dQArKEfsy4UxbQbzACfVIBY/TFUL5D3np4ssjxrh15Y3gl1PwSWjlaPcDeFvAuStmcqfYQmLqQ==} hasBin: true @@ -4097,6 +4138,29 @@ packages: '@fluencelabs/trust-graph': 3.0.4 dev: true + /@fluencelabs/registry@0.8.7: + resolution: {integrity: sha512-43bmb1v4p5ORvaiLBrUAl+hRPo3luxxBVrJgqTvipJa2OEg2wCRA/Wo9s4M7Lchnv3NoYLOyNTzNyFopQRKILA==} + dependencies: + '@fluencelabs/aqua-lib': 0.7.0 + '@fluencelabs/trust-graph': 0.4.1 + dev: false + + /@fluencelabs/spell@0.5.20: + resolution: {integrity: sha512-QFbknWwALLUWMzpWkFt34McuwTz9xwQuiPP1zXqhPqVZ1J6g8F3gwHHtzgHFW5Z7WrRmwsL+IQtFJy8YZubhDw==} + dev: false + + /@fluencelabs/trust-graph@0.4.1: + resolution: {integrity: sha512-V/6ts4q/Y0uKMS6orVpPyxfdd99YFMkm9wN9U2IFtlBUWNsQZG369FK9qEizwsSRCqTchMHYs8Vh4wgZ2uRfuQ==} + dependencies: + '@fluencelabs/aqua-lib': 0.7.3 + dev: false + + /@fluencelabs/trust-graph@0.4.7: + resolution: {integrity: sha512-e4TxWimUh9GBWjqSO8WGsSqjZfyIs6f39/8Pzfo6PCcNoSf8FPaaO817Pw4FmAXYEKR1IalIUX3CDdym3NlHWw==} + dependencies: + '@fluencelabs/aqua-lib': 0.7.3 + dev: false + /@fluencelabs/trust-graph@3.0.4: resolution: {integrity: sha512-4CWe/dBuZwrj5iU6mTrLz5JCSy5v1fw7dYjD65Pz05xWAbLH2jw72YIJfbMX0utzb1qiM8CooXv1XKPgutCIHQ==} dependencies: @@ -19892,6 +19956,10 @@ packages: /ts-pattern@3.3.3: resolution: {integrity: sha512-Z5EFi6g6wyX3uDFHqxF5W5c5h663oZg9O6aOiAT7fqNu0HPSfCxtHzrQ7SblTy738Mrg2Ezorky8H5aUOm8Pvg==} + /ts-pattern@5.0.5: + resolution: {integrity: sha512-tL0w8U/pgaacOmkb9fRlYzWEUDCfVjjv9dD4wHTgZ61MjhuMt46VNWTG747NqW6vRzoWIKABVhFSOJ82FvXrfA==} + dev: false + /tsconfck@2.1.1(typescript@4.7.2): resolution: {integrity: sha512-ZPCkJBKASZBmBUNqGHmRhdhM8pJYDdOXp4nRgj/O0JwUwsMq50lCDRQP/M5GBNAA0elPrq4gAeu4dkaVCuKWww==} engines: {node: ^14.13.1 || ^16 || >=18} @@ -20566,7 +20634,7 @@ packages: '@vitest/runner': 0.29.7 '@vitest/spy': 0.29.7 '@vitest/utils': 0.29.7 - acorn: 8.9.0 + acorn: 8.10.0 acorn-walk: 8.2.0 cac: 6.7.14 chai: 4.3.7