Skip to content

Commit 3540424

Browse files
committed
[Tolk] AST-based semantic analysis, get rid of Expr
This is a huge refactoring focusing on untangling compiler internals (previously forked from FunC). The goal is to convert AST directly to Op (a kind of IR representation), doing all code analysis at AST level. Noteable changes: - AST-based semantic kernel includes: registering global symbols, scope handling and resolving local/global identifiers, lvalue/rvalue calc and check, implicit return detection, mutability analysis, pure/impure validity checks, simple constant folding - values of `const` variables are calculated NOT based on CodeBlob, but via a newly-introduced AST-based constant evaluator - AST vertices are now inherited from expression/statement/other; expression vertices have common properties (TypeExpr, lvalue/rvalue) - symbol table is rewritten completely, SymDef/SymVal no longer exist, lexer now doesn't need to register identifiers - AST vertices have references to symbols, filled at different stages of pipeline - the remaining "FunC legacy part" is almost unchanged besides Expr which was fully dropped; AST is converted to Ops (IR) directly
1 parent ea0dc16 commit 3540424

Some content is hidden

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

71 files changed

+4187
-2977
lines changed

tolk-tester/tests/allow_post_modification.tolk

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,85 +2,112 @@ fun unsafe_tuple<X>(x: X): tuple
22
asm "NOP";
33

44
fun inc(x: int, y: int): (int, int) {
5-
return (x + y, y * 10);
5+
return (x + y, y * 10);
66
}
77
fun `~inc`(mutate self: int, y: int): int {
8-
val (newX, newY) = inc(self, y);
9-
self = newX;
10-
return newY;
8+
val (newX, newY) = inc(self, y);
9+
self = newX;
10+
return newY;
1111
}
1212

13+
fun eq<X>(v: X): X { return v; }
14+
fun eq2(v: (int, int)) { return v; }
15+
fun mul2(mutate dest: int, v: int): int { dest = v*2; return dest; }
16+
fun multens(mutate self: (int, int), v: (int, int)): (int, int) { var (f, s) = self; var (m1, m2) = v; self = (f*m1, s*m2); return self; }
17+
1318
@method_id(11)
1419
fun test_return(x: int): (int, int, int, int, int, int, int) {
15-
return (x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x);
20+
return (x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x);
1621
}
1722

1823
@method_id(12)
1924
fun test_assign(x: int): (int, int, int, int, int, int, int) {
20-
var (x1: int, x2: int, x3: int, x4: int, x5: int, x6: int, x7: int) = (x, x.`~inc`(x / 20), x, x=x*2, x, x+=1, x);
21-
return (x1, x2, x3, x4, x5, x6, x7);
25+
var (x1: int, x2: int, x3: int, x4: int, x5: int, x6: int, x7: int) = (x, x.`~inc`(x / 20), x, x=x*2, x, x+=1, x);
26+
return (x1, x2, x3, x4, x5, x6, x7);
2227
}
2328

2429
@method_id(13)
2530
fun test_tuple(x: int): tuple {
26-
var t: tuple = unsafe_tuple([x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x]);
27-
return t;
31+
var t: tuple = unsafe_tuple([x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x]);
32+
return t;
2833
}
2934

3035
@method_id(14)
3136
fun test_tuple_assign(x: int): (int, int, int, int, int, int, int) {
32-
var [x1: int, x2: int, x3: int, x4: int, x5: int, x6: int, x7: int] = [x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x];
33-
return (x1, x2, x3, x4, x5, x6, x7);
37+
var [x1: int, x2: int, x3: int, x4: int, x5: int, x6: int, x7: int] = [x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x];
38+
return (x1, x2, x3, x4, x5, x6, x7);
3439
}
3540

3641
fun foo1(x1: int, x2: int, x3: int, x4: int, x5: int, x6: int, x7: int): (int, int, int, int, int, int, int) {
37-
return (x1, x2, x3, x4, x5, x6, x7);
42+
return (x1, x2, x3, x4, x5, x6, x7);
3843
}
3944

4045
@method_id(15)
4146
fun test_call_1(x: int): (int, int, int, int, int, int, int) {
42-
return foo1(x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x);
47+
return foo1(x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x);
4348
}
4449

