~ubuntu-branches/ubuntu/wily/puppet/wily-proposed

« back to all changes in this revision

Viewing changes to lib/puppet/pops/model/model.rb

  • Committer: Package Import Robot
  • Author(s): Stig Sandbeck Mathisen
  • Date: 2014-10-24 13:47:15 UTC
  • mfrom: (3.1.64 sid)
  • Revision ID: package-import@ubuntu.com-20141024134715-6ig54u0c4gar36ss
Tags: 3.7.2-1
* Imported upstream release 3.7.2
* Declare compliance with Debian Policy 3.9.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#
2
 
# The Puppet Pops Metamodel
3
 
#
4
 
# This module contains a formal description of the Puppet Pops (*P*uppet *OP*eration instruction*S*).
5
 
# It describes a Metamodel containing DSL instructions, a description of PuppetType and related
6
 
# classes needed to evaluate puppet logic.
7
 
# The metamodel resembles the existing AST model, but it is a semantic model of instructions and
8
 
# the types that they operate on rather than an Abstract Syntax Tree, although closely related.
9
 
#
10
 
# The metamodel is anemic (has no behavior) except basic datatype and type
11
 
# assertions and reference/containment assertions.
12
 
# The metamodel is also a generalized description of the Puppet DSL to enable the
13
 
# same metamodel to be used to express Puppet DSL models (instances) with different semantics as
14
 
# the language evolves.
15
 
#
16
 
# The metamodel is concretized by a validator for a particular version of
17
 
# the Puppet DSL language.
18
 
#
19
 
# This metamodel is expressed using RGen.
 
2
# The Puppet Pops Metamodel Implementation
 
3
#
 
4
# The Puppet Pops Metamodel consists of two parts; the metamodel expressed with RGen in model_meta.rb,
 
5
# and this file which mixes in implementation details.
20
6
#
21
7
 
22
8
require 'rgen/metamodel_builder'
23
 
 
24
 
module Puppet::Pops::Model
25
 
  extend RGen::MetamodelBuilder::ModuleExtension
26
 
 
27
 
  # A base class for modeled objects that makes them Visitable, and Adaptable.
28
 
  #
29
 
  class PopsObject < RGen::MetamodelBuilder::MMBase
30
 
    include Puppet::Pops::Visitable
31
 
    include Puppet::Pops::Adaptable
32
 
    include Puppet::Pops::Containment
33
 
    abstract
34
 
  end
35
 
 
36
 
  # A Positioned object has an offset measured in an opaque unit (representing characters) from the start
37
 
  # of a source text (starting
38
 
  # from 0), and a length measured in the same opaque unit. The resolution of the opaque unit requires the
39
 
  # aid of a Locator instance that knows about the measure. This information is stored in the model's
40
 
  # root node - a Program.
41
 
  #
42
 
  # The offset and length are optional if the source of the model is not from parsed text.
43
 
  #
44
 
  class Positioned < PopsObject
45
 
    abstract
46
 
    has_attr 'offset', Integer
47
 
    has_attr 'length', Integer
48
 
  end
49
 
 
50
 
  # @abstract base class for expressions
51
 
  class Expression < Positioned
52
 
    abstract
53
 
  end
54
 
 
55
 
  # A Nop - the "no op" expression.
56
 
  # @note not really needed since the evaluator can evaluate nil with the meaning of NoOp
57
 
  # @todo deprecate? May be useful if there is the need to differentiate between nil and Nop when transforming model.
58
 
  #
59
 
  class Nop < Expression
60
 
  end
61
 
 
62
 
  # A binary expression is abstract and has a left and a right expression. The order of evaluation
63
 
  # and semantics are determined by the concrete subclass.
64
 
  #
65
 
  class BinaryExpression < Expression
66
 
    abstract
67
 
    #
68
 
    # @!attribute [rw] left_expr
69
 
    #   @return [Expression]
