Skip to content

Commit efe51ee

Browse files
giacomocavalierilpil
authored andcommitted
fix a bug with JS codegen of pattern matching expression using string literals
and segments with a statically unknown size
1 parent 6223938 commit efe51ee

File tree

4 files changed

+56
-4
lines changed

4 files changed

+56
-4
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,3 +748,7 @@
748748
- Fixed a bug where running `gleam update` would not properly update git
749749
dependencies unless `gleam clean` was run first.
750750
([Surya Rose](https://github.com/GearsDatapacks))
751+
752+
- Fixed a bug where the compiler would produce wrong JavaScript code for binary
753+
pattern matching expressions using literal strings and byte segments.
754+
([Giacomo Cavalieri](https://github.com/giacomocavalieri))

compiler-core/src/javascript/decision.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,14 +1443,18 @@ impl<'generator, 'module, 'a> Variables<'generator, 'module, 'a> {
14431443
from_byte += 1;
14441444
}
14451445
} else {
1446+
let mut start = start.clone();
1447+
14461448
// If the string doesn't start at a byte aligned offset then we'll
14471449
// have to take slices out of it to check that each byte matches.
14481450
for byte in bytes {
1449-
let end = self.offset_to_doc(&start.add_constant(8), false);
1450-
let from = self.offset_to_doc(start, false);
1451-
let byte_access =
1452-
self.bit_array_slice_to_int(&bit_array, from, end, endianness, *signed);
1451+
let start_doc = self.offset_to_doc(&start, false);
1452+
let end = start.add_constant(8);
1453+
let end_doc = self.offset_to_doc(&end, false);
1454+
let byte_access = self
1455+
.bit_array_slice_to_int(&bit_array, start_doc, end_doc, endianness, *signed);
14531456
checks.push(docvec![byte_access, equality, byte]);
1457+
start = end;
14541458
}
14551459
}
14561460

compiler-core/src/javascript/tests/bit_arrays.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,3 +2631,17 @@ pub fn main() {
26312631
"
26322632
);
26332633
}
2634+
2635+
#[test]
2636+
fn pattern_match_unknown_size_and_literal_string() {
2637+
assert_js!(
2638+
r#"
2639+
pub fn go(x, n) {
2640+
case x {
2641+
<<_:size(n), "\r\n">> -> 1
2642+
_ -> 2
2643+
}
2644+
}
2645+
"#
2646+
);
2647+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
source: compiler-core/src/javascript/tests/bit_arrays.rs
3+
expression: "\npub fn go(x, n) {\n case x {\n <<_:size(n), \"\\r\\n\">> -> 1\n _ -> 2\n }\n}\n"
4+
---
5+
----- SOURCE CODE
6+
7+
pub fn go(x, n) {
8+
case x {
9+
<<_:size(n), "\r\n">> -> 1
10+
_ -> 2
11+
}
12+
}
13+
14+
15+
----- COMPILED JAVASCRIPT
16+
import { bitArraySliceToInt } from "../gleam.mjs";
17+
18+
export function go(x, n) {
19+
if (
20+
n >= 0 &&
21+
x.bitSize >= n &&
22+
x.bitSize === 16 + n &&
23+
bitArraySliceToInt(x, n, 8 + n, true, false) === 13 &&
24+
bitArraySliceToInt(x, 8 + n, 16 + n, true, false) === 10
25+
) {
26+
return 1;
27+
} else {
28+
return 2;
29+
}
30+
}

0 commit comments

Comments
 (0)