expressir 2.3.7 → 2.4.1
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/TODO.bugs/01-stale-transformer-autoload.md +39 -0
- data/TODO.bugs/02-parser-class-instance-vars.md +36 -0
- data/TODO.bugs/03-builder-mutable-state.md +43 -0
- data/TODO.bugs/04-formatter-public-send-dispatch.md +53 -0
- data/TODO.bugs/05-anonymous-formatter-subclass.md +45 -0
- data/TODO.bugs/06-collection-registry-single-source.md +53 -0
- data/TODO.bugs/07-require-relative-cleanup.md +42 -0
- data/TODO.bugs/08-require-expressir-in-commands.md +34 -0
- data/TODO.bugs/09-parser-split.md +53 -0
- data/TODO.bugs/10-to-s-override.md +42 -0
- data/TODO.bugs/11-parser-class-variables.md +39 -0
- data/TODO.bugs/12-marker-modules-vs-registry.md +64 -0
- data/TODO.bugs/13-string-literal-scanner-limitation.md +52 -0
- data/TODO.bugs/14-model-formatting-leak.md +30 -0
- data/TODO.bugs/15-expression-children-macro.md +27 -0
- data/TODO.bugs/16-pretty-formatter-duplication.md +28 -0
- data/TODO.bugs/17-snake-case-cache-mutable-constant.md +28 -0
- data/TODO.bugs/18-const-get-private-constants.md +30 -0
- data/TODO.bugs/19-format-methods-public.md +22 -0
- data/TODO.bugs/20-coverage-nested-entities-dedup.md +20 -0
- data/TODO.bugs/21-operator-tokens-secondary-dispatch.md +21 -0
- data/TODO.bugs/22-builder-fast-path-wrappers.md +32 -0
- data/TODO.bugs/23-coverage-inverse-maps.md +21 -0
- data/TODO.bugs/24-streaming-builder-complexity.md +19 -0
- data/TODO.bugs/25-debug-puts-in-production.md +21 -0
- data/TODO.bugs/26-generic-entity-children-misplaced.md +21 -0
- data/TODO.bugs/27-package-build-god-method.md +19 -0
- data/TODO.bugs/28-package-god-class.md +30 -0
- data/TODO.bugs/29-validate-ascii-god-class.md +24 -0
- data/TODO.bugs/30-unicode-map-extraction.md +19 -0
- data/TODO.bugs/README.md +43 -0
- data/docs/_tutorials/formatting-schemas.adoc +89 -0
- data/docs/_tutorials/index.adoc +10 -0
- data/docs/lychee.toml +3 -0
- data/expressir.gemspec +4 -2
- data/lib/expressir/commands/changes_import_eengine.rb +0 -6
- data/lib/expressir/commands/changes_validate.rb +0 -2
- data/lib/expressir/commands/clean.rb +1 -1
- data/lib/expressir/commands/file_violations.rb +70 -0
- data/lib/expressir/commands/format.rb +1 -1
- data/lib/expressir/commands/non_ascii_character.rb +49 -0
- data/lib/expressir/commands/non_ascii_violation_collection.rb +301 -0
- data/lib/expressir/commands/package.rb +138 -185
- data/lib/expressir/commands/validate_ascii.rb +0 -510
- data/lib/expressir/commands/version.rb +1 -1
- data/lib/expressir/commands.rb +3 -0
- data/lib/expressir/coverage.rb +49 -117
- data/lib/expressir/express/builder.rb +74 -86
- data/lib/expressir/express/builder_context.rb +22 -0
- data/lib/expressir/express/builders/expression_builder.rb +16 -16
- data/lib/expressir/express/cache.rb +35 -8
- data/lib/expressir/express/error.rb +7 -0
- data/lib/expressir/express/formatter.rb +33 -18
- data/lib/expressir/express/formatters/declarations_formatter.rb +24 -2
- data/lib/expressir/express/formatters/remark_formatter.rb +75 -2
- data/lib/expressir/express/formatters/statements_formatter.rb +20 -3
- data/lib/expressir/express/grammar/parser.rb +705 -0
- data/lib/expressir/express/grammar.rb +11 -0
- data/lib/expressir/express/line_map.rb +48 -0
- data/lib/expressir/express/node_position_index.rb +215 -0
- data/lib/expressir/express/parser.rb +114 -884
- data/lib/expressir/express/pretty_formatter.rb +23 -5
- data/lib/expressir/express/remark_attacher.rb +483 -669
- data/lib/expressir/express/remark_scanner.rb +245 -0
- data/lib/expressir/express/schema_block_scanner.rb +136 -0
- data/lib/expressir/express/schema_source_formatter.rb +15 -0
- data/lib/expressir/express/scope_resolver.rb +194 -0
- data/lib/expressir/express/source_formatter.rb +15 -0
- data/lib/expressir/express/streaming_builder.rb +147 -176
- data/lib/expressir/express.rb +10 -6
- data/lib/expressir/model/concerns.rb +3 -0
- data/lib/expressir/model/data_types/generic_entity.rb +6 -6
- data/lib/expressir/model/declarations/entity.rb +5 -0
- data/lib/expressir/model/declarations/function.rb +5 -0
- data/lib/expressir/model/declarations/procedure.rb +5 -0
- data/lib/expressir/model/declarations/rule.rb +6 -0
- data/lib/expressir/model/declarations/schema.rb +21 -8
- data/lib/expressir/model/declarations/type.rb +3 -0
- data/lib/expressir/model/exp_file.rb +2 -0
- data/lib/expressir/model/expressions/aggregate_initializer.rb +1 -0
- data/lib/expressir/model/expressions/aggregate_initializer_item.rb +1 -0
- data/lib/expressir/model/expressions/binary_expression.rb +1 -0
- data/lib/expressir/model/expressions/entity_constructor.rb +1 -0
- data/lib/expressir/model/expressions/function_call.rb +1 -0
- data/lib/expressir/model/expressions/interval.rb +1 -0
- data/lib/expressir/model/expressions/query_expression.rb +2 -0
- data/lib/expressir/model/expressions/unary_expression.rb +1 -0
- data/lib/expressir/model/model_element.rb +128 -14
- data/lib/expressir/model/remark_format.rb +17 -0
- data/lib/expressir/model/remark_info.rb +31 -3
- data/lib/expressir/model/remark_placement.rb +29 -0
- data/lib/expressir/model/statements/alias.rb +2 -0
- data/lib/expressir/model/statements/assignment.rb +4 -0
- data/lib/expressir/model/statements/case.rb +21 -0
- data/lib/expressir/model/statements/case_action.rb +1 -0
- data/lib/expressir/model/statements/compound.rb +4 -0
- data/lib/expressir/model/statements/escape.rb +3 -0
- data/lib/expressir/model/statements/if.rb +5 -0
- data/lib/expressir/model/statements/null.rb +3 -0
- data/lib/expressir/model/statements/procedure_call.rb +3 -0
- data/lib/expressir/model/statements/repeat.rb +3 -0
- data/lib/expressir/model/statements/return.rb +3 -0
- data/lib/expressir/model/statements/skip.rb +3 -0
- data/lib/expressir/model.rb +12 -3
- data/lib/expressir/package/builder.rb +2 -2
- data/lib/expressir/version.rb +6 -1
- data/lib/expressir.rb +38 -3
- metadata +65 -5
- data/lib/expressir/express/transformer/remark_handling.rb +0 -194
|
@@ -4,6 +4,63 @@ module Expressir
|
|
|
4
4
|
module Model
|
|
5
5
|
# Base model element
|
|
6
6
|
class ModelElement < Lutaml::Model::Serializable
|
|
7
|
+
# ---- Collection-attributes macro (TODO.bugs/12) ----
|
|
8
|
+
#
|
|
9
|
+
# Each model class declares which attributes hold child collections
|
|
10
|
+
# via `collection_attributes :foo, :bar, ...`. The declarations
|
|
11
|
+
# auto-register into the global registry, eliminating the need for
|
|
12
|
+
# a hand-maintained hash in NodePositionIndex.
|
|
13
|
+
|
|
14
|
+
# Returns the global registry: class → array of attr symbols.
|
|
15
|
+
def self.collection_registry
|
|
16
|
+
@collection_registry ||= {}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Returns the collection attributes declared on this class (empty
|
|
20
|
+
# if none declared).
|
|
21
|
+
def self.collection_attributes_list
|
|
22
|
+
@collection_attributes || []
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Declare which attributes on this model class hold child collections
|
|
26
|
+
# that should be traversed by tree-walkers (NodePositionIndex,
|
|
27
|
+
# RemarkAttacher, ScopeResolver). Also registers this class in the
|
|
28
|
+
# global collection registry so NodePositionIndex can derive its
|
|
29
|
+
# COLLECTION_REGISTRY from the model instead of duplicating it.
|
|
30
|
+
def self.collection_attributes(*attrs)
|
|
31
|
+
@collection_attributes = attrs.freeze
|
|
32
|
+
ModelElement.collection_registry[self] = attrs
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# ---- End collection-attributes macro ----
|
|
36
|
+
|
|
37
|
+
# ---- Child-attributes macro (TODO.bugs/15) ----
|
|
38
|
+
#
|
|
39
|
+
# Similar to collection_attributes, but for single-value ModelElement
|
|
40
|
+
# children (non-collection attributes that hold a ModelElement, like
|
|
41
|
+
# BinaryExpression#operand1). Used by RemarkAttacher for query
|
|
42
|
+
# traversal so the EXPRESSION_CHILDREN hash lives on the model.
|
|
43
|
+
|
|
44
|
+
# Returns the global registry: class → array of attr symbols.
|
|
45
|
+
def self.child_attributes_registry
|
|
46
|
+
@child_attributes_registry ||= {}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Returns the child attributes declared on this class (empty if none).
|
|
50
|
+
def self.child_attributes_list
|
|
51
|
+
@child_attributes || []
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Declare which attributes on this model class hold single-value
|
|
55
|
+
# ModelElement children that should be traversed by the remark
|
|
56
|
+
# attacher's query-search.
|
|
57
|
+
def self.child_attributes(*attrs)
|
|
58
|
+
@child_attributes = attrs.freeze
|
|
59
|
+
ModelElement.child_attributes_registry[self] = attrs
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# ---- End child-attributes macro ----
|
|
63
|
+
|
|
7
64
|
SKIP_ATTRIBUTES = %i[parent _class].freeze
|
|
8
65
|
# :parent is a special attribute that is used to store the parent of the current element
|
|
9
66
|
# It is not a real attribute
|
|
@@ -98,10 +155,7 @@ module Expressir
|
|
|
98
155
|
end
|
|
99
156
|
|
|
100
157
|
def source
|
|
101
|
-
|
|
102
|
-
include Expressir::Express::HyperlinkFormatter
|
|
103
|
-
end
|
|
104
|
-
formatter.format(self)
|
|
158
|
+
Expressir::Express::SourceFormatter.format(self)
|
|
105
159
|
end
|
|
106
160
|
|
|
107
161
|
# @param [Hash] options
|
|
@@ -149,16 +203,9 @@ module Expressir
|
|
|
149
203
|
current_scope = self
|
|
150
204
|
target_node = nil
|
|
151
205
|
loop do
|
|
152
|
-
|
|
153
|
-
current_node = current_scope
|
|
154
|
-
path_parts.each do |current_path|
|
|
155
|
-
current_node = current_node.children_by_id[current_path]
|
|
156
|
-
break unless current_node
|
|
157
|
-
end
|
|
158
|
-
target_node = current_node
|
|
206
|
+
target_node = resolve_path_in_scope(current_scope, path_parts)
|
|
159
207
|
break if target_node
|
|
160
208
|
|
|
161
|
-
# retry search in parent scope
|
|
162
209
|
current_scope = current_scope.parent
|
|
163
210
|
break unless current_scope
|
|
164
211
|
end
|
|
@@ -170,6 +217,62 @@ module Expressir
|
|
|
170
217
|
target_node
|
|
171
218
|
end
|
|
172
219
|
|
|
220
|
+
# Walk `path_parts` through `scope`, resolving one part at a time.
|
|
221
|
+
# Handles `SELF\<supertype>.<attr>` qualifiers inline: when a part
|
|
222
|
+
# starts with `self\`, the next part is matched against the scope's
|
|
223
|
+
# redeclared attributes and disambiguated by the supertype name
|
|
224
|
+
# (issues #130 and #267).
|
|
225
|
+
def resolve_path_in_scope(scope, path_parts)
|
|
226
|
+
current_node = scope
|
|
227
|
+
pending_supertype = nil
|
|
228
|
+
|
|
229
|
+
path_parts.each do |current_path|
|
|
230
|
+
if current_path.start_with?("self\\")
|
|
231
|
+
pending_supertype = current_path.split("\\", 2).last
|
|
232
|
+
next
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
if pending_supertype
|
|
236
|
+
child = find_redeclared_by_supertype(current_node, current_path,
|
|
237
|
+
pending_supertype)
|
|
238
|
+
return nil unless child
|
|
239
|
+
|
|
240
|
+
current_node = child
|
|
241
|
+
pending_supertype = nil
|
|
242
|
+
else
|
|
243
|
+
current_node = current_node.children_by_id[current_path]
|
|
244
|
+
return nil unless current_node
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# If the path ended on a SELF qualifier (no attr name followed),
|
|
249
|
+
# resolution is incomplete.
|
|
250
|
+
pending_supertype ? nil : current_node
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Find a redeclared attribute among `scope`'s children whose id matches
|
|
254
|
+
# `attr_name` and whose supertype_attribute references the given
|
|
255
|
+
# `supertype` name. Returns nil if `scope` is not an Attribute container
|
|
256
|
+
# or no such child exists.
|
|
257
|
+
def find_redeclared_by_supertype(scope, attr_name, supertype)
|
|
258
|
+
attrs = scope.respond_to?(:attributes) ? scope.attributes : nil
|
|
259
|
+
return nil unless attrs
|
|
260
|
+
|
|
261
|
+
attrs.find do |child|
|
|
262
|
+
next false unless child.is_a?(Model::Declarations::Attribute)
|
|
263
|
+
next false unless child.id&.safe_downcase == attr_name
|
|
264
|
+
|
|
265
|
+
supertype_attr = child.supertype_attribute
|
|
266
|
+
next false unless supertype_attr.respond_to?(:ref)
|
|
267
|
+
|
|
268
|
+
group_ref = supertype_attr.ref
|
|
269
|
+
next false unless group_ref.respond_to?(:entity)
|
|
270
|
+
|
|
271
|
+
entity_ref = group_ref.entity
|
|
272
|
+
entity_ref&.id&.safe_downcase == supertype
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
173
276
|
# @return [Array<Declaration>]
|
|
174
277
|
def children
|
|
175
278
|
[]
|
|
@@ -188,12 +291,23 @@ module Expressir
|
|
|
188
291
|
nil
|
|
189
292
|
end
|
|
190
293
|
|
|
191
|
-
|
|
294
|
+
# Format this element back into EXPRESS source text.
|
|
295
|
+
# @param no_remarks [Boolean] omit remarks from the output
|
|
296
|
+
# @param formatter [Express::Formatter, nil] use a specific formatter
|
|
297
|
+
# @return [String]
|
|
298
|
+
def format(no_remarks: false, formatter: nil)
|
|
192
299
|
f = formatter || Express::Formatter.new(no_remarks: no_remarks)
|
|
193
|
-
f.no_remarks = no_remarks
|
|
194
300
|
f.format(self)
|
|
195
301
|
end
|
|
196
302
|
|
|
303
|
+
# No-arg delegator so string interpolation ("#{element}") still
|
|
304
|
+
# produces EXPRESS source rather than the default Object#to_s.
|
|
305
|
+
# Remark-free output is requested explicitly through
|
|
306
|
+
# #format(no_remarks: true); it is not this method's default.
|
|
307
|
+
def to_s
|
|
308
|
+
format
|
|
309
|
+
end
|
|
310
|
+
|
|
197
311
|
# Add a remark to this element
|
|
198
312
|
# @param remark_info [RemarkInfo] Remark to add
|
|
199
313
|
def add_remark(remark_info)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Model
|
|
5
|
+
# Single source of truth for the remark-format vocabulary.
|
|
6
|
+
#
|
|
7
|
+
# Reference: ISO 10303-11 §7.1.6 defines exactly two remark forms:
|
|
8
|
+
# the tail remark (`-- ... \n`) and the embedded remark (`(* ... *)`).
|
|
9
|
+
# Both the model (RemarkInfo) and the express-side scanner/attacher
|
|
10
|
+
# reference these constants instead of bare string literals, so a
|
|
11
|
+
# rename or extension lands in one place.
|
|
12
|
+
module RemarkFormat
|
|
13
|
+
TAIL = "tail"
|
|
14
|
+
EMBEDDED = "embedded"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -5,19 +5,24 @@ module Expressir
|
|
|
5
5
|
# Can include optional tags for associating remarks with specific items
|
|
6
6
|
class RemarkInfo < Lutaml::Model::Serializable
|
|
7
7
|
attribute :text, :string
|
|
8
|
-
attribute :format, :string, default:
|
|
8
|
+
attribute :format, :string, default: RemarkFormat::EMBEDDED
|
|
9
9
|
attribute :tag, :string # optional remark tag like "entity.attr"
|
|
10
|
+
# See RemarkPlacement. nil = legacy placement.
|
|
11
|
+
attribute :placement, :string
|
|
12
|
+
# For TRAILING remarks, which body of the owner they close.
|
|
13
|
+
attribute :region, :string
|
|
14
|
+
attribute :source_offset, :integer # byte offset in source text
|
|
10
15
|
|
|
11
16
|
# Check if this is a tail remark
|
|
12
17
|
# @return [Boolean] True if format is 'tail'
|
|
13
18
|
def tail?
|
|
14
|
-
format ==
|
|
19
|
+
format == RemarkFormat::TAIL
|
|
15
20
|
end
|
|
16
21
|
|
|
17
22
|
# Check if this is an embedded remark
|
|
18
23
|
# @return [Boolean] True if format is 'embedded'
|
|
19
24
|
def embedded?
|
|
20
|
-
format ==
|
|
25
|
+
format == RemarkFormat::EMBEDDED
|
|
21
26
|
end
|
|
22
27
|
|
|
23
28
|
# Check if this remark has a tag
|
|
@@ -26,11 +31,32 @@ module Expressir
|
|
|
26
31
|
!tag.nil? && !tag.empty?
|
|
27
32
|
end
|
|
28
33
|
|
|
34
|
+
# Check if this remark should be emitted above its owning statement
|
|
35
|
+
# @return [Boolean] True if placement is 'leading'
|
|
36
|
+
def leading?
|
|
37
|
+
placement == RemarkPlacement::LEADING
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Check if this remark trails its owning statement on the same line
|
|
41
|
+
# @return [Boolean] True if placement is 'inline'
|
|
42
|
+
def inline?
|
|
43
|
+
placement == RemarkPlacement::INLINE
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Check if this remark closes the given body of its owning node
|
|
47
|
+
# @param name [Symbol, String] region attribute name
|
|
48
|
+
# @return [Boolean]
|
|
49
|
+
def trailing_region?(name)
|
|
50
|
+
placement == RemarkPlacement::TRAILING && region == name.to_s
|
|
51
|
+
end
|
|
52
|
+
|
|
29
53
|
# YAML serialization
|
|
30
54
|
yaml do
|
|
31
55
|
map "text", to: :text
|
|
32
56
|
map "format", to: :format
|
|
33
57
|
map "tag", to: :tag
|
|
58
|
+
map "placement", to: :placement
|
|
59
|
+
map "region", to: :region
|
|
34
60
|
end
|
|
35
61
|
|
|
36
62
|
# XML serialization
|
|
@@ -39,6 +65,8 @@ module Expressir
|
|
|
39
65
|
map_element "text", to: :text
|
|
40
66
|
map_element "format", to: :format
|
|
41
67
|
map_element "tag", to: :tag
|
|
68
|
+
map_element "placement", to: :placement
|
|
69
|
+
map_element "region", to: :region
|
|
42
70
|
end
|
|
43
71
|
end
|
|
44
72
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Model
|
|
5
|
+
# Single source of truth for where a remark sits relative to the model
|
|
6
|
+
# element that owns it.
|
|
7
|
+
#
|
|
8
|
+
# The parser discards comments, so attachment reconstructs their position
|
|
9
|
+
# from source lines. Placement records that reconstruction, letting the
|
|
10
|
+
# formatter put the remark back where it was written:
|
|
11
|
+
#
|
|
12
|
+
# - LEADING — on its own line(s) directly above the owning statement.
|
|
13
|
+
# - TRAILING — on its own line(s) at the end of a body, before the closing
|
|
14
|
+
# keyword. The owner is the body's owner, and RemarkInfo#region names
|
|
15
|
+
# which body: an IF owns two, and they close at different keywords.
|
|
16
|
+
# - INLINE — on the same line as the owning statement, after its text.
|
|
17
|
+
# Only single-line statements take these: appending to a multi-line
|
|
18
|
+
# statement would move the remark down to its closing keyword.
|
|
19
|
+
#
|
|
20
|
+
# `nil` means the remark was attached by a legacy path, or predates
|
|
21
|
+
# placement tracking. Those keep their historical emission and must not
|
|
22
|
+
# be rendered by placement-aware emitters.
|
|
23
|
+
module RemarkPlacement
|
|
24
|
+
LEADING = "leading"
|
|
25
|
+
TRAILING = "trailing"
|
|
26
|
+
INLINE = "inline"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -4,8 +4,10 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 13.2 Alias statement
|
|
6
6
|
class Alias < ModelElement
|
|
7
|
+
include Statement
|
|
7
8
|
include Identifier
|
|
8
9
|
|
|
10
|
+
collection_attributes :statements
|
|
9
11
|
attribute :expression, ModelElement
|
|
10
12
|
attribute :statements, ModelElement, collection: true
|
|
11
13
|
attribute :_class, :string, default: -> { self.class.name }
|
|
@@ -4,12 +4,16 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 13.3 Assignment
|
|
6
6
|
class Assignment < ModelElement
|
|
7
|
+
include Statement
|
|
8
|
+
|
|
9
|
+
child_attributes :expression
|
|
7
10
|
attribute :ref, ModelElement
|
|
8
11
|
attribute :expression, ModelElement
|
|
9
12
|
attribute :_class, :string, default: -> { self.class.name }
|
|
10
13
|
|
|
11
14
|
key_value do
|
|
12
15
|
map "_class", to: :_class, render_default: true
|
|
16
|
+
map "untagged_remarks", to: :untagged_remarks
|
|
13
17
|
map "ref", to: :ref
|
|
14
18
|
map "expression", to: :expression
|
|
15
19
|
end
|
|
@@ -4,13 +4,34 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 13.4 Case statement
|
|
6
6
|
class Case < ModelElement
|
|
7
|
+
include Statement
|
|
8
|
+
|
|
9
|
+
# The executable bodies of a CASE, exposed as ordered statement
|
|
10
|
+
# lists. Tree-walkers traverse these rather than `actions`, because
|
|
11
|
+
# a CaseAction is a label wrapper the parser gives no usable source
|
|
12
|
+
# position — the statement inside it carries the position that
|
|
13
|
+
# matters for placing comments.
|
|
14
|
+
collection_attributes :action_statements, :otherwise_statements
|
|
15
|
+
|
|
16
|
+
child_attributes :expression
|
|
7
17
|
attribute :expression, ModelElement
|
|
8
18
|
attribute :actions, CaseAction, collection: true
|
|
9
19
|
attribute :otherwise_statement, ModelElement
|
|
10
20
|
attribute :_class, :string, default: -> { self.class.name }
|
|
11
21
|
|
|
22
|
+
# @return [Array<ModelElement>] each action's statement, in order
|
|
23
|
+
def action_statements
|
|
24
|
+
Array(actions).filter_map(&:statement)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @return [Array<ModelElement>] the OTHERWISE body, if present
|
|
28
|
+
def otherwise_statements
|
|
29
|
+
[otherwise_statement].compact
|
|
30
|
+
end
|
|
31
|
+
|
|
12
32
|
key_value do
|
|
13
33
|
map "_class", to: :_class, render_default: true
|
|
34
|
+
map "untagged_remarks", to: :untagged_remarks
|
|
14
35
|
map "expression", to: :expression
|
|
15
36
|
map "actions", to: :actions
|
|
16
37
|
map "otherwise_statement", to: :otherwise_statement
|
|
@@ -4,6 +4,7 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 13.4 Case statement
|
|
6
6
|
class CaseAction < ModelElement
|
|
7
|
+
child_attributes :expression
|
|
7
8
|
attribute :labels, ModelElement, collection: true
|
|
8
9
|
attribute :statement, ModelElement
|
|
9
10
|
attribute :_class, :string, default: -> { self.class.name }
|
|
@@ -4,11 +4,15 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 13.5 Compound statement
|
|
6
6
|
class Compound < ModelElement
|
|
7
|
+
include Statement
|
|
8
|
+
|
|
9
|
+
collection_attributes :statements
|
|
7
10
|
attribute :statements, ModelElement, collection: true
|
|
8
11
|
attribute :_class, :string, default: -> { self.class.name }
|
|
9
12
|
|
|
10
13
|
key_value do
|
|
11
14
|
map "_class", to: :_class, render_default: true
|
|
15
|
+
map "untagged_remarks", to: :untagged_remarks
|
|
12
16
|
map "statements", to: :statements
|
|
13
17
|
end
|
|
14
18
|
end
|
|
@@ -4,10 +4,13 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 13.6 Escape statement
|
|
6
6
|
class Escape < ModelElement
|
|
7
|
+
include Statement
|
|
8
|
+
|
|
7
9
|
attribute :_class, :string, default: -> { self.class.name }
|
|
8
10
|
|
|
9
11
|
key_value do
|
|
10
12
|
map "_class", to: :_class, render_default: true
|
|
13
|
+
map "untagged_remarks", to: :untagged_remarks
|
|
11
14
|
end
|
|
12
15
|
end
|
|
13
16
|
end
|
|
@@ -4,6 +4,10 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 13.7 If ... Then ... Else statement
|
|
6
6
|
class If < ModelElement
|
|
7
|
+
include Statement
|
|
8
|
+
|
|
9
|
+
collection_attributes :statements, :else_statements
|
|
10
|
+
child_attributes :expression
|
|
7
11
|
attribute :expression, ModelElement
|
|
8
12
|
attribute :statements, ModelElement, collection: true
|
|
9
13
|
attribute :else_statements, ModelElement, collection: true
|
|
@@ -11,6 +15,7 @@ module Expressir
|
|
|
11
15
|
|
|
12
16
|
key_value do
|
|
13
17
|
map "_class", to: :_class, render_default: true
|
|
18
|
+
map "untagged_remarks", to: :untagged_remarks
|
|
14
19
|
map "expression", to: :expression
|
|
15
20
|
map "statements", to: :statements
|
|
16
21
|
map "else_statements", to: :else_statements
|
|
@@ -4,10 +4,13 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 13.1 Null (statement)
|
|
6
6
|
class Null < ModelElement
|
|
7
|
+
include Statement
|
|
8
|
+
|
|
7
9
|
attribute :_class, :string, default: -> { self.class.name }
|
|
8
10
|
|
|
9
11
|
key_value do
|
|
10
12
|
map "_class", to: :_class, render_default: true
|
|
13
|
+
map "untagged_remarks", to: :untagged_remarks
|
|
11
14
|
end
|
|
12
15
|
end
|
|
13
16
|
end
|
|
@@ -4,12 +4,15 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 13.8 Procedure call statement
|
|
6
6
|
class ProcedureCall < ModelElement
|
|
7
|
+
include Statement
|
|
8
|
+
|
|
7
9
|
attribute :procedure, ModelElement
|
|
8
10
|
attribute :parameters, ModelElement, collection: true
|
|
9
11
|
attribute :_class, :string, default: -> { self.class.name }
|
|
10
12
|
|
|
11
13
|
key_value do
|
|
12
14
|
map "_class", to: :_class, render_default: true
|
|
15
|
+
map "untagged_remarks", to: :untagged_remarks
|
|
13
16
|
map "procedure", to: :procedure
|
|
14
17
|
map "parameters", to: :parameters
|
|
15
18
|
end
|
|
@@ -4,8 +4,11 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 13.9 Repeat statement
|
|
6
6
|
class Repeat < ModelElement
|
|
7
|
+
include Statement
|
|
7
8
|
include Identifier
|
|
8
9
|
|
|
10
|
+
collection_attributes :statements
|
|
11
|
+
child_attributes :while_expression, :until_expression
|
|
9
12
|
attribute :bound1, ModelElement
|
|
10
13
|
attribute :bound2, ModelElement
|
|
11
14
|
attribute :increment, ModelElement
|
|
@@ -4,11 +4,14 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 13.10 Return statement
|
|
6
6
|
class Return < ModelElement
|
|
7
|
+
include Statement
|
|
8
|
+
|
|
7
9
|
attribute :expression, ModelElement
|
|
8
10
|
attribute :_class, :string, default: -> { self.class.name }
|
|
9
11
|
|
|
10
12
|
key_value do
|
|
11
13
|
map "_class", to: :_class, render_default: true
|
|
14
|
+
map "untagged_remarks", to: :untagged_remarks
|
|
12
15
|
map "expression", to: :expression
|
|
13
16
|
end
|
|
14
17
|
end
|
|
@@ -4,10 +4,13 @@ module Expressir
|
|
|
4
4
|
# Specified in ISO 10303-11:2004
|
|
5
5
|
# - section 13.11 Skip statement
|
|
6
6
|
class Skip < ModelElement
|
|
7
|
+
include Statement
|
|
8
|
+
|
|
7
9
|
attribute :_class, :string, default: -> { self.class.name }
|
|
8
10
|
|
|
9
11
|
key_value do
|
|
10
12
|
map "_class", to: :_class, render_default: true
|
|
13
|
+
map "untagged_remarks", to: :untagged_remarks
|
|
11
14
|
end
|
|
12
15
|
end
|
|
13
16
|
end
|
data/lib/expressir/model.rb
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
# lib/expressir/model.rb
|
|
2
2
|
|
|
3
|
-
# Load marker modules for type checking
|
|
4
|
-
require_relative "model/concerns"
|
|
5
|
-
|
|
6
3
|
module Expressir
|
|
7
4
|
module Model
|
|
5
|
+
# Marker modules — autoload the same concerns.rb file from each name.
|
|
6
|
+
# The first reference triggers the load; the file defines all seven markers.
|
|
7
|
+
autoload :HasId, "#{__dir__}/model/concerns"
|
|
8
|
+
autoload :HasRemarkItems, "#{__dir__}/model/concerns"
|
|
9
|
+
autoload :HasRemarks, "#{__dir__}/model/concerns"
|
|
10
|
+
autoload :ScopeContainer, "#{__dir__}/model/concerns"
|
|
11
|
+
autoload :HasInformalPropositions, "#{__dir__}/model/concerns"
|
|
12
|
+
autoload :HasWhereRules, "#{__dir__}/model/concerns"
|
|
13
|
+
autoload :Statement, "#{__dir__}/model/concerns"
|
|
14
|
+
|
|
8
15
|
autoload :ModelElement, "#{__dir__}/model/model_element"
|
|
9
16
|
autoload :Cache, "#{__dir__}/model/cache"
|
|
10
17
|
autoload :ExpFile, "#{__dir__}/model/exp_file"
|
|
@@ -12,6 +19,8 @@ module Expressir
|
|
|
12
19
|
autoload :Repository, "#{__dir__}/model/repository"
|
|
13
20
|
autoload :RepositoryValidator, "#{__dir__}/model/repository_validator"
|
|
14
21
|
autoload :DependencyResolver, "#{__dir__}/model/dependency_resolver"
|
|
22
|
+
autoload :RemarkFormat, "#{__dir__}/model/remark_format"
|
|
23
|
+
autoload :RemarkPlacement, "#{__dir__}/model/remark_placement"
|
|
15
24
|
autoload :RemarkInfo, "#{__dir__}/model/remark_info"
|
|
16
25
|
autoload :InterfaceValidator, "#{__dir__}/model/interface_validator"
|
|
17
26
|
autoload :SearchEngine, "#{__dir__}/model/search_engine"
|
|
@@ -31,7 +31,7 @@ module Expressir
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
# Create ZIP package
|
|
34
|
-
Zip::File.open(output_path,
|
|
34
|
+
Zip::File.open(output_path, create: true) do |zip|
|
|
35
35
|
add_metadata(zip, metadata)
|
|
36
36
|
add_schemas(zip, repository, options)
|
|
37
37
|
add_indexes(zip, repository)
|
|
@@ -68,7 +68,7 @@ module Expressir
|
|
|
68
68
|
description: options[:description],
|
|
69
69
|
created_at: Time.now.utc.iso8601,
|
|
70
70
|
created_by: "expressir",
|
|
71
|
-
expressir_version: Expressir::VERSION,
|
|
71
|
+
expressir_version: Expressir::Version::VERSION,
|
|
72
72
|
express_mode: options[:express_mode],
|
|
73
73
|
resolution_mode: options[:resolution_mode],
|
|
74
74
|
serialization_format: options[:serialization_format],
|
data/lib/expressir/version.rb
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
module Expressir
|
|
2
|
-
|
|
2
|
+
# Gem version. Wrapped in a Version module so that lib/expressir.rb can
|
|
3
|
+
# autoload it (Ruby autoload only works for module/class constants, not
|
|
4
|
+
# for string constants like `Expressir::VERSION`).
|
|
5
|
+
module Version
|
|
6
|
+
VERSION = "2.4.1".freeze
|
|
7
|
+
end
|
|
3
8
|
end
|
data/lib/expressir.rb
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
require_relative "expressir/version"
|
|
2
|
-
require_relative "expressir/errors"
|
|
3
|
-
|
|
4
1
|
require "lutaml/model"
|
|
5
2
|
require "liquid" # To enable Lutaml::Model::Liquefiable
|
|
6
3
|
|
|
@@ -29,6 +26,44 @@ module Expressir
|
|
|
29
26
|
autoload :Config, "#{__dir__}/expressir/config"
|
|
30
27
|
extend Config
|
|
31
28
|
|
|
29
|
+
autoload :Version, "#{__dir__}/expressir/version"
|
|
30
|
+
|
|
31
|
+
# Error classes — autoload the same errors.rb file from each name.
|
|
32
|
+
# The first reference triggers the load; the file defines all 21 classes.
|
|
33
|
+
autoload :Error, "#{__dir__}/expressir/errors"
|
|
34
|
+
autoload :FileNotFoundError, "#{__dir__}/expressir/errors"
|
|
35
|
+
autoload :ManifestNotFoundError, "#{__dir__}/expressir/errors"
|
|
36
|
+
autoload :PackageNotFoundError, "#{__dir__}/expressir/errors"
|
|
37
|
+
autoload :SchemaNotFoundError, "#{__dir__}/expressir/errors"
|
|
38
|
+
autoload :UsageError, "#{__dir__}/expressir/errors"
|
|
39
|
+
autoload :MissingRequiredArgumentError, "#{__dir__}/expressir/errors"
|
|
40
|
+
autoload :InvalidOptionError, "#{__dir__}/expressir/errors"
|
|
41
|
+
autoload :ValidationError, "#{__dir__}/expressir/errors"
|
|
42
|
+
autoload :ManifestValidationError, "#{__dir__}/expressir/errors"
|
|
43
|
+
autoload :SchemaValidationError, "#{__dir__}/expressir/errors"
|
|
44
|
+
autoload :ReferentialIntegrityError, "#{__dir__}/expressir/errors"
|
|
45
|
+
autoload :NoValidSchemaPathsError, "#{__dir__}/expressir/errors"
|
|
46
|
+
autoload :CommandError, "#{__dir__}/expressir/errors"
|
|
47
|
+
autoload :PackageBuildError, "#{__dir__}/expressir/errors"
|
|
48
|
+
autoload :PackageReadError, "#{__dir__}/expressir/errors"
|
|
49
|
+
autoload :PackageExtractError, "#{__dir__}/expressir/errors"
|
|
50
|
+
autoload :PackageValidationError, "#{__dir__}/expressir/errors"
|
|
51
|
+
autoload :PackageListError, "#{__dir__}/expressir/errors"
|
|
52
|
+
autoload :PackageSearchError, "#{__dir__}/expressir/errors"
|
|
53
|
+
autoload :PackageTreeError, "#{__dir__}/expressir/errors"
|
|
54
|
+
|
|
55
|
+
# Backward-compatible top-level VERSION constant.
|
|
56
|
+
# Expressir::VERSION is a string, which Ruby autoload cannot lazy-load
|
|
57
|
+
# (autoload only works for module/class constants). The actual value
|
|
58
|
+
# lives in Expressir::Version::VERSION, autoloaded on first reference.
|
|
59
|
+
# This const_missing triggers the autoload when Expressir::VERSION is
|
|
60
|
+
# referenced, then caches the result.
|
|
61
|
+
def self.const_missing(name)
|
|
62
|
+
return Version::VERSION if name == :VERSION
|
|
63
|
+
|
|
64
|
+
super
|
|
65
|
+
end
|
|
66
|
+
|
|
32
67
|
autoload :Benchmark, "#{__dir__}/expressir/benchmark"
|
|
33
68
|
autoload :Coverage, "#{__dir__}/expressir/coverage"
|
|
34
69
|
|