70
 
    contains_one_uni 'left_expr', Expression, :lowerBound => 1
71
 
    contains_one_uni 'right_expr', Expression, :lowerBound => 1
72
 
  end
73
 
 
74
 
  # An unary expression is abstract and contains one expression. The semantics are determined by
75
 
  # a concrete subclass.
76
 
  #
77
 
  class UnaryExpression < Expression
78
 
    abstract
79
 
    contains_one_uni 'expr', Expression, :lowerBound => 1
80
 
  end
81
 
 
82
 
  # A class that simply evaluates to the contained expression.
83
 
  # It is of value in order to preserve user entered parentheses in transformations, and
84
 
  # transformations from model to source.
85
 
  #
86
 
  class ParenthesizedExpression < UnaryExpression; end
87
 
 
88
 
  # A boolean not expression, reversing the truth of the unary expr.
89
 
  #
90
 
  class NotExpression < UnaryExpression; end
91
 
 
92
 
  # An arithmetic expression reversing the polarity of the numeric unary expr.
93
 
  #
94
 
  class UnaryMinusExpression < UnaryExpression; end
95
 
 
96
 
  # An assignment expression assigns a value to the lval() of the left_expr.
97
 
  #
98
 
  class AssignmentExpression < BinaryExpression
99
 
    has_attr 'operator', RGen::MetamodelBuilder::DataTypes::Enum.new([:'=', :'+=', :'-=']), :lowerBound => 1
100
 
  end
101
 
 
102
 
  # An arithmetic expression applies an arithmetic operator on left and right expressions.
103
 
  #
104
 
  class ArithmeticExpression < BinaryExpression
105
 
    has_attr 'operator', RGen::MetamodelBuilder::DataTypes::Enum.new([:'+', :'-', :'*', :'%', :'/', :'<<', :'>>' ]), :lowerBound => 1
106
 
  end
107
 
 
108
 
  # A relationship expression associates the left and right expressions
109
 
  #
110
 
  class RelationshipExpression < BinaryExpression
111
 
    has_attr 'operator', RGen::MetamodelBuilder::DataTypes::Enum.new([:'->', :'<-', :'~>', :'<~']), :lowerBound => 1
112
 
  end
113
 
 
114
 
  # A binary expression, that accesses the value denoted by right in left. i.e. typically
115
 
  # expressed concretely in a language as left[right].
116
 
  #
117
 
  class AccessExpression < Expression
118
 
    contains_one_uni 'left_expr', Expression, :lowerBound => 1
119
 
    contains_many_uni 'keys', Expression, :lowerBound => 1
120
 
  end
121
 
 
122
 
  # A comparison expression compares left and right using a comparison operator.
123
 
  #
124
 
  class ComparisonExpression < BinaryExpression
125
 
    has_attr 'operator', RGen::MetamodelBuilder::DataTypes::Enum.new([:'==', :'!=', :'<', :'>', :'<=', :'>=' ]), :lowerBound => 1
126
 
  end
127
 
 
128
 
  # A match expression matches left and right using a matching operator.
129
 
  #
130
 
  class MatchExpression < BinaryExpression
131
 
    has_attr 'operator', RGen::MetamodelBuilder::DataTypes::Enum.new([:'!~', :'=~']), :lowerBound => 1
132
 
  end
133
 
 
134
 
  # An 'in' expression checks if left is 'in' right
135
 
  #
136
 
  class InExpression < BinaryExpression; end
137
 
 
138
 
  # A boolean expression applies a logical connective operator (and, or) to left and right expressions.
139
 
  #
140
 
  class BooleanExpression < BinaryExpression
141
 
    abstract
142
 
  end
143
 
 
144
 
  # An and expression applies the logical connective operator and to left and right expression
145
 
  # and does not evaluate the right expression if the left expression is false.
146
 
  #
147
 
  class AndExpression < BooleanExpression; end