4550
fun foo2(x1: int, x2: int, x3456: (int, int, int, int), x7: int): (int, int, int, int, int, int, int) {
46-
var (x3: int, x4: int, x5: int, x6: int) = x3456;
47-
return (x1, x2, x3, x4, x5, x6, x7);
51+
var (x3: int, x4: int, x5: int, x6: int) = x3456;
52+
return (x1, x2, x3, x4, x5, x6, x7);
4853
}
4954

5055
@method_id(16)
5156
fun test_call_2(x: int): (int, int, int, int, int, int, int) {
52-
return foo2(x, x.`~inc`(x / 20), (x, x = x * 2, x, x += 1), x);
57+
return foo2(x, x.`~inc`(x / 20), (x, x = x * 2, x, x += 1), x);
5358
}
5459

5560
fun asm_func(x1: int, x2: int, x3: int, x4: int, x5: int, x6: int, x7: int): (int, int, int, int, int, int, int)
56-
asm
57-
(x4 x5 x6 x7 x1 x2 x3->0 1 2 3 4 5 6) "NOP";
61+
asm (x4 x5 x6 x7 x1 x2 x3->0 1 2 3 4 5 6) "NOP";
5862

5963
@method_id(17)
6064
fun test_call_asm_old(x: int): (int, int, int, int, int, int, int) {
61-
return asm_func(x, x += 1, x, x, x.`~inc`(x / 20), x, x = x * 2);
65+
return asm_func(x, x += 1, x, x, x.`~inc`(x / 20), x, x = x * 2);
6266
}
6367

6468
@method_id(18)
6569
fun test_call_asm_new(x: int): (int, int, int, int, int, int, int) {
66-
return asm_func(x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x);
70+
return asm_func(x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x);
6771
}
6872

