forked from nulang-org/nulang
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathspill_bug_repro.nula
More file actions
96 lines (96 loc) · 4.3 KB
/
Copy pathspill_bug_repro.nula
File metadata and controls
96 lines (96 loc) · 4.3 KB
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
// Reproduction: recursive parse_pratt inside app branch with result processing
fn is_digit(c: Int) -> Bool { c >= 48 and c <= 57 }
fn is_space(c: Int) -> Bool { c == 32 or c == 10 or c == 13 or c == 9 }
fn skip_ws(src: String, pos: Int, len: Int) -> Int {
if pos >= len then pos
else if is_space(perform String.charAt(src, pos)) then skip_ws(src, pos + 1, len)
else pos
}
fn read_int(src: String, pos: Int, len: Int, acc: Int) -> Int {
if pos >= len then (acc << 32) + pos
else {
let c = perform String.charAt(src, pos);
if is_digit(c) then read_int(src, pos + 1, len, acc * 10 + (c - 48))
else (acc << 32) + pos
}
}
fn prec_of(c: Int) -> Int {
if c == 43 then 1 else if c == 45 then 1
else if c == 42 then 2 else if c == 47 then 2
else 0
}
fn parse_pratt(src: String, pos: Int, len: Int, left: Int, min_prec: Int) -> Int {
let pair = if left == 0 then {
let p = skip_ws(src, pos, len);
if p >= len then (0 << 32) + p
else {
let c = perform String.charAt(src, p);
if is_digit(c) then read_int(src, p, len, 0)
else if c == 40 then {
let d0 = 0; let d1 = 1; let d2 = 2; let d3 = 3; let d4 = 4; let d5 = 5; let d6 = 6; let d7 = 7; let d8 = 8; let d9 = 9; let d10 = 10; let d11 = 11; let d12 = 12; let d13 = 13; let d14 = 14; let d15 = 15; let d16 = 16; let d17 = 17; let d18 = 18; let d19 = 19;
let inner = parse_pratt(src, p + 1, len, 0, 0);
let v = inner >> 32;
let q = inner & 0xFFFFFFFF;
let q2 = skip_ws(src, q, len);
if q2 < len then {
let c2 = perform String.charAt(src, q2);
if c2 == 41 then (v << 32) + (q2 + 1)
else (v << 32) + q2
} else (v << 32) + q2
} else (0 << 32) + p
}
} else (left << 32) + pos;
let lv = pair >> 32;
let lp = pair & 0xFFFFFFFF;
// Dummies between prefix and loop
let e0 = 0; let e1 = 1; let e2 = 2; let e3 = 3; let e4 = 4; let e5 = 5; let e6 = 6; let e7 = 7; let e8 = 8; let e9 = 9; let e10 = 10; let e11 = 11; let e12 = 12; let e13 = 13; let e14 = 14; let e15 = 15; let e16 = 16; let e17 = 17; let e18 = 18; let e19 = 19;
let p = skip_ws(src, lp, len);
if p >= len then pair
else {
let c = perform String.charAt(src, p);
if c == 40 then {
// Application: parse arg, then call parse_pratt recursively,
// then process result and call parse_pratt again.
let f0 = 0; let f1 = 1; let f2 = 2; let f3 = 3; let f4 = 4; let f5 = 5; let f6 = 6; let f7 = 7; let f8 = 8; let f9 = 9; let f10 = 10; let f11 = 11; let f12 = 12; let f13 = 13; let f14 = 14; let f15 = 15; let f16 = 16; let f17 = 17; let f18 = 18; let f19 = 19;
let arg = parse_pratt(src, p + 1, len, 0, 0);
let av = arg >> 32;
let ap = arg & 0xFFFFFFFF;
let ap2 = skip_ws(src, ap, len);
if ap2 < len then {
let c2 = perform String.charAt(src, ap2);
if c2 == 41 then {
// Recursive call with new state, then process result
let inner = parse_pratt(src, ap2 + 1, len, 0, 0);
let rv = inner >> 32;
let rp2 = inner & 0xFFFFFFFF;
// Process result: another recursive call
parse_pratt(src, rp2, len, rv, min_prec)
} else pair
} else pair
} else {
let prec = prec_of(c);
if prec == 0 or prec < min_prec then pair
else {
let rhs = parse_pratt(src, p + 1, len, 0, prec);
let rv = rhs >> 32;
let rp = rhs & 0xFFFFFFFF;
let result = if c == 43 then lv + rv
else if c == 45 then lv - rv
else if c == 42 then lv * rv
else if c == 47 then {
if rv == 0 then lv else lv / rv
} else lv;
parse_pratt(src, rp, len, result, min_prec)
}
}
}
}
fn parse(src: String) -> Int {
let len = perform String.length(src);
let result = parse_pratt(src, 0, len, 0, 0);
result >> 32
}
fn main() {
perform IO.print(parse("1 + 2 * 3"))
perform IO.print(parse("42"))
}