148
 
 
149
 
  # An or expression applies the logical connective operator or to the left and right expression
150
 
  # and does not evaluate the right expression if the left expression is true
151
 
  #
152
 
  class OrExpression < BooleanExpression; end
153
 
 
154
 
  # A literal list / array containing 0:M expressions.
155
 
  #
156
 
  class LiteralList < Expression
157
 
    contains_many_uni 'values', Expression
158
 
  end
159
 
 
160
 
  # A Keyed entry has a key and a value expression. It is typically used as an entry in a Hash.
161
 
  #
162
 
  class KeyedEntry < Positioned
163
 
    contains_one_uni 'key', Expression, :lowerBound => 1
164
 
    contains_one_uni 'value', Expression, :lowerBound => 1
165
 
  end
166
 
 
167
 
  # A literal hash is a collection of KeyedEntry objects
168
 
  #
169
 
  class LiteralHash < Expression
170
 
    contains_many_uni 'entries', KeyedEntry
171
 
  end
172
 
 
173
 
  # A block contains a list of expressions
174
 
  #
175
 
  class BlockExpression < Expression
176
 
    contains_many_uni 'statements', Expression
177
 
  end
178
 
 
179
 
  # A case option entry in a CaseStatement
180
 
  #
181
 
  class CaseOption < Expression
182
 
    contains_many_uni 'values', Expression, :lowerBound => 1
183
 
    contains_one_uni 'then_expr', Expression, :lowerBound => 1
184
 
  end
185
 
 
186
 
  # A case expression has a test, a list of options (multi values => block map).
187
 
  # One CaseOption may contain a LiteralDefault as value. This option will be picked if nothing
188
 
  # else matched.
189
 
  #
190
 
  class CaseExpression < Expression
191
 
    contains_one_uni 'test', Expression, :lowerBound => 1
192
 
    contains_many_uni 'options', CaseOption
193
 
  end
194
 
 
195
 
  # A query expression is an expression that is applied to some collection.
196
 
  # The contained optional expression may contain different types of relational expressions depending
197
 
  # on what the query is applied to.
198
 
  #
199
 
  class QueryExpression < Expression
200
 
    abstract
201
 
    contains_one_uni 'expr', Expression, :lowerBound => 0
202
 
  end
203
 
 
204
 
  # An exported query is a special form of query that searches for exported objects.
205
 
  #
206
 
  class ExportedQuery < QueryExpression
207
 
  end
208
 
 
209
 
  # A virtual query is a special form of query that searches for virtual objects.
210
 
  #
211
 
  class VirtualQuery < QueryExpression
212
 
  end
213
 
 
214
 
  # An attribute operation sets or appends a value to a named attribute.
215
 
  #
216
 
  class AttributeOperation < Positioned
217
 
    has_attr 'attribute_name', String, :lowerBound => 1
218
 
    has_attr 'operator', RGen::MetamodelBuilder::DataTypes::Enum.new([:'=>', :'+>', ]), :lowerBound => 1
219
 
    contains_one_uni 'value_expr', Expression, :lowerBound => 1
220
 
  end
221
 
 
222
 
  # An object that collects stored objects from the central cache and returns
223
 
  # them to the current host. Operations may optionally be applied.
224
 
  #
225
 
  class CollectExpression < Expression
226
 
    contains_one_uni 'type_expr', Expression, :lowerBound => 1
227
 
    contains_one_uni 'query', QueryExpression, :lowerBound => 1
228
 
    contains_many_uni 'operations', AttributeOperation
229
 
  end
230
 
 
231
 
  class Parameter < Positioned
232
 
    has_attr 'name', String, :lowerBound => 1
233
 
    contains_one_uni 'value', Expression
234
 
  end
235
 
 
236
 
  # Abstract base class for definitions.
237
 
  #
238
 
  class Definition < Expression
239
 
    abstract
240
 
  end
241
 
 
242
 
  # Abstract base class for named and parameterized definitions.
