Fork of daniellemaywood.uk/gleam — Wasm codegen work
9.6 kB
627 lines
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2021 The Gleam contributors
3
4use crate::assert_js;
5
6#[test]
7fn referencing_pattern_var() {
8 assert_js!(
9 r#"pub fn main(xs) {
10 case xs {
11 #(x) if x -> 1
12 _ -> 0
13 }
14}
15"#,
16 );
17}
18
19#[test]
20fn rebound_var() {
21 assert_js!(
22 r#"pub fn main() {
23 let x = False
24 let x = True
25 case x {
26 _ if x -> 1
27 _ -> 0
28 }
29}
30"#,
31 );
32}
33
34#[test]
35fn bitarray_with_var() {
36 assert_js!(
37 r#"pub fn main() {
38 case 5 {
39 z if <<z>> == <<z>> -> Nil
40 _ -> Nil
41 }
42}
43"#,
44 )
45}
46
47// https://github.com/gleam-lang/gleam/issues/3004
48#[test]
49fn keyword_var() {
50 assert_js!(
51 r#"
52pub const function = 5
53pub const do = 10
54pub fn main() {
55 let class = 5
56 let while = 10
57 let var = 7
58 case var {
59 _ if class == while -> True
60 _ if [class] == [5] -> True
61 function if #(function) == #(5) -> False
62 _ if do == function -> True
63 while if while > 5 -> False
64 class -> False
65 }
66}
67"#,
68 );
69}
70
71#[test]
72fn operator_wrapping_right() {
73 assert_js!(
74 r#"pub fn main(xs, y: Bool, z: Bool) {
75 case xs {
76 #(x) if x == { y == z } -> 1
77 _ -> 0
78 }
79}
80"#,
81 );
82}
83
84#[test]
85fn operator_wrapping_left() {
86 assert_js!(
87 r#"pub fn main(xs, y: Bool, z: Bool) {
88 case xs {
89 #(x) if { x == y } == z -> 1
90 _ -> 0
91 }
92}
93"#,
94 );
95}
96
97#[test]
98fn eq_scalar() {
99 assert_js!(
100 r#"pub fn main(xs, y: Int) {
101 case xs {
102 #(x) if x == y -> 1
103 _ -> 0
104 }
105}
106"#,
107 );
108}
109
110#[test]
111fn not_eq_scalar() {
112 assert_js!(
113 r#"pub fn main(xs, y: Int) {
114 case xs {
115 #(x) if x != y -> 1
116 _ -> 0
117 }
118}
119"#,
120 );
121}
122
123#[test]
124fn tuple_index() {
125 assert_js!(
126 r#"pub fn main(x, xs: #(Bool, Bool, Bool)) {
127 case x {
128 _ if xs.2 -> 1
129 _ -> 0
130 }
131}
132"#,
133 );
134}
135
136#[test]
137fn not_eq_complex() {
138 assert_js!(
139 r#"pub fn main(xs, y) {
140 case xs {
141 #(x) if xs != y -> x
142 _ -> 0
143 }
144}
145"#,
146 );
147}
148
149#[test]
150fn eq_complex() {
151 assert_js!(
152 r#"pub fn main(xs, y) {
153 case xs {
154 #(x) if xs == y -> x
155 _ -> 0
156 }
157}
158"#,
159 );
160}
161
162#[test]
163fn constant() {
164 assert_js!(
165 r#"pub fn main(xs) {
166 case xs {
167 #(x) if x == 1 -> x
168 _ -> 0
169 }
170}
171"#,
172 );
173}
174
175#[test]
176fn alternative_patterns() {
177 assert_js!(
178 r#"pub fn main(xs) {
179 case xs {
180 1 | 2 -> 0
181 _ -> 1
182 }
183}
184"#,
185 );
186}
187
188#[test]
189fn alternative_patterns_list() {
190 assert_js!(
191 r#"pub fn main(xs) -> Int {
192 case xs {
193 [1] | [1, 2] -> 0
194 _ -> 1
195 }
196}
197"#,
198 );
199}
200
201#[test]
202fn alternative_patterns_assignment() {
203 assert_js!(
204 r#"pub fn main(xs) -> Int {
205 case xs {
206 [x] | [_, x] -> x
207 _ -> 1
208 }
209}
210"#,
211 );
212}
213
214#[test]
215fn alternative_patterns_guard() {
216 assert_js!(
217 r#"pub fn main(xs) -> Int {
218 case xs {
219 [x] | [_, x] if x == 1 -> x
220 _ -> 0
221 }
222}
223"#,
224 );
225}
226
227#[test]
228fn field_access() {
229 assert_js!(
230 r#"
231 pub type Person {
232 Person(username: String, name: String, age: Int)
233 }
234 pub fn main() {
235 let given_name = "jack"
236 let raiden = Person("raiden", "jack", 31)
237 case given_name {
238 name if name == raiden.name -> "It's jack"
239 _ -> "It's not jack"
240 }
241 }
242 "#
243 )
244}
245
246#[test]
247fn nested_record_access() {
248 assert_js!(
249 r#"
250pub type A {
251 A(b: B)
252}
253
254pub type B {
255 B(c: C)
256}
257
258pub type C {
259 C(d: Bool)
260}
261
262pub fn a(a: A) {
263 case a {
264 _ if a.b.c.d -> 1
265 _ -> 0
266 }
267}
268"#
269 );
270}
271
272#[test]
273fn module_string_access() {
274 assert_js!(
275 (
276 "package",
277 "hero",
278 r#"
279 pub const ironman = "Tony Stark"
280 "#
281 ),
282 r#"
283 import hero
284 pub fn main() {
285 let name = "Tony Stark"
286 case name {
287 n if n == hero.ironman -> True
288 _ -> False
289 }
290 }
291 "#
292 );
293}
294
295#[test]
296fn module_list_access() {
297 assert_js!(
298 (
299 "package",
300 "hero",
301 r#"
302 pub const heroes = ["Tony Stark", "Bruce Wayne"]
303 "#
304 ),
305 r#"
306 import hero
307 pub fn main() {
308 let names = ["Tony Stark", "Bruce Wayne"]
309 case names {
310 n if n == hero.heroes -> True
311 _ -> False
312 }
313 }
314 "#
315 );
316}
317
318#[test]
319fn module_tuple_access() {
320 assert_js!(
321 (
322 "package",
323 "hero",
324 r#"
325 pub const hero = #("ironman", "Tony Stark")
326 "#
327 ),
328 r#"
329 import hero
330 pub fn main() {
331 let name = "Tony Stark"
332 case name {
333 n if n == hero.hero.1 -> True
334 _ -> False
335 }
336 }
337 "#
338 );
339}
340
341#[test]
342fn module_access() {
343 assert_js!(
344 (
345 "package",
346 "hero",
347 r#"
348 pub type Hero {
349 Hero(name: String)
350 }
351 pub const ironman = Hero("Tony Stark")
352 "#
353 ),
354 r#"
355 import hero
356 pub fn main() {
357 let name = "Tony Stark"
358 case name {
359 n if n == hero.ironman.name -> True
360 _ -> False
361 }
362 }
363 "#
364 );
365}
366
367#[test]
368fn module_access_submodule() {
369 assert_js!(
370 (
371 "package",
372 "hero/submodule",
373 r#"
374 pub type Hero {
375 Hero(name: String)
376 }
377 pub const ironman = Hero("Tony Stark")
378 "#
379 ),
380 r#"
381 import hero/submodule
382 pub fn main() {
383 let name = "Tony Stark"
384 case name {
385 n if n == submodule.ironman.name -> True
386 _ -> False
387 }
388 }
389 "#
390 );
391}
392
393#[test]
394fn module_access_aliased() {
395 assert_js!(
396 (
397 "package",
398 "hero/submodule",
399 r#"
400 pub type Hero {
401 Hero(name: String)
402 }
403 pub const ironman = Hero("Tony Stark")
404 "#
405 ),
406 r#"
407 import hero/submodule as myhero
408 pub fn main() {
409 let name = "Tony Stark"
410 case name {
411 n if n == myhero.ironman.name -> True
412 _ -> False
413 }
414 }
415 "#
416 );
417}
418
419#[test]
420fn module_nested_access() {
421 assert_js!(
422 (
423 "package",
424 "hero",
425 r#"
426 pub type Person {
427 Person(name: String)
428 }
429 pub type Hero {
430 Hero(secret_identity: Person)
431 }
432 const bruce = Person("Bruce Wayne")
433 pub const batman = Hero(bruce)
434 "#
435 ),
436 r#"
437 import hero
438 pub fn main() {
439 let name = "Bruce Wayne"
440 case name {
441 n if n == hero.batman.secret_identity.name -> True
442 _ -> False
443 }
444 }
445 "#
446 );
447}
448
449#[test]
450fn not() {
451 assert_js!(
452 r#"pub fn main(x, y) {
453 case x {
454 _ if !y -> 0
455 _ -> 1
456 }
457}
458"#,
459 );
460}
461
462#[test]
463fn not_two() {
464 assert_js!(
465 r#"pub fn main(x, y) {
466 case x {
467 _ if !y && !x -> 0
468 _ -> 1
469 }
470}
471"#,
472 );
473}
474
475#[test]
476fn custom_type_constructor_imported_and_aliased() {
477 assert_js!(
478 ("package", "other_module", "pub type T { A }"),
479 r#"import other_module.{A as B}
480pub fn func() {
481 case B {
482 x if x == B -> True
483 _ -> False
484 }
485}
486"#,
487 );
488}
489
490#[test]
491fn imported_aliased_ok() {
492 assert_js!(
493 r#"import gleam.{Ok as Y}
494pub type X {
495 Ok
496}
497pub fn func() {
498 case Y {
499 y if y == Y -> True
500 _ -> False
501 }
502}
503"#,
504 );
505}
506
507#[test]
508fn imported_ok() {
509 assert_js!(
510 r#"import gleam
511pub type X {
512 Ok
513}
514pub fn func(x) {
515 case gleam.Ok {
516 _ if [] == [ gleam.Ok ] -> True
517 _ -> False
518 }
519}
520"#,
521 );
522}
523
524// Variant of https://github.com/lpil/decode/pull/6
525#[test]
526fn constructor_function_in_guard() {
527 assert_js!(
528 r#"pub fn func(x) {
529 case [] {
530 _ if [] == [ Ok ] -> True
531 _ -> False
532 }
533}
534 "#,
535 );
536}
537
538// https://github.com/gleam-lang/gleam/issues/4241
539#[test]
540fn int_division() {
541 assert_js!(
542 r#"
543pub fn main() {
544 case 5 / 2 {
545 x if x == 5 / 2 -> True
546 _ -> False
547 }
548}
549"#,
550 );
551}
552
553// https://github.com/gleam-lang/gleam/issues/4241
554#[test]
555fn float_division() {
556 assert_js!(
557 r#"
558pub fn main() {
559 case 5.1 /. 0.0 {
560 x if x == 5.1 /. 0.0 -> True
561 _ -> False
562 }
563}
564"#,
565 );
566}
567
568// https://github.com/gleam-lang/gleam/issues/4241
569#[test]
570fn int_remainder() {
571 assert_js!(
572 r#"
573pub fn main() {
574 case 4 % 0 {
575 x if x == 4 % 0 -> True
576 _ -> False
577 }
578}
579"#,
580 );
581}
582
583// https://github.com/gleam-lang/gleam/issues/5094
584#[test]
585fn guard_pattern_does_not_shadow_outer_scope() {
586 assert_js!(
587 r#"
588pub type Option(a) {
589 Some(a)
590 None
591}
592
593pub type Container {
594 Container(x: Option(Int))
595}
596
597pub fn main() {
598 let x: Option(Int) = Some(42)
599 case Some(1) {
600 Some(x) if x < 0 -> Container(None)
601 _ -> {
602 Container(x:)
603 }
604 }
605}
606"#,
607 );
608}
609
610// https://github.com/gleam-lang/gleam/issues/5214
611#[test]
612fn bit_array_referencing_shadowed_variable() {
613 assert_js!(
614 "
615pub fn main() {
616 let a = 1
617 let a = 2
618
619 case Nil {
620 _ if <<a>> == <<1>> -> False
621 _ if <<a>> == <<2>> -> True
622 _ -> False
623 }
624}
625"
626 );
627}