6973
global xx: int;
7074
@method_id(19)
71-
fun test_global(x: int): (int, int, int, int, int, int, int) {
72-
xx = x;
73-
return (xx, xx.`~inc`(xx / 20), xx, xx = xx * 2, xx, xx += 1, xx);
75+
fun test_global(x: int) {
76+
xx = x;
77+
return (x, xx, xx.`~inc`(xx / 20), eq(xx += (x *= 0)), xx = xx * 2, xx, xx += 1, xx, x);
7478
}
7579

7680
@method_id(20)
7781
fun test_if_else(x: int): (int, int, int, int, int) {
78-
if (x > 10) {
79-
return (x.`~inc`(8), x + 1, x = 1, x <<= 3, x);
80-
} else {
81-
xx = 9;
82-
return (x, x.`~inc`(-4), x.`~inc`(-1), x >= 1, x = x + xx);
83-
}
82+
if (x > 10) {
83+
return (x.`~inc`(8), x + 1, x = 1, x <<= 3, x);
84+
} else {
85+
xx = 9;
86+
return (x, x.`~inc`(-4), x.`~inc`(-1), x >= 1, x = x + xx);
87+
}
88+
}
89+
90+
@method_id(21)
91+
fun test_assign_with_inner(x: int) {
92+
return (x, x += 10, [(x, x += 20, eq(x -= 50), x)], eq2((x, x *= eq(x /= 2))));
93+
}
94+
95+
@method_id(22)
96+
fun test_assign_with_mutate(x: int) {
97+
return (x, mul2(mutate x, x += 5), x.`~inc`(mul2(mutate x, x)), x);
98+
}
99+
100+
@method_id(23)
101+
fun test_assign_tensor(x: (int, int)) {
102+
var fs = (0, 0);
103+
return (x, x = (20, 30), fs = x.multens((1, 2)), fs.multens(multens(mutate x, (-1, -1))), x, fs);
104+
}
105+
106+
global fs: (int, int);
107+
@method_id(24)
108+
fun test_assign_tensor_global(x: (int, int)) {
109+
fs = (0, 0);
110+
return (x, x = (20, 30), fs = x.multens((1, 2)), fs.multens(multens(mutate x, (-1, -1))), x, fs);
84111
}
85112

86113
fun main() {
@@ -96,9 +123,13 @@ fun main() {
96123
@testcase | 16 | 100 | 100 50 105 210 210 211 211
97124
@testcase | 17 | 100 | 101 50 106 212 100 101 101
98125
@testcase | 18 | 100 | 210 210 211 211 100 50 105
99-
@testcase | 19 | 100 | 100 50 105 210 210 211 211
126+
@testcase | 19 | 100 | 100 100 50 105 210 210 211 211 0
100127
@testcase | 20 | 80 | 80 89 1 8 8
101128
@testcase | 20 | 9 | 9 -40 -10 -1 13
129+
@testcase | 21 | 100 | 100 110 [ 110 130 80 80 ] 80 3200
130+
@testcase | 22 | 100 | 100 210 4200 630
131+
@testcase | 23 | 1 1 | 1 1 20 30 20 60 -400 -3600 -20 -60 -400 -3600
132+
@testcase | 24 | 1 1 | 1 1 20 30 20 60 -400 -3600 -20 -60 -400 -3600
102133

103134
@fif_codegen
104135
"""
@@ -107,5 +138,5 @@ fun main() {
107138
inc CALLDICT // self newY
108139
}>
109140
"""
110-
@code_hash 97139400653362069936987769894397430077752335662822462908581556703209313861576
141+
@code_hash 33262590582878205026101577472505372101182291690814957175155528952950621243206
111142
*/

tolk-tester/tests/cells-slices.tolk

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -216,15 +216,15 @@ Note, that since 'compute-asm-ltr' became on be default, chaining methods codege
216216
"""
217217
test6 PROC:<{
218218
//
219-
NEWC // _1
220-
1 PUSHINT // _1 _2=1
221-
SWAP // _2=1 _1
219+
NEWC // _0
220+
1 PUSHINT // _0 _1=1
221+
SWAP // _1=1 _0
222222
32 STU // _0
223-
2 PUSHINT // _0 _6=2
224-
SWAP // _6=2 _0
223+
2 PUSHINT // _0 _5=2
224+
SWAP // _5=2 _0
225225
32 STU // _0
226-
3 PUSHINT // _0 _10=3
227-
SWAP // _10=3 _0
226+
3 PUSHINT // _0 _9=3
227+
SWAP // _9=3 _0
228228
32 STU // _0
229229
}>
230230
"""

tolk-tester/tests/codegen_check_demo.tolk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Below, I just give examples of @fif_codegen tag:
3535
"""
3636
main PROC:<{
3737
// s
38-
17 PUSHINT // s _3=17
38+
17 PUSHINT // s _1=17
3939
OVER // s z=17 t
4040
WHILE:<{
4141
...

tolk-tester/tests/invalid-call-1.tolk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ fun main() {
55
/**
66
@compilation_should_fail
77
The message is weird now, but later I'll rework error messages anyway.
8-
@stderr cannot apply expression of type int to an expression of type (): cannot unify type () -> ??3 with int
8+
@stderr cannot apply expression of type int to an expression of type (): cannot unify type () -> ??2 with int
99
*/

tolk-tester/tests/invalid-call-5.tolk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ fun main() {
88

99
/**
1010
@compilation_should_fail
11-
@stderr rvalue expected
11+
@stderr `_` can't be used as a value; it's a placeholder for a left side of assignment
1212
@stderr inc(_)
1313
*/
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fun main() {
2+
return 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;
3+
}
4+
5+
/**
6+
@compilation_should_fail
7+
@stderr invalid integer constant
8+
*/

tolk-tester/tests/invalid-mutate-1.tolk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ fun cantAssignToVal() {
77

88
/**
99
@compilation_should_fail
10-
@stderr modifying an immutable variable `x`
10+
@stderr modifying immutable variable `x`
1111
*/

tolk-tester/tests/invalid-mutate-11.tolk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ fun load32(self: slice): int {
44

55
/**
66
@compilation_should_fail
7-
@stderr modifying `self` (call a mutating method), which is immutable by default
7+
@stderr modifying `self`, which is immutable by default
88
*/

tolk-tester/tests/invalid-mutate-2.tolk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ fun cantAssignToVal() {
66

77
/**
88
@compilation_should_fail
9-
@stderr modifying an immutable variable `x`
9+
@stderr modifying immutable variable `x`
1010
*/

tolk-tester/tests/invalid-mutate-3.tolk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ fun cantAssignToConst() {
77

88
/**
99
@compilation_should_fail
10-
@stderr modifying an immutable variable `op_increase`
10+
@stderr modifying immutable constant
1111
*/

0 commit comments

Comments
 (0)