243
 
  class NamedDefinition < Definition
244
 
    abstract
245
 
    has_attr 'name', String, :lowerBound => 1
246
 
    contains_many_uni 'parameters', Parameter
247
 
    contains_one_uni 'body', Expression
248
 
  end
249
 
 
250
 
  # A resource type definition (a 'define' in the DSL).
251
 
  #
252
 
  class ResourceTypeDefinition < NamedDefinition
253
 
  end
254
 
 
255
 
  # A node definition matches hosts using Strings, or Regular expressions. It may inherit from
256
 
  # a parent node (also using a String or Regular expression).
257
 
  #
258
 
  class NodeDefinition < Definition
259
 
    contains_one_uni 'parent', Expression
260
 
    contains_many_uni 'host_matches', Expression, :lowerBound => 1
261
 
    contains_one_uni 'body', Expression
262
 
  end
263
 
 
264
 
  class LocatableExpression < Expression
265
 
    has_many_attr 'line_offsets', Integer
266
 
    has_attr 'locator', Object, :lowerBound => 1, :transient => true
267
 
 
268
 
    module ClassModule
269
 
      # Go through the gymnastics of making either value or pattern settable
270
 
      # with synchronization to the other form. A derived value cannot be serialized
271
 
      # and we want to serialize the pattern. When recreating the object we need to
272
 
      # recreate it from the pattern string.
273
 
      # The below sets both values if one is changed.
274
 
      #
275
 
      def locator
276
 
        unless result = getLocator
277
 
          setLocator(result = Puppet::Pops::Parser::Locator.locator(source_text, source_ref(), line_offsets))
278
 
        end
279
 
        result
280
 
      end
281
 
    end
282
 
  end
283
 
 
284
 
  # Contains one expression which has offsets reported virtually (offset against the Program's
285
 
  # overall locator).
286
 
  #
287
 
  class SubLocatedExpression < Expression
288
 
    contains_one_uni 'expr', Expression, :lowerBound => 1
289
 
 
290
 
    # line offset index for contained expressions
291
 
    has_many_attr 'line_offsets', Integer
292
 
 
293
 
    # Number of preceding lines (before the line_offsets)
294
 
    has_attr 'leading_line_count', Integer
295
 
 
296
 
    # The offset of the leading source line (i.e. size of "left margin").
297
 
    has_attr 'leading_line_offset', Integer
298
 
 
299
 
    # The locator for the sub-locatable's children (not for the sublocator itself)
300
 
    # The locator is not serialized and is recreated on demand from the indexing information
301
 
    # in self.
302
 
    #
303
 
    has_attr 'locator', Object, :lowerBound => 1, :transient => true
304
 
 
305
 
    module ClassModule
306
 
      def locator
307
 
        unless result = getLocator
308
 
          # Adapt myself to get the Locator for me
309
 
          adapter = Puppet::Pops::Adapters::SourcePosAdapter.adapt(self)
310
 
          # Get the program (root), and deal with case when not contained in a program
311
 
          program = eAllContainers.find {|c| c.is_a?(Program) }
312
 
          source_ref = program.nil? ? '' : program.source_ref
313
 
 
314
 
          # An outer locator is needed since SubLocator only deals with offsets. This outer locator
315
 
          # has 0,0 as origin.
316
 
          outer_locator = Puppet::Pops::Parser::Locator.locator(adpater.extract_text, source_ref, line_offsets)
317
 
 
318
 
          # Create a sublocator that describes an offset from the outer
319
 
          # NOTE: the offset of self is the same as the sublocator's leading_offset
320
 
          result = Puppet::Pops::Parser::Locator::SubLocator.new(outer_locator,
321
 
            leading_line_count, offset, leading_line_offset)
322
 
          setLocator(result)
323
 
        end
324
 
        result
325
 
      end
326
 
    end
327
 
  end
