parsanol 1.3.68 → 1.3.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Cargo.lock +32 -3
- data/ext/parsanol_native/Cargo.toml +3 -2
- data/lib/parsanol/version.rb +1 -1
- data/lib/parsanol/vm.rb +38 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 46a9a34dd51e63ba24ee155131eb13326947d08cf08a9814a6d600046aead88a
|
|
4
|
+
data.tar.gz: 679d459fa6c46a6b27816c042af13b0c6e9f15ccae847786140c473731b25ebd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5bddc1e0b863c8f50be6573f29e09b17091c95dbfd0db57c660aea348d090b681bb7d99e3870276f3b05f32fcc1944098f71777bdaf4db2b34f348c1e847fbaa
|
|
7
|
+
data.tar.gz: bbb0ce39775917e628fcc19a04d15e2f252437d6fdcfe9b9b69f33711e096b2cb9a2b9a40908177068f66e54c3dc9ceb4d4ba25396b4cfc0ac465de34667b65d
|
data/Cargo.lock
CHANGED
|
@@ -310,13 +310,31 @@ name = "parsanol"
|
|
|
310
310
|
version = "0.10.2"
|
|
311
311
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
312
312
|
checksum = "dd43c104276def3f79a54ce6e8d26642ea330c13f97d66380bd94fc057f0a849"
|
|
313
|
+
dependencies = [
|
|
314
|
+
"ahash",
|
|
315
|
+
"getrandom 0.3.4",
|
|
316
|
+
"getrandom 0.4.3",
|
|
317
|
+
"hashbrown",
|
|
318
|
+
"parsanol-derive 0.10.2",
|
|
319
|
+
"regex",
|
|
320
|
+
"regex-syntax",
|
|
321
|
+
"serde",
|
|
322
|
+
"serde_json",
|
|
323
|
+
"sha2",
|
|
324
|
+
]
|
|
325
|
+
|
|
326
|
+
[[package]]
|
|
327
|
+
name = "parsanol"
|
|
328
|
+
version = "0.12.0"
|
|
329
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
330
|
+
checksum = "b3754baf8f7f9761748bac497cd60efd1bab93ff54c4212e899e27cf3f09100a"
|
|
313
331
|
dependencies = [
|
|
314
332
|
"ahash",
|
|
315
333
|
"getrandom 0.3.4",
|
|
316
334
|
"getrandom 0.4.3",
|
|
317
335
|
"hashbrown",
|
|
318
336
|
"magnus",
|
|
319
|
-
"parsanol-derive",
|
|
337
|
+
"parsanol-derive 0.12.0",
|
|
320
338
|
"regex",
|
|
321
339
|
"regex-syntax",
|
|
322
340
|
"serde",
|
|
@@ -335,11 +353,22 @@ dependencies = [
|
|
|
335
353
|
"syn 3.0.6",
|
|
336
354
|
]
|
|
337
355
|
|
|
356
|
+
[[package]]
|
|
357
|
+
name = "parsanol-derive"
|
|
358
|
+
version = "0.12.0"
|
|
359
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
360
|
+
checksum = "7cdc8438988a014ec5a7cb6d7891c3c467154de134b353e8790bd42d4ae2ddd5"
|
|
361
|
+
dependencies = [
|
|
362
|
+
"proc-macro2",
|
|
363
|
+
"quote",
|
|
364
|
+
"syn 3.0.6",
|
|
365
|
+
]
|
|
366
|
+
|
|
338
367
|
[[package]]
|
|
339
368
|
name = "parsanol_cdylib"
|
|
340
369
|
version = "1.3.52"
|
|
341
370
|
dependencies = [
|
|
342
|
-
"parsanol",
|
|
371
|
+
"parsanol 0.10.2",
|
|
343
372
|
]
|
|
344
373
|
|
|
345
374
|
[[package]]
|
|
@@ -348,7 +377,7 @@ version = "1.0.2"
|
|
|
348
377
|
dependencies = [
|
|
349
378
|
"log",
|
|
350
379
|
"magnus",
|
|
351
|
-
"parsanol",
|
|
380
|
+
"parsanol 0.12.0",
|
|
352
381
|
"rb-sys",
|
|
353
382
|
]
|
|
354
383
|
|
|
@@ -27,8 +27,9 @@ rb-sys = { version = "0.9.124", features = ["global-allocator"] }
|
|
|
27
27
|
# magnus for Ruby bindings (from crates.io, patched locally for Ruby 4.0 support)
|
|
28
28
|
magnus = { version = "0.9" }
|
|
29
29
|
|
|
30
|
-
# parsanol parser library (crates.io; 0.
|
|
31
|
-
|
|
30
|
+
# parsanol parser library (crates.io; 0.12 carries the rs#174 native
|
|
31
|
+
# backtracking fix: dynamic-dependent memoization + outcome cache)
|
|
32
|
+
parsanol = { version = "0.12.0", features = ["ruby"] }
|
|
32
33
|
|
|
33
34
|
# Logging
|
|
34
35
|
log = "0.4"
|
data/lib/parsanol/version.rb
CHANGED
data/lib/parsanol/vm.rb
CHANGED
|
@@ -84,6 +84,14 @@ module Parsanol
|
|
|
84
84
|
STEP_BUDGET_FIXED = 10_000
|
|
85
85
|
MEMO_BUDGET_FACTOR = 4_096
|
|
86
86
|
MEMO_BUDGET_CELLS_FACTOR = 16
|
|
87
|
+
# Wall-clock ceiling for the memoized retry pass. Step budgets assume
|
|
88
|
+
# sub-microsecond steps; pathological grammars make each step
|
|
89
|
+
# expensive enough that a step budget alone mispredicts wall time by
|
|
90
|
+
# orders of magnitude (parsanol-ruby#147: a 6-line skip-injected
|
|
91
|
+
# document ground ~146s inside its memo budget where the interpreter
|
|
92
|
+
# answers in milliseconds). Bounded wall time surrenders the grammar
|
|
93
|
+
# to the interpreter, the source of truth, instead of burning CPU.
|
|
94
|
+
MEMO_WALL_BUDGET_SECONDS = 5.0
|
|
87
95
|
|
|
88
96
|
# Compiled-program and heavy-flag caches hold at most this many
|
|
89
97
|
# grammars. A process rarely uses more than a handful concurrently;
|
|
@@ -130,7 +138,10 @@ module Parsanol
|
|
|
130
138
|
end
|
|
131
139
|
cache[root] = program
|
|
132
140
|
trim_cache(cache)
|
|
133
|
-
|
|
141
|
+
# :fallback = VM-incompatible; :oversize even non-inlined means
|
|
142
|
+
# the grammar is beyond the program cap — the interpreter
|
|
143
|
+
# handles both.
|
|
144
|
+
program.equal?(:fallback) || program.equal?(:oversize) ? nil : program
|
|
134
145
|
end
|
|
135
146
|
|
|
136
147
|
# Marks a grammar as VM-incompatible after a runtime failure.
|
|
@@ -197,6 +208,10 @@ module Parsanol
|
|
|
197
208
|
end
|
|
198
209
|
|
|
199
210
|
compiler.to_program
|
|
211
|
+
rescue Compiler::ProgramTooLarge
|
|
212
|
+
# Emission aborted at the cap: discard and let the caller
|
|
213
|
+
# decide (compile retries non-inlined).
|
|
214
|
+
:oversize
|
|
200
215
|
end
|
|
201
216
|
|
|
202
217
|
# Returns violation descriptions for this atom's ordered-choice
|
|
@@ -679,7 +694,19 @@ module Parsanol
|
|
|
679
694
|
|
|
680
695
|
private
|
|
681
696
|
|
|
697
|
+
# Raised mid-emission once the program passes MAX_PROGRAM: abort
|
|
698
|
+
# the build immediately instead of materializing millions of
|
|
699
|
+
# instructions only to discover the overflow in to_program
|
|
700
|
+
# (parsanol-ruby#147: an inline pass on a skip-injected grammar
|
|
701
|
+
# reached 6.3M instructions / 16M with subroutines before the
|
|
702
|
+
# post-hoc check discarded them — minutes of compile time and
|
|
703
|
+
# gigabytes of transient allocations for a program that is
|
|
704
|
+
# thrown away and rebuilt non-inlined anyway).
|
|
705
|
+
class ProgramTooLarge < StandardError; end
|
|
706
|
+
|
|
682
707
|
def emit(op, a = nil, b = nil, c = nil) # rubocop:disable Naming/MethodParameterName -- opcode operand slots
|
|
708
|
+
raise ProgramTooLarge if @ops.size > MAX_PROGRAM
|
|
709
|
+
|
|
683
710
|
@ops << [op, a, b, c]
|
|
684
711
|
@ops.size - 1
|
|
685
712
|
end
|
|
@@ -902,6 +929,9 @@ module Parsanol
|
|
|
902
929
|
(STEP_BUDGET_FACTOR * n) + STEP_BUDGET_FIXED
|
|
903
930
|
end
|
|
904
931
|
steps = 0
|
|
932
|
+
wall_deadline = if @memoize
|
|
933
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC) + MEMO_WALL_BUDGET_SECONDS
|
|
934
|
+
end
|
|
905
935
|
|
|
906
936
|
pc = 0
|
|
907
937
|
pos = 0
|
|
@@ -917,6 +947,13 @@ module Parsanol
|
|
|
917
947
|
# rubocop:disable Metrics/BlockLength -- the dispatch loop IS execute
|
|
918
948
|
loop do
|
|
919
949
|
steps += 1
|
|
950
|
+
# Checked every 1024 steps: a monotonic clock read per
|
|
951
|
+
# millisecond of ordinary work costs nothing measurable.
|
|
952
|
+
if wall_deadline && steps.nobits?(0x3FF) &&
|
|
953
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC) > wall_deadline
|
|
954
|
+
return BUDGET
|
|
955
|
+
end
|
|
956
|
+
|
|
920
957
|
if steps > budget
|
|
921
958
|
if trace
|
|
922
959
|
warn "BUDGET at steps=#{steps} pc=#{pc} pos=#{pos} rstack=#{rstack.size} bt=#{bt.size} calls=#{calls.size}"
|