interscript 2.4.5 → 3.0.0
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 +15 -0
- data/docs/demo/20191118-interscript-demo-cast.gif +0 -0
- data/exe/codemod-imp-to-isc +5 -0
- data/exe/diagnose_parse_failures +47 -0
- data/exe/interscript +2 -1
- data/exe/verify_isc_deep +211 -0
- data/exe/verify_isc_equivalence +128 -0
- data/interscript.gemspec +27 -20
- data/lib/interscript/command.rb +21 -12
- data/lib/interscript/compiler/javascript.rb +34 -35
- data/lib/interscript/compiler/json_ir.rb +214 -0
- data/lib/interscript/compiler/python.rb +354 -0
- data/lib/interscript/compiler/ruby.rb +23 -22
- data/lib/interscript/compiler.rb +20 -3
- data/lib/interscript/detector.rb +14 -7
- data/lib/interscript/dsl/aliases.rb +1 -1
- data/lib/interscript/dsl/document.rb +6 -3
- data/lib/interscript/dsl/group/parallel.rb +1 -1
- data/lib/interscript/dsl/group.rb +18 -9
- data/lib/interscript/dsl/items.rb +28 -16
- data/lib/interscript/dsl/metadata.rb +19 -18
- data/lib/interscript/dsl/stage.rb +1 -1
- data/lib/interscript/dsl/symbol_mm.rb +4 -2
- data/lib/interscript/dsl/tests.rb +1 -1
- data/lib/interscript/dsl.rb +21 -13
- data/lib/interscript/interpreter.rb +32 -21
- data/lib/interscript/isc/codemod.rb +791 -0
- data/lib/interscript/isc/document_builder.rb +354 -0
- data/lib/interscript/isc/generator.rb +191 -0
- data/lib/interscript/isc/grammar/concerns/aliases.rb +29 -0
- data/lib/interscript/isc/grammar/concerns/dependencies.rb +23 -0
- data/lib/interscript/isc/grammar/concerns/items.rb +176 -0
- data/lib/interscript/isc/grammar/concerns/metadata.rb +142 -0
- data/lib/interscript/isc/grammar/concerns/primitives.rb +112 -0
- data/lib/interscript/isc/grammar/concerns/stages.rb +129 -0
- data/lib/interscript/isc/grammar/concerns/system.rb +37 -0
- data/lib/interscript/isc/grammar/concerns/tests.rb +31 -0
- data/lib/interscript/isc/grammar/concerns.rb +18 -0
- data/lib/interscript/isc/grammar/core.rb +23 -0
- data/lib/interscript/isc/grammar/isc.artifact.json +1 -0
- data/lib/interscript/isc/grammar/isc.parg +196 -0
- data/lib/interscript/isc/grammar.rb +12 -0
- data/lib/interscript/isc/items.rb +185 -0
- data/lib/interscript/isc/model/alias.rb +20 -0
- data/lib/interscript/isc/model/constraint.rb +20 -0
- data/lib/interscript/isc/model/dependency.rb +19 -0
- data/lib/interscript/isc/model/document.rb +31 -0
- data/lib/interscript/isc/model/item.rb +50 -0
- data/lib/interscript/isc/model/rule.rb +23 -0
- data/lib/interscript/isc/model/stage.rb +20 -0
- data/lib/interscript/isc/model/stage_item.rb +33 -0
- data/lib/interscript/isc/model/test.rb +21 -0
- data/lib/interscript/isc/model.rb +19 -0
- data/lib/interscript/isc/node_adapter.rb +310 -0
- data/lib/interscript/isc/normalizer.rb +127 -0
- data/lib/interscript/isc/parser.rb +78 -0
- data/lib/interscript/isc/serializer.rb +248 -0
- data/lib/interscript/isc/transform.rb +138 -0
- data/lib/interscript/isc/yaml_bridge.rb +236 -0
- data/lib/interscript/isc.rb +30 -0
- data/lib/interscript/ml/byt5_onnx.rb +102 -0
- data/lib/interscript/ml/imf.rb +182 -0
- data/lib/interscript/ml/model.rb +52 -0
- data/lib/interscript/ml/provisioning.rb +189 -0
- data/lib/interscript/ml/translator.rb +38 -0
- data/lib/interscript/ml/vocab.rb +48 -0
- data/lib/interscript/ml.rb +25 -0
- data/lib/interscript/node/alias_def.rb +5 -5
- data/lib/interscript/node/dependency.rb +7 -7
- data/lib/interscript/node/document.rb +10 -10
- data/lib/interscript/node/group.rb +11 -9
- data/lib/interscript/node/item/alias.rb +14 -10
- data/lib/interscript/node/item/any.rb +14 -7
- data/lib/interscript/node/item/capture.rb +14 -9
- data/lib/interscript/node/item/group.rb +22 -17
- data/lib/interscript/node/item/repeat.rb +3 -3
- data/lib/interscript/node/item/stage.rb +4 -5
- data/lib/interscript/node/item/string.rb +18 -13
- data/lib/interscript/node/item.rb +27 -17
- data/lib/interscript/node/metadata.rb +6 -5
- data/lib/interscript/node/rule/funcall.rb +4 -5
- data/lib/interscript/node/rule/run.rb +4 -5
- data/lib/interscript/node/rule/sub.rb +55 -55
- data/lib/interscript/node/rule.rb +6 -5
- data/lib/interscript/node/stage.rb +11 -14
- data/lib/interscript/node/tests.rb +6 -6
- data/lib/interscript/node.rb +14 -17
- data/lib/interscript/stdlib/functions/rababa_adapter.rb +56 -0
- data/lib/interscript/stdlib/functions/secryst_adapter.rb +37 -0
- data/lib/interscript/stdlib/functions.rb +49 -0
- data/lib/interscript/stdlib.rb +25 -95
- data/lib/interscript/utils/helpers.rb +8 -5
- data/lib/interscript/utils/regexp_converter.rb +143 -144
- data/lib/interscript/version.rb +1 -1
- data/lib/interscript/visualize/json.rb +12 -13
- data/lib/interscript/visualize/nodes.rb +13 -13
- data/lib/interscript/visualize.rb +18 -18
- data/lib/interscript.rb +59 -45
- metadata +88 -31
- data/.github/workflows/assets.yml +0 -91
- data/.github/workflows/rake.yml +0 -52
- data/.github/workflows/release.yml +0 -68
- data/.gitignore +0 -79
- data/.rspec +0 -3
- data/Gemfile +0 -38
- data/Rakefile +0 -139
- data/bin/console +0 -10
- data/bin/interscript +0 -5
- data/bin/maps_analyze_staging +0 -168
- data/bin/maps_debug_compilers +0 -58
- data/bin/maps_debug_ordering +0 -88
- data/bin/maps_debug_ruby_compile +0 -24
- data/bin/maps_debug_step_by_step +0 -44
- data/bin/maps_optimize_order +0 -112
- data/bin/maps_v1_analyze_regexps +0 -45
- data/bin/maps_v1_to_v2 +0 -426
- data/bin/set_version +0 -16
- data/bin/setup +0 -8
- data/requirements.txt +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
begin
|
|
2
|
-
require
|
|
2
|
+
require "mini_racer"
|
|
3
3
|
rescue LoadError
|
|
4
4
|
# Ignore loading error
|
|
5
5
|
end
|
|
6
|
-
require
|
|
6
|
+
require "json"
|
|
7
7
|
|
|
8
8
|
class Interscript::Compiler::Javascript < Interscript::Compiler
|
|
9
9
|
def compile(map, debug: false)
|
|
@@ -12,24 +12,23 @@ class Interscript::Compiler::Javascript < Interscript::Compiler
|
|
|
12
12
|
@parallel_regexps = {}
|
|
13
13
|
@debug = debug
|
|
14
14
|
c = "var map = function(Interscript) {"
|
|
15
|
-
c << "Interscript.define_map(#{map.name.inspect}, function(Interscript, map) {\n"
|
|
15
|
+
c << "Interscript.define_map(#{map.name.inspect}, function(Interscript, map) {\n"
|
|
16
16
|
c << "map.dependencies = #{map.dependencies.map(&:full_name).to_json};\n"
|
|
17
|
-
c
|
|
18
17
|
|
|
19
18
|
map.aliases.each do |name, value|
|
|
20
19
|
val = compile_item(value.data, map, :str)
|
|
21
20
|
c << "map.aliases.#{name} = #{val};\n"
|
|
22
|
-
val = '"'+compile_item(value.data, map, :re)+'"'
|
|
21
|
+
val = '"' + compile_item(value.data, map, :re) + '"'
|
|
23
22
|
c << "map.aliases_re.#{name} = #{val};\n"
|
|
24
23
|
end
|
|
25
24
|
|
|
26
25
|
map.stages.each do |_, stage|
|
|
27
26
|
c << compile_rule(stage, @map, true)
|
|
28
27
|
end
|
|
29
|
-
@parallel_trees.each do |k,v|
|
|
28
|
+
@parallel_trees.each do |k, v|
|
|
30
29
|
c << "map.cache.PTREE_#{k} = #{v.to_json};\n"
|
|
31
30
|
end
|
|
32
|
-
@parallel_regexps.each do |k,v|
|
|
31
|
+
@parallel_regexps.each do |k, v|
|
|
33
32
|
v = "[\"#{v[0]}\", #{v[1].to_json}]"
|
|
34
33
|
c << "map.cache.PRE_#{k} = #{v};\n"
|
|
35
34
|
end
|
|
@@ -44,10 +43,10 @@ class Interscript::Compiler::Javascript < Interscript::Compiler
|
|
|
44
43
|
|
|
45
44
|
def parallel_regexp_compile(subs_hash)
|
|
46
45
|
# puts subs_hash.inspect
|
|
47
|
-
|
|
48
|
-
"(?<_%d>%s)" % [i,p[0]]
|
|
46
|
+
subs_hash.each_with_index.map do |p, i|
|
|
47
|
+
"(?<_%d>%s)" % [i, p[0]]
|
|
49
48
|
end.join("|")
|
|
50
|
-
|
|
49
|
+
|
|
51
50
|
# puts subs_regexp.inspect
|
|
52
51
|
end
|
|
53
52
|
|
|
@@ -90,7 +89,7 @@ class Interscript::Compiler::Javascript < Interscript::Compiler
|
|
|
90
89
|
a = []
|
|
91
90
|
Interscript::Stdlib.deterministic_sort_by_max_length(r.children).each do |i|
|
|
92
91
|
raise Interscript::SystemConversionError, "Can't parallelize #{i.class}" unless Interscript::Node::Rule::Sub === i
|
|
93
|
-
|
|
92
|
+
|
|
94
93
|
next if i.reverse_run == true
|
|
95
94
|
a << [build_regexp(i, map), compile_item(i.to, map, :parstr)]
|
|
96
95
|
end
|
|
@@ -102,13 +101,13 @@ class Interscript::Compiler::Javascript < Interscript::Compiler
|
|
|
102
101
|
c += "s = Interscript.parallel_regexp_gsub(s, map.cache.PRE_#{ah});\n"
|
|
103
102
|
end
|
|
104
103
|
when Interscript::Node::Rule::Sub
|
|
105
|
-
from = %
|
|
106
|
-
if r.to == :upcase
|
|
107
|
-
|
|
104
|
+
from = %("#{build_regexp(r, map).gsub("/", "\\\\/")}")
|
|
105
|
+
to = if r.to == :upcase
|
|
106
|
+
"function(a){return a.toUpperCase();}"
|
|
108
107
|
elsif r.to == :downcase
|
|
109
|
-
|
|
108
|
+
"function(a){return a.toLowerCase();}"
|
|
110
109
|
else
|
|
111
|
-
|
|
110
|
+
compile_item(r.to, map, :str)
|
|
112
111
|
end
|
|
113
112
|
c += "s = Interscript.gsub(s, #{from}, #{to});\n"
|
|
114
113
|
when Interscript::Node::Rule::Funcall
|
|
@@ -127,7 +126,7 @@ class Interscript::Compiler::Javascript < Interscript::Compiler
|
|
|
127
126
|
c
|
|
128
127
|
end
|
|
129
128
|
|
|
130
|
-
def build_regexp(r, map
|
|
129
|
+
def build_regexp(r, map = @map)
|
|
131
130
|
from = compile_item(r.from, map, :re)
|
|
132
131
|
before = compile_item(r.before, map, :re) if r.before
|
|
133
132
|
after = compile_item(r.after, map, :re) if r.after
|
|
@@ -144,7 +143,7 @@ class Interscript::Compiler::Javascript < Interscript::Compiler
|
|
|
144
143
|
re
|
|
145
144
|
end
|
|
146
145
|
|
|
147
|
-
def compile_item i, doc
|
|
146
|
+
def compile_item i, doc = @map, target = nil
|
|
148
147
|
i = i.first_string if %i[str parstr].include? target
|
|
149
148
|
i = Interscript::Node::Item.try_convert(i)
|
|
150
149
|
if target == :parstr
|
|
@@ -152,7 +151,7 @@ class Interscript::Compiler::Javascript < Interscript::Compiler
|
|
|
152
151
|
target = :par
|
|
153
152
|
end
|
|
154
153
|
|
|
155
|
-
|
|
154
|
+
case i
|
|
156
155
|
when Interscript::Node::Item::Alias
|
|
157
156
|
astr = if i.map
|
|
158
157
|
d = doc.dep_aliases[i.map].document
|
|
@@ -173,14 +172,14 @@ class Interscript::Compiler::Javascript < Interscript::Compiler
|
|
|
173
172
|
end
|
|
174
173
|
|
|
175
174
|
if target == :str
|
|
176
|
-
astr
|
|
175
|
+
astr.sub("_ALIASTYPE(", "(")
|
|
177
176
|
elsif target == :re
|
|
178
|
-
|
|
177
|
+
%("+#{astr.sub("_ALIASTYPE(", "_re(")}+")
|
|
179
178
|
elsif parstr && stdlib_alias
|
|
180
|
-
|
|
179
|
+
Interscript::Stdlib::ALIASES[i.name]
|
|
181
180
|
elsif target == :par
|
|
182
181
|
# raise NotImplementedError, "Can't use aliases in parallel mode yet"
|
|
183
|
-
|
|
182
|
+
Interscript::Stdlib::ALIASES[i.name]
|
|
184
183
|
end
|
|
185
184
|
when Interscript::Node::Item::String
|
|
186
185
|
if target == :str
|
|
@@ -195,7 +194,7 @@ class Interscript::Compiler::Javascript < Interscript::Compiler
|
|
|
195
194
|
if target == :par
|
|
196
195
|
i.children.map do |j|
|
|
197
196
|
compile_item(j, doc, target)
|
|
198
|
-
end.reduce([""]) do |j,k|
|
|
197
|
+
end.reduce([""]) do |j, k|
|
|
199
198
|
Array(j).product(Array(k)).map(&:join)
|
|
200
199
|
end
|
|
201
200
|
elsif target == :str
|
|
@@ -212,9 +211,9 @@ class Interscript::Compiler::Javascript < Interscript::Compiler
|
|
|
212
211
|
Interscript::Node::Item::MaybeSome,
|
|
213
212
|
Interscript::Node::Item::Some
|
|
214
213
|
|
|
215
|
-
resuffix = {
|
|
216
|
-
|
|
217
|
-
|
|
214
|
+
resuffix = {Interscript::Node::Item::Maybe => "?",
|
|
215
|
+
Interscript::Node::Item::Some => "+",
|
|
216
|
+
Interscript::Node::Item::MaybeSome => "*"}[i.class]
|
|
218
217
|
|
|
219
218
|
if target == :par
|
|
220
219
|
raise Interscript::SystemConversionError, "Can't use a MaybeSome in a #{target} context"
|
|
@@ -241,7 +240,7 @@ class Interscript::Compiler::Javascript < Interscript::Compiler
|
|
|
241
240
|
case i.value
|
|
242
241
|
when Array
|
|
243
242
|
data = i.data.map { |j| compile_item(j, doc, target) }
|
|
244
|
-
"(?:"+data.join("|")+")"
|
|
243
|
+
"(?:" + data.join("|") + ")"
|
|
245
244
|
when String
|
|
246
245
|
"[#{Regexp.escape(i.value)}]"
|
|
247
246
|
when Range
|
|
@@ -270,28 +269,28 @@ class Interscript::Compiler::Javascript < Interscript::Compiler
|
|
|
270
269
|
ctx = self.class.ctx
|
|
271
270
|
unless ctx
|
|
272
271
|
ctx = MiniRacer::Context.new
|
|
273
|
-
ctx.eval File.read(__dir__+"/../../../../js/test-compiler/xregexp.js")
|
|
272
|
+
ctx.eval File.read(__dir__ + "/../../../../js/test-compiler/xregexp.js")
|
|
274
273
|
# Compatibility with Safari: will come later
|
|
275
|
-
#ctx.eval File.read(__dir__+"/../../../js/xregexp-oniguruma.js")
|
|
276
|
-
ctx.eval File.read(__dir__+"/../../../../js/src/stdlib.js")
|
|
274
|
+
# ctx.eval File.read(__dir__+"/../../../js/xregexp-oniguruma.js")
|
|
275
|
+
ctx.eval File.read(__dir__ + "/../../../../js/src/stdlib.js")
|
|
277
276
|
self.class.ctx = ctx
|
|
278
277
|
end
|
|
279
|
-
#puts @code
|
|
278
|
+
# puts @code
|
|
280
279
|
ctx.eval @code
|
|
281
280
|
self.class.maps_loaded[@map.name] = true
|
|
282
281
|
end
|
|
283
282
|
end
|
|
284
283
|
|
|
285
|
-
def call(str, stage
|
|
284
|
+
def call(str, stage = :main)
|
|
286
285
|
load
|
|
287
286
|
self.class.ctx.eval "Interscript.transliterate(#{@map.name.to_json}, #{str.to_json}, #{stage.to_json})"
|
|
288
287
|
end
|
|
289
288
|
|
|
290
289
|
def self.read_debug_data
|
|
291
|
-
|
|
290
|
+
ctx.eval "globalThis.map_debug || []"
|
|
292
291
|
end
|
|
293
292
|
|
|
294
293
|
def self.reset_debug_data
|
|
295
|
-
|
|
294
|
+
ctx.eval "globalThis.map_debug = []"
|
|
296
295
|
end
|
|
297
296
|
end
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
# JSON IR compiler — emits a data-only intermediate representation consumable
|
|
6
|
+
# by non-Ruby runtimes (e.g. interscript-ts). Unlike Compiler::Javascript,
|
|
7
|
+
# which emits imperative JS that calls into a runtime, this emits a pure-data
|
|
8
|
+
# JSON document describing the AST.
|
|
9
|
+
#
|
|
10
|
+
# The shape is versioned via SCHEMA_VERSION. Runtimes should refuse to load
|
|
11
|
+
# IR with an unknown schema.
|
|
12
|
+
class Interscript::Compiler::JsonIR < Interscript::Compiler
|
|
13
|
+
SCHEMA_VERSION = 1
|
|
14
|
+
|
|
15
|
+
CompiledResult = Struct.new(:code) do
|
|
16
|
+
# JsonIR output is already JSON. The runtime treats .code as opaque
|
|
17
|
+
# text; consumers parse via JSON.parse.
|
|
18
|
+
def to_json(*)
|
|
19
|
+
code
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def compile(map, debug: false)
|
|
24
|
+
@map = map
|
|
25
|
+
@c = JSON.pretty_generate(serialise_document(map))
|
|
26
|
+
self
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def code
|
|
30
|
+
@c
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def serialise_document(doc)
|
|
36
|
+
# Merge aliases from the document AND from dependency documents so
|
|
37
|
+
# that consumers (interscript-ts) can resolve every alias reference
|
|
38
|
+
# without re-implementing the Ruby dep_aliases indirection.
|
|
39
|
+
all_aliases = {}
|
|
40
|
+
|
|
41
|
+
# Only the document's own aliases are serialised. Library and
|
|
42
|
+
# dependency aliases resolve at runtime via the alias `map:` qualifier,
|
|
43
|
+
# matching the production corpus shape.
|
|
44
|
+
doc.aliases.each do |name, defn|
|
|
45
|
+
all_aliases[name.to_s] = serialise_item(defn.data)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
{
|
|
49
|
+
schemaVersion: SCHEMA_VERSION,
|
|
50
|
+
systemCode: doc.name.to_s,
|
|
51
|
+
dependencies: doc.dependencies.map(&:full_name),
|
|
52
|
+
metadata: serialise_metadata(doc.metadata),
|
|
53
|
+
stages: serialise_stages(doc.stages),
|
|
54
|
+
aliases: all_aliases,
|
|
55
|
+
functions: {}
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def serialise_metadata(metadata)
|
|
60
|
+
return {} unless metadata
|
|
61
|
+
out = {}
|
|
62
|
+
metadata.data.each do |k, v|
|
|
63
|
+
out[k.to_s] = case v
|
|
64
|
+
when Symbol then v.to_s
|
|
65
|
+
else v
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
out
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def serialise_stages(stages)
|
|
72
|
+
# Document#stages returns Hash{name => Stage} for the document's own stages,
|
|
73
|
+
# but may also include imported stages. Iterate values and skip anything
|
|
74
|
+
# that isn't an Interscript::Node::Stage (e.g. imported Hash entries).
|
|
75
|
+
stages.values.map { |s| serialise_stage(s) if s.is_a?(Interscript::Node::Stage) }.compact
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def serialise_stage(stage)
|
|
79
|
+
{
|
|
80
|
+
kind: "stage",
|
|
81
|
+
name: stage.name.to_s,
|
|
82
|
+
rules: stage.children.map { |r| serialise_rule(r) }
|
|
83
|
+
}
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def serialise_rule(rule)
|
|
87
|
+
case rule
|
|
88
|
+
when Interscript::Node::Rule::Sub
|
|
89
|
+
serialise_sub_rule(rule)
|
|
90
|
+
when Interscript::Node::Rule::Run
|
|
91
|
+
serialise_run_rule(rule)
|
|
92
|
+
when Interscript::Node::Rule::Funcall
|
|
93
|
+
serialise_funcall_rule(rule)
|
|
94
|
+
when Interscript::Node::Group::Parallel
|
|
95
|
+
# Parallel rule groups contain sub-rules that are applied simultaneously.
|
|
96
|
+
# In IR, we emit them as a marker rule so the runtime can decide.
|
|
97
|
+
{
|
|
98
|
+
kind: "parallel",
|
|
99
|
+
rules: rule.children.map { |r| serialise_rule(r) }
|
|
100
|
+
}
|
|
101
|
+
when Interscript::Node::Group::Sequential
|
|
102
|
+
{
|
|
103
|
+
kind: "sequential",
|
|
104
|
+
rules: rule.children.map { |r| serialise_rule(r) }
|
|
105
|
+
}
|
|
106
|
+
else
|
|
107
|
+
raise Interscript::MapLogicError, "Cannot serialise rule of type #{rule.class}"
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def serialise_sub_rule(rule)
|
|
112
|
+
out = {kind: "sub"}
|
|
113
|
+
out[:from] = serialise_item(rule.from) if rule.from
|
|
114
|
+
out[:to] = serialise_to(rule.to)
|
|
115
|
+
out[:before] = serialise_item(rule.before) if rule.before
|
|
116
|
+
out[:after] = serialise_item(rule.after) if rule.after
|
|
117
|
+
out[:notBefore] = serialise_item(rule.not_before) if rule.not_before
|
|
118
|
+
out[:notAfter] = serialise_item(rule.not_after) if rule.not_after
|
|
119
|
+
out[:priority] = rule.priority if rule.priority
|
|
120
|
+
out
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def serialise_run_rule(rule)
|
|
124
|
+
stage = rule.stage
|
|
125
|
+
doc_name = stage.map
|
|
126
|
+
if doc_name && @map.respond_to?(:dep_aliases) && @map.dep_aliases[doc_name.to_sym]
|
|
127
|
+
resolved = @map.dep_aliases[doc_name.to_sym].document
|
|
128
|
+
doc_name = resolved.name.to_s if resolved.respond_to?(:name)
|
|
129
|
+
end
|
|
130
|
+
{
|
|
131
|
+
kind: "run",
|
|
132
|
+
stage: stage.name.to_s,
|
|
133
|
+
docName: doc_name&.to_s
|
|
134
|
+
}
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def serialise_funcall_rule(rule)
|
|
138
|
+
{
|
|
139
|
+
kind: "funcall",
|
|
140
|
+
name: rule.name.to_s,
|
|
141
|
+
kwargs: symbolise_keys(rule.kwargs)
|
|
142
|
+
}
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def serialise_to(to)
|
|
146
|
+
case to
|
|
147
|
+
when Symbol
|
|
148
|
+
{kind: "funcall_inline", name: to.to_s}
|
|
149
|
+
else
|
|
150
|
+
serialise_item(to)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def serialise_item(item)
|
|
155
|
+
return {kind: "any", of: item.map { |i| i.is_a?(String) ? {kind: "string", value: i} : serialise_item(i) }} if item.is_a?(::Array)
|
|
156
|
+
case item
|
|
157
|
+
when Interscript::Node::Item::String
|
|
158
|
+
{kind: "string", value: item.data}
|
|
159
|
+
when Interscript::Node::Item::CaptureGroup
|
|
160
|
+
{kind: "capture_group", data: serialise_item(item.data)}
|
|
161
|
+
when Interscript::Node::Item::CaptureRef
|
|
162
|
+
{kind: "capture_ref", id: item.id}
|
|
163
|
+
when Interscript::Node::Item::Alias
|
|
164
|
+
out = {kind: "alias", name: item.name.to_s}
|
|
165
|
+
out[:map] = item.map if item.map
|
|
166
|
+
out
|
|
167
|
+
when Interscript::Node::Item::Any
|
|
168
|
+
# Any with a String payload becomes a character class in Ruby's
|
|
169
|
+
# regex compilation. Range payloads become `[first-last]`. Both
|
|
170
|
+
# must survive IR serialisation as char-class form, NOT expanded
|
|
171
|
+
# into alternatives — Ruby's String#succ expansion of "a".."ᖵ"
|
|
172
|
+
# produces nonsense like "zzz" and misses most of the BMP.
|
|
173
|
+
case item.value
|
|
174
|
+
when ::Range
|
|
175
|
+
{kind: "any_char_class", range: [item.value.first, item.value.last]}
|
|
176
|
+
when ::String
|
|
177
|
+
{kind: "any_char_class", chars: item.value.chars}
|
|
178
|
+
else
|
|
179
|
+
data = item.data || []
|
|
180
|
+
{kind: "any", of: data.map { |i| serialise_item(i) }}
|
|
181
|
+
end
|
|
182
|
+
when Interscript::Node::Item::Group
|
|
183
|
+
{kind: "group", items: item.children.map { |i| serialise_item(i) }}
|
|
184
|
+
when Interscript::Node::Item::Repeat
|
|
185
|
+
{kind: "repeat", item: serialise_item(item.data), min: 0, max: nil}
|
|
186
|
+
when Interscript::Node::Item::Stage
|
|
187
|
+
{kind: "stage_ref", name: item.name.to_s}
|
|
188
|
+
when nil
|
|
189
|
+
nil
|
|
190
|
+
else
|
|
191
|
+
raise Interscript::MapLogicError, "Cannot serialise item of type #{item.class}"
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def capture_index(_item)
|
|
196
|
+
# CaptureGroup index is determined by position in pattern compilation.
|
|
197
|
+
# Runtimes should treat as a placeholder; the actual index is computed
|
|
198
|
+
# during pattern compilation based on capture-group ordering.
|
|
199
|
+
0
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def serialise_aliases(aliases)
|
|
203
|
+
out = {}
|
|
204
|
+
aliases.each do |name, defn|
|
|
205
|
+
out[name.to_s] = serialise_item(defn.data)
|
|
206
|
+
end
|
|
207
|
+
out
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def symbolise_keys(hash)
|
|
211
|
+
return {} if hash.nil?
|
|
212
|
+
hash.transform_keys(&:to_s)
|
|
213
|
+
end
|
|
214
|
+
end
|