328
 
 
329
 
  # A heredoc is a wrapper around a LiteralString or a ConcatenatedStringExpression with a specification
330
 
  # of syntax. The expectation is that "syntax" has meaning to a validator. A syntax of nil or '' means
331
 
  # "unspecified syntax".
332
 
  #
333
 
  class HeredocExpression < Expression
334
 
    has_attr 'syntax', String
335
 
    contains_one_uni 'text_expr', Expression, :lowerBound => 1
336
 
  end
337
 
 
338
 
  # A class definition
339
 
  #
340
 
  class HostClassDefinition < NamedDefinition
341
 
    has_attr 'parent_class', String
342
 
  end
343
 
 
344
 
  # i.e {|parameters| body }
345
 
  class LambdaExpression < Expression
346
 
    contains_many_uni 'parameters', Parameter
347
 
    contains_one_uni 'body', Expression
348
 
  end
349
 
 
350
 
  # If expression. If test is true, the then_expr part should be evaluated, else the (optional)
351
 
  # else_expr. An 'elsif' is simply an else_expr = IfExpression, and 'else' is simply else == Block.
352
 
  # a 'then' is typically a Block.
353
 
  #
354
 
  class IfExpression < Expression
355
 
    contains_one_uni 'test', Expression, :lowerBound => 1
356
 
    contains_one_uni 'then_expr', Expression, :lowerBound => 1
357
 
    contains_one_uni 'else_expr', Expression
358
 
  end
359
 
 
360
 
  # An if expression with boolean reversed test.
361
 
  #
362
 
  class UnlessExpression < IfExpression
363
 
  end
364
 
 
365
 
  # An abstract call.
366
 
  #
367
 
  class CallExpression < Expression
368
 
    abstract
369
 
    # A bit of a crutch; functions are either procedures (void return) or has an rvalue
370
 
    # this flag tells the evaluator that it is a failure to call a function that is void/procedure
371
 
    # where a value is expected.
372
 
    #
373
 
    has_attr 'rval_required', Boolean, :defaultValueLiteral => "false"
374
 
    contains_one_uni 'functor_expr', Expression, :lowerBound => 1
375
 
    contains_many_uni 'arguments', Expression
376
 
    contains_one_uni 'lambda', Expression
377
 
  end
378
 
 
379
 
  # A function call where the functor_expr should evaluate to something callable.
380
 
  #
381
 
  class CallFunctionExpression < CallExpression; end
382
 
 
383
 
  # A function call where the given functor_expr should evaluate to the name
384
 
  # of a function.
385
 
  #
386
 
  class CallNamedFunctionExpression < CallExpression; end
387
 
 
388
 
  # A method/function call where the function expr is a NamedAccess and with support for
389
 
  # an optional lambda block
390
 
  #
391
 
  class CallMethodExpression < CallExpression
392
 
  end
393
 
 
394
 
  # Abstract base class for literals.
395
 
  #
396
 
  class Literal < Expression
397
 
    abstract
398
 
  end
399
 
 
400
 
  # A literal value is an abstract value holder. The type of the contained value is
401
 
  # determined by the concrete subclass.
402
 
  #
403
 
  class LiteralValue < Literal
404
 
    abstract
405
 
  end
406
 
 
407
 
  # A Regular Expression Literal.
408
 
  #
409
 
  class LiteralRegularExpression < LiteralValue
410
 
    has_attr 'value', Object, :lowerBound => 1, :transient => true
411
 
    has_attr 'pattern', String, :lowerBound => 1
412
 
 
413
 
    module ClassModule
414
 
      # Go through the gymnastics of making either value or pattern settable
415
 
      # with synchronization to the other form. A derived value cannot be serialized
416
 
      # and we want to serialize the pattern. When recreating the object we need to
417
 
      # recreate it from the pattern string.
418
 
      # The below sets both values if one is changed.
419
 
      #
420
 
      def value= regexp
421
 
        setValue regexp
