summaryrefslogtreecommitdiffhomepage
path: root/tests/02_runtime/00_scoping
blob: 5fadf43d5264477ca68e61332ae609b929465459 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
Utpl implements function scoping, make sure that let variables are
invisible outside of the function scope.

-- Expect stdout --
a_global=true
a_local=true

b_global=true
b_local=false

c_global=true
c_local=false


When seting a nonlocal variable, it is set in the nearest parent
scope containing the variable or in the root scope if the variable
was not found.

x=2
y=
z=1


Variables implicitly declared by for-in or counting for loops follow the same
scoping rules.

inner2 f_a=3
inner2 f_b=
inner2 f_c=3
inner2 f_d=
inner2 f_e=3

inner f_a=3
inner f_b=
inner f_c=3
inner f_d=
inner f_e=3

outer f_a=3
outer f_b=
outer f_c=
outer f_d=
outer f_e=3
-- End --

-- Testcase --
{%
	a_global = true;
	let a_local = true;

	function test() {
		b_global = true;
		let b_local = true;

		function test2() {
			c_global = true;
			let c_local = true;
		}

		test2();
	}

	test();
-%}

a_global={{ !!a_global }}
a_local={{ !!a_local }}

b_global={{ !!b_global }}
b_local={{ !!b_local }}

c_global={{ !!c_global }}
c_local={{ !!c_local }}


When seting a nonlocal variable, it is set in the nearest parent
scope containing the variable or in the root scope if the variable
was not found.

{%
	x = 1;

	function scope1() {
		x = 2;
		let y;

		function scope2() {
			// this does not set "y" in the root scope but overwrites the
			// variable declared in the "scope1" function scope.
			y = 2;

			// this sets "z" in the root scope because it was not declared
			// anywhere yet
			z = 1;
		}

		scope2();
	}

	scope1();
-%}

x={{ x }}
y={{ y }}
z={{ z }}


Variables implicitly declared by for-in or counting for loops follow the same
scoping rules.

{%
	function scope3() {
		// f_a is not declared local and be set in the root scope
		for (f_a = 1; f_a < 3; f_a++)
			;

		for (let f_b = 1; f_b < 3; f_b++)
			;

		let f_c;

		function scope4() {
			// f_c is not declared local but declared in the parent scope, it
			// will be set there
			for (f_c in [1, 2, 3])
				;

			for (let f_d in [1, 2, 3])
				;

			// f_e is not declared, it will be set in the root scope
			for (f_e in [1, 2, 3])
				;

			print("inner2 f_a=", f_a, "\n");
			print("inner2 f_b=", f_b, "\n");
			print("inner2 f_c=", f_c, "\n");
			print("inner2 f_d=", f_d, "\n");
			print("inner2 f_e=", f_e, "\n");
			print("\n");
		}

		scope4();

		print("inner f_a=", f_a, "\n");
		print("inner f_b=", f_b, "\n");
		print("inner f_c=", f_c, "\n");
		print("inner f_d=", f_d, "\n");
		print("inner f_e=", f_e, "\n");
		print("\n");
	}

	scope3();

	print("outer f_a=", f_a, "\n");
	print("outer f_b=", f_b, "\n");
	print("outer f_c=", f_c, "\n");
	print("outer f_d=", f_d, "\n");
	print("outer f_e=", f_e, "\n");
%}
-- End --