expressir 2.4.31-aarch64-linux → 2.4.36-aarch64-linux
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/.github/workflows/conformance.yml +34 -0
- data/.gitignore +3 -0
- data/Gemfile +1 -1
- data/TODO.eengine/00-overview.md +39 -0
- data/TODO.eengine/01-resolution-diagnostics.md +30 -0
- data/TODO.eengine/02-check-catalog-completion.md +53 -0
- data/TODO.eengine/03-entity-computations.md +22 -0
- data/TODO.eengine/04-shtolo-rule-audit.md +32 -0
- data/TODO.eengine/05-shtolo-longform-flatten.md +12 -0
- data/TODO.eengine/06-population-p21.md +34 -0
- data/TODO.eengine/07-schema-compare-patch.md +25 -0
- data/TODO.eengine/08-official-corpus-gate.md +7 -0
- data/TODO.eengine/09-mim-mapping-parser.md +9 -0
- data/TODO.parity-ee/00-overview.md +1 -1
- data/TODO.sota/00-overview.md +57 -0
- data/TODO.sota/01-type-checking.md +115 -0
- data/TODO.sota/02-evaluator.md +86 -0
- data/TODO.sota/03-conformance.md +53 -0
- data/TODO.sota/04-lsp.md +70 -0
- data/TODO.sota/05-interop.md +55 -0
- data/TODO.sota/06-dialects.md +57 -0
- data/TODO.sota/07-reference-artifacts.md +55 -0
- data/TODO.suma-improvements/07-part28-xml.md +10 -13
- data/docs/_guides/interop/index.adoc +25 -0
- data/docs/_guides/interop/json-schema.adoc +88 -0
- data/docs/_guides/interop/owl-rdf.adoc +87 -0
- data/docs/_guides/reference/checker-notes.adoc +55 -0
- data/docs/_guides/reference/checker.adoc +36 -0
- data/docs/_guides/reference/evaluator.adoc +40 -0
- data/docs/_guides/reference/grammar-crosswalk.adoc +299 -0
- data/docs/_guides/reference/index.adoc +22 -0
- data/docs/_guides/reference/lsp.adoc +41 -0
- data/docs/_guides/reference/p21.adoc +30 -0
- data/docs/_guides/reference/shtolo.adoc +36 -0
- data/exe/expressir-lsp +6 -0
- data/expressir.gemspec +2 -2
- data/lib/expressir/3.2/expressir_core.so +0 -0
- data/lib/expressir/3.3/expressir_core.so +0 -0
- data/lib/expressir/3.4/expressir_core.so +0 -0
- data/lib/expressir/4.0/expressir_core.so +0 -0
- data/lib/expressir/cli.rb +25 -0
- data/lib/expressir/commands/check.rb +3 -1
- data/lib/expressir/commands/export_json_schema.rb +29 -0
- data/lib/expressir/commands/export_owl.rb +26 -0
- data/lib/expressir/commands/smrl_xml_index.rb +25 -0
- data/lib/expressir/commands/validate.rb +3 -0
- data/lib/expressir/commands.rb +3 -0
- data/lib/expressir/conformance/trend.rb +100 -0
- data/lib/expressir/conformance.rb +8 -0
- data/lib/expressir/eval/environment.rb +83 -0
- data/lib/expressir/eval/expression.rb +610 -0
- data/lib/expressir/eval/interpreter.rb +316 -0
- data/lib/expressir/eval/rules.rb +88 -0
- data/lib/expressir/eval/values.rb +74 -0
- data/lib/expressir/eval.rb +17 -0
- data/lib/expressir/express/builder.rb +17 -5
- data/lib/expressir/express/builders/entity_decl_builder.rb +17 -5
- data/lib/expressir/express/builders/expression_builder.rb +9 -1
- data/lib/expressir/express/checker.rb +970 -5
- data/lib/expressir/express/dialect.rb +44 -0
- data/lib/expressir/express/formatters/declarations_formatter.rb +21 -14
- data/lib/expressir/express/formatters/expressions_formatter.rb +4 -1
- data/lib/expressir/express/parser.rb +9 -4
- data/lib/expressir/express/pretty_formatter.rb +9 -14
- data/lib/expressir/express/schema_compare.rb +194 -0
- data/lib/expressir/express/shtolo.rb +194 -63
- data/lib/expressir/express.rb +3 -0
- data/lib/expressir/interop/json_schema.rb +195 -0
- data/lib/expressir/interop/owl.rb +216 -0
- data/lib/expressir/interop.rb +13 -0
- data/lib/expressir/lsp/document.rb +226 -0
- data/lib/expressir/lsp/server.rb +184 -0
- data/lib/expressir/lsp/workspace.rb +402 -0
- data/lib/expressir/lsp.rb +11 -0
- data/lib/expressir/model/declarations/entity.rb +132 -0
- data/lib/expressir/model/declarations/schema.rb +37 -6
- data/lib/expressir/p21/builder.rb +92 -0
- data/lib/expressir/p21/grammar.rb +107 -0
- data/lib/expressir/p21/parser.rb +16 -0
- data/lib/expressir/p21/population.rb +35 -0
- data/lib/expressir/p21/validator.rb +213 -0
- data/lib/expressir/p21.rb +17 -0
- data/lib/expressir/reference/grammar_crosswalk.rb +122 -0
- data/lib/expressir/reference/grammar_crosswalk.yml +800 -0
- data/lib/expressir/reference/note_catalog.rb +54 -0
- data/lib/expressir/reference.rb +10 -0
- data/lib/expressir/version.rb +1 -1
- data/lib/expressir.rb +5 -0
- data/lib/tasks/conformance.rake +27 -0
- data/lib/tasks/reference.rake +25 -0
- metadata +68 -4
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module Expressir
|
|
6
|
+
module Conformance
|
|
7
|
+
# Trended property metrics over a corpus slice: parse rate and
|
|
8
|
+
# format idempotence rate are fractions; the diagnostic rate is the
|
|
9
|
+
# number of Checker notes per parsed file. Per-note-id counts make
|
|
10
|
+
# the report actionable. Published by the nightly conformance
|
|
11
|
+
# workflow as a JSON artifact so the numbers can be trended.
|
|
12
|
+
class Trend
|
|
13
|
+
def self.measure(files)
|
|
14
|
+
report = {
|
|
15
|
+
"files" => files.size,
|
|
16
|
+
"parsed" => 0,
|
|
17
|
+
"parse_failed" => 0,
|
|
18
|
+
"measurement_failed" => 0,
|
|
19
|
+
"idempotent" => 0,
|
|
20
|
+
"not_idempotent" => 0,
|
|
21
|
+
"notes" => 0,
|
|
22
|
+
"errors" => 0,
|
|
23
|
+
"warnings" => 0,
|
|
24
|
+
"note_ids" => {},
|
|
25
|
+
}
|
|
26
|
+
files.each do |path|
|
|
27
|
+
measure_file(path, report)
|
|
28
|
+
end
|
|
29
|
+
report.merge!(
|
|
30
|
+
"parse_rate" => rate(report["parsed"], report["files"]),
|
|
31
|
+
"idempotence_rate" => rate(report["idempotent"], report["parsed"]),
|
|
32
|
+
"diagnostic_rate" => rate(report["notes"], report["parsed"]),
|
|
33
|
+
)
|
|
34
|
+
report
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.run(files, output:)
|
|
38
|
+
report = measure(files)
|
|
39
|
+
File.write(output, "#{JSON.pretty_generate(report)}\n")
|
|
40
|
+
report
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.measure_file(path, report)
|
|
44
|
+
repository = parse_file(path)
|
|
45
|
+
unless repository
|
|
46
|
+
report["parse_failed"] += 1
|
|
47
|
+
return
|
|
48
|
+
end
|
|
49
|
+
report["parsed"] += 1
|
|
50
|
+
measure_properties(repository, report)
|
|
51
|
+
end
|
|
52
|
+
private_class_method :measure_file
|
|
53
|
+
|
|
54
|
+
def self.parse_file(path)
|
|
55
|
+
Expressir::Express::Parser.from_exp(File.read(path))
|
|
56
|
+
rescue StandardError
|
|
57
|
+
nil
|
|
58
|
+
end
|
|
59
|
+
private_class_method :parse_file
|
|
60
|
+
|
|
61
|
+
def self.measure_properties(repository, report)
|
|
62
|
+
schema = Array(repository.schemas).first
|
|
63
|
+
if schema && idempotent?(schema)
|
|
64
|
+
report["idempotent"] += 1
|
|
65
|
+
else
|
|
66
|
+
report["not_idempotent"] += 1
|
|
67
|
+
end
|
|
68
|
+
notes = Expressir::Express::Checker.new(
|
|
69
|
+
Expressir::Model::Repository.new(files: [repository]),
|
|
70
|
+
).check.notes
|
|
71
|
+
report["notes"] += notes.size
|
|
72
|
+
notes.each do |note|
|
|
73
|
+
report[note.severity == :error ? "errors" : "warnings"] += 1
|
|
74
|
+
report["note_ids"][note.id.to_s] =
|
|
75
|
+
report["note_ids"].fetch(note.id.to_s, 0) + 1
|
|
76
|
+
end
|
|
77
|
+
rescue StandardError
|
|
78
|
+
report["measurement_failed"] += 1
|
|
79
|
+
end
|
|
80
|
+
private_class_method :measure_properties
|
|
81
|
+
|
|
82
|
+
def self.idempotent?(schema)
|
|
83
|
+
once = Expressir::Express::Formatter.format(schema)
|
|
84
|
+
reparsed = Expressir::Express::Parser.from_exp(once)
|
|
85
|
+
twice = Expressir::Express::Formatter.format(reparsed.schemas.first)
|
|
86
|
+
once == twice
|
|
87
|
+
rescue StandardError
|
|
88
|
+
false
|
|
89
|
+
end
|
|
90
|
+
private_class_method :idempotent?
|
|
91
|
+
|
|
92
|
+
def self.rate(numerator, denominator)
|
|
93
|
+
return 0.0 if denominator.zero?
|
|
94
|
+
|
|
95
|
+
(numerator.to_f / denominator).round(4)
|
|
96
|
+
end
|
|
97
|
+
private_class_method :rate
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Eval
|
|
5
|
+
# Lexical scope chain: a name resolves to a value through the
|
|
6
|
+
# innermost scope that declares it. The schema provides type
|
|
7
|
+
# context; the population (step 3) provides instances for the
|
|
8
|
+
# instance-aware builtins.
|
|
9
|
+
class Environment
|
|
10
|
+
attr_reader :schema, :population
|
|
11
|
+
|
|
12
|
+
def initialize(schema:, population: nil, frames: [{}])
|
|
13
|
+
@schema = schema
|
|
14
|
+
@population = population
|
|
15
|
+
@frames = frames
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def push(frame)
|
|
19
|
+
Environment.new(schema: @schema, population: @population,
|
|
20
|
+
frames: @frames + [frame])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def define(name, value)
|
|
24
|
+
frame = @frames.last.dup
|
|
25
|
+
frame[name.safe_downcase] = value
|
|
26
|
+
Environment.new(schema: @schema, population: @population,
|
|
27
|
+
frames: @frames[0..-2] + [frame])
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def lookup(name)
|
|
31
|
+
key = name.safe_downcase
|
|
32
|
+
@frames.reverse_each do |frame|
|
|
33
|
+
return frame[key] if frame.key?(key)
|
|
34
|
+
end
|
|
35
|
+
nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def bound?(name)
|
|
39
|
+
!lookup(name).nil? || @frames.any? { |f| f.key?(name.safe_downcase) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def interpreter
|
|
43
|
+
@interpreter ||= Interpreter.new(schema: @schema,
|
|
44
|
+
population: @population)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Part 21 attribute slots for an entity: inherited explicit
|
|
48
|
+
# attributes (supertype closure order) then the entity's own —
|
|
49
|
+
# the same order the P21 validator maps values by.
|
|
50
|
+
def slots_for(entity)
|
|
51
|
+
@slots ||= {}
|
|
52
|
+
@slots[entity] ||= begin
|
|
53
|
+
inherited = entity.supertype_closure.flat_map do |supertype|
|
|
54
|
+
explicit_attributes(supertype)
|
|
55
|
+
end
|
|
56
|
+
(inherited + explicit_attributes(entity)).each_with_index
|
|
57
|
+
.to_h do |attribute, index|
|
|
58
|
+
[attribute.id&.safe_downcase, index]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def explicit_attributes(entity)
|
|
64
|
+
Array(entity.attributes)
|
|
65
|
+
.select { |a| a.instance_of?(Model::Declarations::Attribute) }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def entity_for_keyword(keyword)
|
|
69
|
+
Array(@schema&.entities).find do |entity|
|
|
70
|
+
entity.id&.safe_downcase == keyword&.safe_downcase
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def instance_for(reference)
|
|
75
|
+
return nil unless @population && reference.is_a?(String)
|
|
76
|
+
return nil unless reference.start_with?("#")
|
|
77
|
+
|
|
78
|
+
record = @population.instances[reference]
|
|
79
|
+
record && Values::Instance.new(id: reference[1..], record: record)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|