422
 
        setPattern regexp.to_s
423
 
      end
424
 
 
425
 
      def pattern= regexp_string
426
 
        setPattern regexp_string
427
 
        setValue Regexp.new(regexp_string)
428
 
      end
429
 
    end
430
 
 
431
 
  end
432
 
 
433
 
  # A Literal String
434
 
  #
435
 
  class LiteralString < LiteralValue
436
 
    has_attr 'value', String, :lowerBound => 1
437
 
  end
438
 
 
439
 
  class LiteralNumber < LiteralValue
440
 
    abstract
441
 
  end
442
 
 
443
 
  # A literal number has a radix of decimal (10), octal (8), or hex (16) to enable string conversion with the input radix.
444
 
  # By default, a radix of 10 is used.
445
 
  #
446
 
  class LiteralInteger < LiteralNumber
447
 
    has_attr 'radix', Integer, :lowerBound => 1, :defaultValueLiteral => "10"
448
 
    has_attr 'value', Integer, :lowerBound => 1
449
 
  end
450
 
 
451
 
  class LiteralFloat < LiteralNumber
452
 
    has_attr 'value', Float, :lowerBound => 1
453
 
  end
454
 
 
455
 
  # The DSL `undef`.
456
 
  #
457
 
  class LiteralUndef < Literal; end
458
 
 
459
 
  # The DSL `default`
460
 
  class LiteralDefault < Literal; end
461
 
 
462
 
  # DSL `true` or `false`
463
 
  class LiteralBoolean < LiteralValue
464
 
    has_attr 'value', Boolean, :lowerBound => 1
465
 
  end
466
 
 
467
 
  # A text expression is an interpolation of an expression. If the embedded expression is
468
 
  # a QualifiedName, it is taken as a variable name and resolved. All other expressions are evaluated.
469
 
  # The result is transformed to a string.
470
 
  #
471
 
  class TextExpression < UnaryExpression; end
472
 
 
473
 
  # An interpolated/concatenated string. The contained segments are expressions. Verbatim sections
474
 
  # should be LiteralString instances, and interpolated expressions should either be
475
 
  # TextExpression instances (if QualifiedNames should be turned into variables), or any other expression
476
 
  # if such treatment is not needed.
477
 
  #
478
 
  class ConcatenatedString < Expression
479
 
    contains_many_uni 'segments', Expression
480
 
  end
481
 
 
482
 
  # A DSL NAME (one or multiple parts separated by '::').
483
 
  #
484
 
  class QualifiedName < LiteralValue
485
 
    has_attr 'value', String, :lowerBound => 1
486
 
  end
487
 
 
488
 
  # A DSL CLASSREF (one or multiple parts separated by '::' where (at least) the first part starts with an upper case letter).
489
 
  #
490
 
  class QualifiedReference < LiteralValue
491
 
    has_attr 'value', String, :lowerBound => 1
492
 
  end
493
 
 
494
 
  # A Variable expression looks up value of expr (some kind of name) in scope.
495
 
  # The expression is typically a QualifiedName, or QualifiedReference.
496
 
  #
497
 
  class VariableExpression < UnaryExpression; end
498
 
 
499
 
  # Epp start
500
 
  class EppExpression < Expression
501
 
    has_attr 'see_scope', Boolean
502
 
    contains_one_uni 'body', Expression
503
 
  end
504
 
 
505
 
  # A string to render
506
 
  class RenderStringExpression < LiteralString
507
 
  end
508
 
 
509
 
  # An expression to evluate and render
510
 
  class RenderExpression < UnaryExpression
511
 
  end
512
 
 
513
 
  # A resource body describes one resource instance
514
 
  #
515
 
  class ResourceBody < Positioned
516
 
    contains_one_uni 'title', Expression
517
 
    contains_many_uni 'operations', AttributeOperation
518
 
  end
519
 
 
520
 
  # An abstract resource describes the form of the resource (regular, virtual or exported)
