schemurai 3.0.1 → 3.0.2
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/README.md +6 -4
- data/ext/schemurai_native/Cargo.lock +48 -1
- data/ext/schemurai_native/Cargo.toml +3 -1
- data/ext/schemurai_native/extconf.rb +1 -1
- data/ext/schemurai_native/glue.c +1679 -62
- data/ext/schemurai_native/protocol.def +45 -0
- data/ext/schemurai_native/src/budget.rs +49 -0
- data/ext/schemurai_native/src/container.rs +460 -0
- data/ext/schemurai_native/src/content.rs +56 -27
- data/ext/schemurai_native/src/diagnostics/array.rs +392 -0
- data/ext/schemurai_native/src/diagnostics/object.rs +218 -0
- data/ext/schemurai_native/src/diagnostics.rs +1087 -307
- data/ext/schemurai_native/src/enumeration.rs +6 -1
- data/ext/schemurai_native/src/evaluation.rs +49 -20
- data/ext/schemurai_native/src/format.rs +8 -6
- data/ext/schemurai_native/src/graph.rs +37 -0
- data/ext/schemurai_native/src/instance_graph.rs +90 -0
- data/ext/schemurai_native/src/lib.rs +910 -237
- data/ext/schemurai_native/src/memo.rs +11 -38
- data/ext/schemurai_native/src/number/arbitrary.rs +154 -0
- data/ext/schemurai_native/src/number.rs +250 -59
- data/ext/schemurai_native/src/pattern.rs +113 -101
- data/ext/schemurai_native/src/pointer.rs +97 -0
- data/ext/schemurai_native/src/runtime/properties.rs +162 -0
- data/ext/schemurai_native/src/runtime/reports.rs +266 -0
- data/ext/schemurai_native/src/runtime/scopes.rs +430 -0
- data/ext/schemurai_native/src/runtime.rs +1020 -0
- data/ext/schemurai_native/src/scope.rs +60 -16
- data/ext/schemurai_native/src/string.rs +68 -0
- data/ext/schemurai_native/src/tracking.rs +244 -174
- data/lib/schemurai/container_checks/array_diagnostics.rb +119 -0
- data/lib/schemurai/container_checks/object_diagnostics.rb +152 -0
- data/lib/schemurai/container_checks.rb +534 -0
- data/lib/schemurai/decimal.rb +11 -0
- data/lib/schemurai/dialect.rb +0 -12
- data/lib/schemurai/ecma_regexp.rb +46 -0
- data/lib/schemurai/evaluation_pool.rb +66 -0
- data/lib/schemurai/evaluator.rb +9 -48
- data/lib/schemurai/json_pointer.rb +11 -0
- data/lib/schemurai/native/diagnostics.rb +4 -3
- data/lib/schemurai/native/evaluator.rb +38 -10
- data/lib/schemurai/native/null_numeric.rb +23 -0
- data/lib/schemurai/number_checks.rb +128 -0
- data/lib/schemurai/string_checks.rb +166 -0
- data/lib/schemurai/type_checks.rb +59 -0
- data/lib/schemurai/value_equality.rb +72 -0
- data/lib/schemurai/version.rb +1 -1
- data/lib/schemurai/vm/compiler.rb +18 -26
- data/lib/schemurai/vm/evaluator.rb +87 -545
- data/lib/schemurai/vm/limited_evaluator.rb +7 -22
- metadata +24 -2
|
@@ -92,6 +92,7 @@ mod tests {
|
|
|
92
92
|
#[derive(Clone, Copy, Debug)]
|
|
93
93
|
enum ReferenceKind {
|
|
94
94
|
Static,
|
|
95
|
+
InvariantDynamic(usize),
|
|
95
96
|
Recursive,
|
|
96
97
|
Dynamic(usize),
|
|
97
98
|
}
|
|
@@ -117,11 +118,23 @@ impl Reference {
|
|
|
117
118
|
_ => None,
|
|
118
119
|
}
|
|
119
120
|
}
|
|
121
|
+
pub(super) fn callback_dynamic_target(self) -> Option<(usize, usize)> {
|
|
122
|
+
match self.kind {
|
|
123
|
+
ReferenceKind::Dynamic(name) | ReferenceKind::InvariantDynamic(name) => {
|
|
124
|
+
Some((name, self.target))
|
|
125
|
+
}
|
|
126
|
+
_ => None,
|
|
127
|
+
}
|
|
128
|
+
}
|
|
120
129
|
pub(super) fn recursive_target(self) -> Option<usize> {
|
|
121
130
|
matches!(self.kind, ReferenceKind::Recursive).then_some(self.target)
|
|
122
131
|
}
|
|
123
132
|
pub(super) fn static_target(self) -> Option<usize> {
|
|
124
|
-
matches!(
|
|
133
|
+
matches!(
|
|
134
|
+
self.kind,
|
|
135
|
+
ReferenceKind::Static | ReferenceKind::InvariantDynamic(_)
|
|
136
|
+
)
|
|
137
|
+
.then_some(self.target)
|
|
125
138
|
}
|
|
126
139
|
}
|
|
127
140
|
impl Engine {
|
|
@@ -148,7 +161,7 @@ impl Engine {
|
|
|
148
161
|
&& let ReferenceKind::Dynamic(name) = reference.kind
|
|
149
162
|
&& invariant[name] == Some(reference.target)
|
|
150
163
|
{
|
|
151
|
-
reference.kind = ReferenceKind::
|
|
164
|
+
reference.kind = ReferenceKind::InvariantDynamic(name);
|
|
152
165
|
}
|
|
153
166
|
}
|
|
154
167
|
}
|
|
@@ -386,6 +399,14 @@ impl Engine {
|
|
|
386
399
|
active
|
|
387
400
|
}
|
|
388
401
|
}
|
|
402
|
+
fn scope_binding(&self, reference: Reference, resource: Value) -> Option<usize> {
|
|
403
|
+
if let Some((name, _)) = reference.callback_dynamic_target() {
|
|
404
|
+
return self.dynamic_bindings.get(&(resource, name)).copied();
|
|
405
|
+
}
|
|
406
|
+
let &root = self.resources.get(&resource)?;
|
|
407
|
+
(reference.recursive_target().is_some() && self.metadata[root].recursive_anchor)
|
|
408
|
+
.then_some(root)
|
|
409
|
+
}
|
|
389
410
|
pub(super) fn reference_target(&self, reference: Reference, context: Context<'_>) -> usize {
|
|
390
411
|
if matches!(reference.kind, ReferenceKind::Dynamic(0)) && self.anchor_tables.len() == 1 {
|
|
391
412
|
return context
|
|
@@ -398,23 +419,46 @@ impl Engine {
|
|
|
398
419
|
// Linked frames walk inner to outer. Keep replacing a match so the
|
|
399
420
|
// outermost matching resource wins, just as the VM's scope.each does.
|
|
400
421
|
while let Some(frame) = current {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
{
|
|
407
|
-
target = root;
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
ReferenceKind::Dynamic(name) => {
|
|
411
|
-
if let Some(binding) = self.dynamic_bindings.get(&(frame.resource, name)) {
|
|
412
|
-
target = *binding;
|
|
413
|
-
}
|
|
414
|
-
}
|
|
422
|
+
if reference.static_target().is_some() {
|
|
423
|
+
break;
|
|
424
|
+
}
|
|
425
|
+
if let Some(binding) = self.scope_binding(reference, frame.resource) {
|
|
426
|
+
target = binding;
|
|
415
427
|
}
|
|
416
428
|
current = frame.parent;
|
|
417
429
|
}
|
|
418
430
|
target
|
|
419
431
|
}
|
|
420
432
|
}
|
|
433
|
+
|
|
434
|
+
impl Execution<'_> {
|
|
435
|
+
pub(super) fn resolve_reference(
|
|
436
|
+
&self,
|
|
437
|
+
reference: Reference,
|
|
438
|
+
value: Value,
|
|
439
|
+
active: Context<'_>,
|
|
440
|
+
) -> Result<usize, Verdict> {
|
|
441
|
+
if !self.caches.scopes_enabled() {
|
|
442
|
+
return Ok(self.engine.reference_target(reference, active));
|
|
443
|
+
}
|
|
444
|
+
let dynamic = reference.callback_dynamic_target();
|
|
445
|
+
let recursive = reference.recursive_target();
|
|
446
|
+
if dynamic.is_none() && recursive.is_none() {
|
|
447
|
+
return Ok(reference.static_target().expect("static reference"));
|
|
448
|
+
}
|
|
449
|
+
let mut index = 0;
|
|
450
|
+
while let Some(resource) = self.caches.scope_at(index) {
|
|
451
|
+
if self.caches.callback_checkpoint(value) != Valid {
|
|
452
|
+
return Err(Unsupported);
|
|
453
|
+
}
|
|
454
|
+
if let Some(target) = self.engine.scope_binding(reference, resource) {
|
|
455
|
+
return Ok(target);
|
|
456
|
+
}
|
|
457
|
+
index += 1;
|
|
458
|
+
}
|
|
459
|
+
Ok(dynamic
|
|
460
|
+
.map(|(_, fallback)| fallback)
|
|
461
|
+
.or(recursive)
|
|
462
|
+
.expect("scoped reference"))
|
|
463
|
+
}
|
|
464
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
//! Staged Ruby string semantics for values without safe native storage views.
|
|
2
|
+
use super::*;
|
|
3
|
+
|
|
4
|
+
impl StringRules {
|
|
5
|
+
pub(super) fn runtime_valid(
|
|
6
|
+
&self,
|
|
7
|
+
caches: &runtime::Caches,
|
|
8
|
+
required: i32,
|
|
9
|
+
value: Value,
|
|
10
|
+
) -> Verdict {
|
|
11
|
+
caches
|
|
12
|
+
.string(self.source, value, required | self.runtime_flags)
|
|
13
|
+
.map_or(Unsupported, |frame| frame.step(0))
|
|
14
|
+
}
|
|
15
|
+
pub(super) fn runtime_failures(
|
|
16
|
+
&self,
|
|
17
|
+
caches: &runtime::Caches,
|
|
18
|
+
required: i32,
|
|
19
|
+
value: Value,
|
|
20
|
+
mut visit: impl FnMut(&'static str, Value, bool) -> Result<(), Verdict>,
|
|
21
|
+
) -> Result<(), Verdict> {
|
|
22
|
+
let frame = caches.string(self.source, value, required | self.runtime_flags)?;
|
|
23
|
+
if !frame.predicate(1)? {
|
|
24
|
+
if required != 0 {
|
|
25
|
+
visit("type", frame.ordinal(), false)?;
|
|
26
|
+
}
|
|
27
|
+
return Ok(());
|
|
28
|
+
}
|
|
29
|
+
if !frame.predicate(2)? {
|
|
30
|
+
visit("pattern", frame.ordinal(), true)?;
|
|
31
|
+
return Ok(());
|
|
32
|
+
}
|
|
33
|
+
for (step, active, keyword) in [
|
|
34
|
+
(3, self.runtime_flags & 4 != 0, "maxLength"),
|
|
35
|
+
(4, self.runtime_flags & 8 != 0, "minLength"),
|
|
36
|
+
(5, self.pattern.is_some(), "pattern"),
|
|
37
|
+
(6, self.runtime_format, "format"),
|
|
38
|
+
(
|
|
39
|
+
7,
|
|
40
|
+
self.content.is_some(),
|
|
41
|
+
if self.content.as_ref().is_some_and(|c| c.base64) {
|
|
42
|
+
"contentEncoding"
|
|
43
|
+
} else {
|
|
44
|
+
"contentMediaType"
|
|
45
|
+
},
|
|
46
|
+
),
|
|
47
|
+
] {
|
|
48
|
+
if active && !frame.predicate(step)? {
|
|
49
|
+
let invalid_pattern = frame.predicate(8 + step)?;
|
|
50
|
+
match visit(
|
|
51
|
+
if invalid_pattern { "pattern" } else { keyword },
|
|
52
|
+
frame.ordinal(),
|
|
53
|
+
invalid_pattern,
|
|
54
|
+
) {
|
|
55
|
+
Err(Invalid) if !invalid_pattern => {
|
|
56
|
+
visit("pattern", frame.ordinal(), true)?;
|
|
57
|
+
return Ok(());
|
|
58
|
+
}
|
|
59
|
+
result => result?,
|
|
60
|
+
}
|
|
61
|
+
if invalid_pattern {
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
Ok(())
|
|
67
|
+
}
|
|
68
|
+
}
|