Skip to content

Commit 9e6c1fc

Browse files
committed
[Tolk] Implement structures that work like tensors on a stack
Support declaring structures with arbitrary fields and creating objects very similar to TS syntax. Structs are actually tensors on a stack, and accessing their fields behave exactly as accessing tensor's elements by index. As a consequence, recurring struct fields doesn't work; it will lead to infinity size. All features of type system (nullables, unions) seamlessly work with structures. A struct with 1 field has no extra overhead, it's just a field on a stack.
1 parent ebde55e commit 9e6c1fc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1719
-61
lines changed

tolk-tester/tests/allow-post-modification.tolk

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@ fun test_assign_tensor_global(x: (int, int)) {
112112
return (x, x = (20, 30), fs = x.multens((1, 2)), fs.multens(multens(mutate x, (-1, -1))), x, fs);
113113
}
114114

115+
struct Point1D {
116+
c: int;
117+
}
118+
119+
@method_id(25)
120+
fun test_with_single_slot_struct(x: Point1D) {
121+
var result = (x, x.c += 10, [x, x.c += 20, eq(x.c -= 50), x.c], eq2((x.c, x.c *= eq(x.c /= 2))));
122+
return result;
123+
}
124+
115125
fun main() {
116126
}
117127

@@ -132,6 +142,7 @@ fun main() {
132142
@testcase | 22 | 100 | 100 210 4200 630
133143
@testcase | 23 | 1 1 | 1 1 20 30 20 60 -400 -3600 -20 -60 -400 -3600
134144
@testcase | 24 | 1 1 | 1 1 20 30 20 60 -400 -3600 -20 -60 -400 -3600
145+
@testcase | 25 | 100 | 100 110 [ 110 130 80 80 ] 80 3200
135146

136147
@fif_codegen
137148
"""
@@ -147,5 +158,5 @@ fun main() {
147158
// x.0 x.1
148159
"""
149160

150-
@code_hash 61280273714870328160131559159866470128402169974050439159015534193532598351244
161+
@code_hash 6737917279814799680932710799951154408447028229503449454536845752635763933556
151162
*/
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
struct B { a: A }
2+
struct A { b: BAlias }
3+
4+
type BAlias = B;
5+
6+
/**
7+
@compilation_should_fail
8+
@stderr struct `B` size is infinity due to recursive fields
9+
@stderr struct B {
10+
*/
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
struct A {
2+
value: int;
3+
}
4+
5+
struct B {
6+
data: slice;
7+
}
8+
9+
fun main() {
10+
var r1: A | B = A { value: 10 };
11+
var r2: A | null = { value: 10 };
12+
var r3: A | int | builder = { value: 10 };
13+
14+
var r4: A | B = { value: 20 };
15+
}
16+
17+
/**
18+
@compilation_should_fail
19+
@stderr can not detect struct name
20+
@stderr use either `var v: StructName = { ... }` or `var v = StructName { ... }`
21+
@stderr { value: 20 }
22+
*/
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fun increment(mutate x: int) {
2+
x += 1;
3+
}
4+
5+
fun checkCantMutateFieldOfImmutableTensor() {
6+
val t = (0, 1);
7+
increment(mutate ((t!)).0);
8+
}
9+
10+
/**
11+
@compilation_should_fail
12+
@stderr modifying immutable variable `t`
13+
*/
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
struct User {
2+
id: int;
3+
}
4+
5+
fun cantInstantiateNonGenericStruct() {
6+
var u = User<int> { id: 3 };
7+
}
8+
9+
/**
10+
@compilation_should_fail
11+
@stderr generic T not expected here
12+
@stderr User<int>
13+
*/
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
struct User {
2+
id: int;
3+
}
4+
5+
type UserAlias = User;
6+
7+
fun cantInstantiateNonGenericStruct() {
8+
var u = UserAlias<int> { id: 3 };
9+
}
10+
11+
/**
12+
@compilation_should_fail
13+
@stderr generic T not expected here
14+
@stderr UserAlias<int>
15+
*/
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
struct User {
2+
id: int;
3+
name: slice;
4+
}
5+
6+
fun main() {
7+
var u: User = { id: 1 };
8+
}
9+
10+
/**
11+
@compilation_should_fail
12+
@stderr field `name` missed in initialization of struct `User`
13+
*/
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
struct NumberFields {
2+
`-1`: int;
3+
`0`: int;
4+
`100500`: int;
5+
}
6+
7+
fun main() {
8+
var b: NumberFields = { `-1`: -1, `0`: 0, `100500`: 100500 };
9+
b.0; // ok
10+
b.`0`; // ok
11+
b.`-1`; // ok
12+
b.`100500`; // ok
13+
b.100500; // ok
14+
b.123;
15+
}
16+
17+
/**
18+
@compilation_should_fail
19+
@stderr field `123` doesn't exist in type `NumberFields`
20+
@stderr b.123
21+
*/
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
struct value { id: int; }
2+
3+
fun main() {
4+
var value = 100;
5+
var obj = value { id: 100 };
6+
}
7+
8+
/**
9+
@compilation_should_fail
10+
@stderr `value` does not name a struct
11+
@stderr obj = value
12+
*/
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
fun checkCantMutateFieldOfImmutableTuple() {
2+
val ks = null as [int, [int, [int]]]?;
3+
ks!.1.1.0 = 10;
4+
}
5+
6+
/**
7+
@compilation_should_fail
8+
@stderr modifying immutable variable `ks`
9+
*/

0 commit comments

Comments
 (0)