521
 
  # and adds convenience methods to ask if it is virtual or exported.
522
 
  # All derived classes may not support all forms, and these needs to be validated
523
 
  #
524
 
  class AbstractResource < Expression
525
 
    abstract
526
 
    has_attr 'form', RGen::MetamodelBuilder::DataTypes::Enum.new([:regular, :virtual, :exported ]), :lowerBound => 1, :defaultValueLiteral => "regular"
527
 
    has_attr 'virtual', Boolean, :derived => true
528
 
    has_attr 'exported', Boolean, :derived => true
529
 
 
530
 
    module ClassModule
531
 
      def virtual_derived
532
 
        form == :virtual || form == :exported
533
 
      end
534
 
 
535
 
      def exported_derived
536
 
        form == :exported
537
 
      end
538
 
    end
539
 
 
540
 
  end
541
 
 
542
 
  # A resource expression is used to instantiate one or many resource. Resources may optionally
543
 
  # be virtual or exported, an exported resource is always virtual.
544
 
  #
545
 
  class ResourceExpression < AbstractResource
546
 
    contains_one_uni 'type_name', Expression, :lowerBound => 1
547
 
    contains_many_uni 'bodies', ResourceBody
548
 
  end
549
 
 
550
 
  # A resource defaults sets defaults for a resource type. This class inherits from AbstractResource
551
 
  # but does only support the :regular form (this is intentional to be able to produce better error messages
552
 
  # when illegal forms are applied to a model.
553
 
  #
554
 
  class ResourceDefaultsExpression < AbstractResource
555
 
    contains_one_uni 'type_ref', QualifiedReference
556
 
    contains_many_uni 'operations', AttributeOperation
557
 
  end
558
 
 
559
 
  # A resource override overrides already set values.
560
 
  #
561
 
  class ResourceOverrideExpression < Expression
562
 
    contains_one_uni 'resources', Expression, :lowerBound => 1
563
 
    contains_many_uni 'operations', AttributeOperation
564
 
  end
565
 
 
566
 
  # A selector entry describes a map from matching_expr to value_expr.
567
 
  #
568
 
  class SelectorEntry < Positioned
569
 
    contains_one_uni 'matching_expr', Expression, :lowerBound => 1
570
 
    contains_one_uni 'value_expr', Expression, :lowerBound => 1
571
 
  end
572
 
 
573
 
  # A selector expression represents a mapping from a left_expr to a matching SelectorEntry.
574
 
  #
575
 
  class SelectorExpression < Expression
576
 
    contains_one_uni 'left_expr', Expression, :lowerBound => 1
577
 
    contains_many_uni 'selectors', SelectorEntry
578
 
  end
579
 
 
580
 
  # A named access expression looks up a named part. (e.g. $a.b)
581
 
  #
582
 
  class NamedAccessExpression < BinaryExpression; end
583
 
 
584
 
  # A Program is the top level construct returned by the parser
585
 
  # it contains the parsed result in the body, and has a reference to the full source text,
586
 
  # and its origin. The line_offset's is an array with the start offset of each line.
587
 
  #
588
 
  class Program < PopsObject
589
 
    contains_one_uni 'body', Expression
590
 
    has_many 'definitions', Definition
591
 
    has_attr 'source_text', String
592
 
    has_attr 'source_ref', String
593
 
    has_many_attr 'line_offsets', Integer
594
 
    has_attr 'locator', Object, :lowerBound => 1, :transient => true
595
 
 
596
 
    module ClassModule
597
 
      def locator
598
 
        unless result = getLocator
599
 
          setLocator(result = Puppet::Pops::Parser::Locator.locator(source_text, source_ref(), line_offsets))
600
 
        end
601
 
        result
602
 
      end
603
 
    end
604
 
 
605
 
  end
 
9
require 'rgen/ecore/ecore'
 
10
require 'rgen/ecore/ecore_ext'
 
