Skip to content

Commit

Permalink
- can destruct implicit enum variants inside tuples
Browse files Browse the repository at this point in the history
- is_valid_data() ir function doesn't assume single field data for enums
  • Loading branch information
christianschmitz committed Sep 5, 2024
1 parent 867ecb8 commit 5d89f8c
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 9 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@helios-lang/compiler",
"version": "0.17.0-68",
"version": "0.17.0-69",
"description": "Helios is a Domain Specific Language that compiles to Plutus-Core (i.e. Cardano on-chain validator scripts). Helios is a non-Haskell alternative to Plutus. With this library you can compile Helios scripts and build Cardano transactions, all you need to build 100% client-side dApps for Cardano.",
"main": "src/index.js",
"types": "types/index.d.ts",
Expand Down
19 changes: 17 additions & 2 deletions src/expressions/DestructExpr.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,15 @@ export class DestructExpr {
if (this.#isTuple) {
const upstreamItemTypes = upstreamType
? getTupleItemTypes(upstreamType)
: null
: None
const downStreamItemTypes = downstreamType
? getTupleItemTypes(downstreamType)
: None
const nestedTypes = this.destructExprs.map((e, i) => {
const de = e.evalType(
scope,
upstreamItemTypes ? upstreamItemTypes[i] : null
upstreamItemTypes ? upstreamItemTypes[i] : None,
downStreamItemTypes ? downStreamItemTypes[i] : None
)

if (!de) {
Expand Down Expand Up @@ -247,6 +251,16 @@ export class DestructExpr {
)
this.typeExpr.cache = variant
return variant
} else if (
// could be the same implicit enum variant
this.typeExpr instanceof RefExpr &&
upstreamType &&
!downstreamType &&
upstreamType.asEnumMemberType &&
upstreamType.asEnumMemberType.name == this.typeExpr.name.value
) {
this.typeExpr.cache = upstreamType
return upstreamType
} else {
const t = downstreamType ?? this.typeExpr.evalAsType(scope)

Expand All @@ -257,6 +271,7 @@ export class DestructExpr {
t.asEnumMemberType &&
castEnumVariantToParent
) {
// this is important when used as the type against which the rhs is checked
return t.asEnumMemberType.parentType
} else {
return t
Expand Down
2 changes: 1 addition & 1 deletion src/program/version.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const VERSION = "0.17.0-68"
export const VERSION = "0.17.0-69"
5 changes: 3 additions & 2 deletions src/statements/DataDefinition.js
Original file line number Diff line number Diff line change
Expand Up @@ -514,9 +514,10 @@ export class DataDefinition {
}

/**
* @param {boolean} argIsConstrFields - true in case of sndPair(unConstrData(...)) call for enum variant
* @returns {SourceMappedString}
*/
toIR_is_valid_data() {
toIR_is_valid_data(argIsConstrFields = false) {
if (this.hasTags()) {
const fields = this.#fields

Expand Down Expand Up @@ -549,7 +550,7 @@ export class DataDefinition {
return $`(data) -> {
${ir}
}`
} else if (this.nFields == 1) {
} else if (this.nFields == 1 && !argIsConstrFields) {
return $`${this.#fields[0].type.path}__is_valid_data`
} else {
const reversedFields = this.#fields.slice().reverse()
Expand Down
2 changes: 1 addition & 1 deletion src/statements/EnumMember.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ export class EnumMember {
__core__ifThenElse(
__core__equalsInteger(__core__fstPair(pair), ${this.constrIndex}),
() -> {
${this.#dataDef.toIR_is_valid_data()}(__core__listData(__core__sndPair(pair)))
${this.#dataDef.toIR_is_valid_data(true)}(__core__listData(__core__sndPair(pair)))
},
() -> {
false
Expand Down
144 changes: 144 additions & 0 deletions test/assign.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,150 @@ describe("Assign", () => {
inputs: [int(1)],
output: int(1)
},
{
description: "can destruct enum nested in tuple",
main: `testing destruct_custom_enum_variant_nested
enum MyEnum {
A{
a: Int
}
B
}
func main(a: Int) -> Int {
enum: MyEnum = MyEnum::A{a};
(_, A{b}) = (a, enum);
b
}`,
inputs: [int(1)],
output: int(1)
},
{
description: "can destruct enum nested in tuple (fully namespaced)",
main: `testing destruct_custom_enum_variant_nested
enum MyEnum {
A{
a: Int
}
B
}
func main(a: Int) -> Int {
enum: MyEnum = MyEnum::A{a};
(_, MyEnum::A{b}) = (a, enum);
b
}`,
inputs: [int(1)],
output: int(1)
},
{
description:
"can destruct enum nested variant nested in tuple (implicit variants)",
main: `testing destruct_custom_enum_variant_nested_in_tuple
enum Inner {
A{a: Int}
B
}
enum Outer {
C{
i: Inner
}
D
}
func main(a: Int) -> Int {
inner: Inner = Inner::A{a};
outer: Outer = Outer::C{inner};
(_, C{A{b}}) = (a, outer);
b
}`,
inputs: [int(1)],
output: int(1)
},
{
description:
"can destruct enum nested variant nested in tuple (partially namespaced)",
main: `testing destruct_custom_enum_variant_nested_in_tuple
enum Inner {
A{a: Int}
B
}
enum Outer {
C{
i: Inner
}
D
}
func main(a: Int) -> Int {
inner: Inner = Inner::A{a};
outer: Outer = Outer::C{inner};
(_, C{Inner::A{b}}) = (a, outer);
b
}`,
inputs: [int(1)],
output: int(1)
},
{
description:
"can destruct enum nested variant nested in tuple (partially namespaced 2)",
main: `testing destruct_custom_enum_variant_nested_in_tuple
enum Inner {
A{a: Int}
B
}
enum Outer {
C{
i: Inner
}
D
}
func main(a: Int) -> Int {
inner: Inner = Inner::A{a};
outer: Outer = Outer::C{inner};
(_, Outer::C{A{b}}) = (a, outer);
b
}`,
inputs: [int(1)],
output: int(1)
},
{
description:
"can destruct enum nested variant nested in tuple (fully namespaced)",
main: `testing destruct_custom_enum_variant_nested_in_tuple
enum Inner {
A{a: Int}
B
}
enum Outer {
C{
i: Inner
}
D
}
func main(a: Int) -> Int {
inner: Inner = Inner::A{a};
outer: Outer = Outer::C{inner};
(_, Outer::C{Inner::A{b}}) = (a, outer);
b
}`,
inputs: [int(1)],
output: int(1)
},
{
description: "infers types when assigning to tuple",
main: `testing destruct_tuple_infered_types
Expand Down

0 comments on commit 5d89f8c

Please sign in to comment.