11
require 'rgen/ecore/ecore_to_ruby'
 
12
 
 
13
module Puppet::Pops
 
14
  require 'puppet/pops/model/model_meta'
 
15
 
 
16
  # TODO: See PUP-2978 for possible performance optimization
 
17
 
 
18
  # Mix in implementation into the generated code
 
19
  module Model
 
20
 
 
21
    class PopsObject
 
22
      include Puppet::Pops::Visitable
 
23
      include Puppet::Pops::Adaptable
 
24
      include Puppet::Pops::Containment
 
25
    end
 
26
 
 
27
    class LocatableExpression
 
28
      module ClassModule
 
29
        # Go through the gymnastics of making either value or pattern settable
 
30
        # with synchronization to the other form. A derived value cannot be serialized
 
31
        # and we want to serialize the pattern. When recreating the object we need to
 
32
        # recreate it from the pattern string.
 
33
        # The below sets both values if one is changed.
 
34
        #
 
35
        def locator
 
36
          unless result = getLocator
 
37
            setLocator(result = Puppet::Pops::Parser::Locator.locator(source_text, source_ref(), line_offsets))
 
38
          end
 
39
          result
 
40
        end
 
41
      end
 
42
    end
 
43
 
 
44
    class SubLocatedExpression
 
45
      module ClassModule
 
46
        def locator
 
47
          unless result = getLocator
 
48
            # Adapt myself to get the Locator for me
 
49
            adapter = Puppet::Pops::Adapters::SourcePosAdapter.adapt(self)
 
50
            # Get the program (root), and deal with case when not contained in a program
 
51
            program = eAllContainers.find {|c| c.is_a?(Program) }
 
52
            source_ref = program.nil? ? '' : program.source_ref
 
53
 
 
54
            # An outer locator is needed since SubLocator only deals with offsets. This outer locator
 
55
            # has 0,0 as origin.
 
56
            outer_locator = Puppet::Pops::Parser::Locator.locator(adpater.extract_text, source_ref, line_offsets)
 
57
 
 
58
            # Create a sublocator that describes an offset from the outer
 
59
            # NOTE: the offset of self is the same as the sublocator's leading_offset
 
60
            result = Puppet::Pops::Parser::Locator::SubLocator.new(outer_locator,
 
61
              leading_line_count, offset, leading_line_offset)
 
62
            setLocator(result)
 
63
          end
 
64
          result
 
65
        end
 
66
      end
 
67
    end
 
68
 
 
69
    class LiteralRegularExpression
 
70
      module ClassModule
 
71
        # Go through the gymnastics of making either value or pattern settable
 
72
        # with synchronization to the other form. A derived value cannot be serialized
 
73
        # and we want to serialize the pattern. When recreating the object we need to
 
74
        # recreate it from the pattern string.
 
75
        # The below sets both values if one is changed.
 
76
        #
 
77
        def value= regexp
 
78
          setValue regexp
 
79
          setPattern regexp.to_s
 
80
        end
 
81
 
 
82
        def pattern= regexp_string
 
83
          setPattern regexp_string
 
84
          setValue Regexp.new(regexp_string)
 
85
        end
 
86
      end
 
87
    end
 
88
 
 
89
    class AbstractResource
 
90
      module ClassModule
 
91
        def virtual_derived
 
92
          form == :virtual || form == :exported
 
93
        end
 
94
 
 
95
        def exported_derived
 
96
          form == :exported
 
97
        end
 
98
      end
 
99
    end
 
100
 
 
101
    class Program < PopsObject
 
102
      module ClassModule
 
103
        def locator
 
104
          unless result = getLocator
 
105
            setLocator(result = Puppet::Pops::Parser::Locator.locator(source_text, source_ref(), line_offsets))
 
106
          end
 
107
          result
 
108
        end
 
109
      end
 
110
    end
 
111
 
 
112
  end
 
113
 
606
114
end