diff --git a/lib/puppet/parser/ast.rb b/lib/puppet/parser/ast.rb index 7c878cdfd..ed55e69ed 100644 --- a/lib/puppet/parser/ast.rb +++ b/lib/puppet/parser/ast.rb @@ -1,62 +1,60 @@ -require 'puppet' -require 'puppet/util/autoload' - # The base class for the 3x "parse tree", now only used by the top level # constructs and the compiler. # Handles things like file name, line #, and also does the initialization # for all of the parameters of all of the child objects. # class Puppet::Parser::AST AST = Puppet::Parser::AST include Puppet::Util::Errors include Puppet::Util::MethodHelper attr_accessor :parent, :scope, :file, :line, :pos def inspect "( #{self.class} #{self.to_s} #{@children.inspect} )" end # Evaluate the current object. Just a stub method, since the subclass # should override this method. - def evaluate(*options) + def evaluate(scope) end # The version of the evaluate method that should be called, because it # correctly handles errors. It is critical to use this method because # it can enable you to catch the error where it happens, rather than # much higher up the stack. - def safeevaluate(*options) + def safeevaluate(scope) # We duplicate code here, rather than using exceptwrap, because this # is called so many times during parsing. begin - return self.evaluate(*options) + return self.evaluate(scope) rescue Puppet::Error => detail raise adderrorcontext(detail) rescue => detail error = Puppet::ParseError.new(detail.to_s, nil, nil, detail) # We can't use self.fail here because it always expects strings, # not exceptions. raise adderrorcontext(error, detail) end end # Initialize the object. Requires a hash as the argument, and - # takes each of the parameters of the hash and calls the settor + # takes each of the parameters of the hash and calls the setter # method for them. This is probably pretty inefficient and should # likely be changed at some point. def initialize(args) set_options(args) end end # And include all of the AST subclasses. -require 'puppet/parser/ast/block_expression' -require 'puppet/parser/ast/hostclass' # PUP-3274 cannot remove until environment uses a different representation +require 'puppet/parser/ast/branch' require 'puppet/parser/ast/leaf' +require 'puppet/parser/ast/block_expression' +require 'puppet/parser/ast/hostclass' require 'puppet/parser/ast/node' require 'puppet/parser/ast/resource' require 'puppet/parser/ast/resource_instance' require 'puppet/parser/ast/resourceparam' diff --git a/lib/puppet/parser/ast/block_expression.rb b/lib/puppet/parser/ast/block_expression.rb index 386b6ad55..81f2012b0 100644 --- a/lib/puppet/parser/ast/block_expression.rb +++ b/lib/puppet/parser/ast/block_expression.rb @@ -1,29 +1,15 @@ -require 'puppet/parser/ast/branch' - -class Puppet::Parser::AST - class BlockExpression < Branch - include Enumerable - - # Evaluate contained expressions, produce result of the last - def evaluate(scope) - result = nil - @children.each do |child| - result = child.safeevaluate(scope) - end - result - end - - # Return a child by index. - def [](index) - @children[index] - end +# Evaluates contained expressions, produce result of the last +# +class Puppet::Parser::AST::BlockExpression < Puppet::Parser::AST::Branch + def evaluate(scope) + @children.reduce(nil) { |_, child| child.safeevaluate(scope) } + end - def sequence_with(other) - Puppet::Parser::AST::BlockExpression.new(:children => self.children + other.children) - end + def sequence_with(other) + Puppet::Parser::AST::BlockExpression.new(:children => self.children + other.children) + end - def to_s - "[" + @children.collect { |c| c.to_s }.join(', ') + "]" - end + def to_s + "[" + @children.collect { |c| c.to_s }.join(', ') + "]" end end diff --git a/lib/puppet/parser/ast/branch.rb b/lib/puppet/parser/ast/branch.rb index 83155b398..32febd33e 100644 --- a/lib/puppet/parser/ast/branch.rb +++ b/lib/puppet/parser/ast/branch.rb @@ -1,22 +1,19 @@ -class Puppet::Parser::AST - # The parent class of all AST objects that contain other AST objects. - # Everything but the really simple objects descend from this. It is - # important to note that Branch objects contain other AST objects only -- - # if you want to contain values, use a descendent of the AST::Leaf class. - class Branch < AST - include Enumerable - attr_accessor :pin, :children +# The parent class of all AST objects that contain other AST objects. +# Everything but the really simple objects descend from this. It is +# important to note that Branch objects contain other AST objects only -- +# if you want to contain values, use a descendent of the AST::Leaf class. +# +# @api private +class Puppet::Parser::AST::Branch < Puppet::Parser::AST + include Enumerable + attr_accessor :pin, :children - def each - @children.each { |child| - yield child - } - end - - def initialize(arghash) - super(arghash) + def each + @children.each { |child| yield child } + end - @children ||= [] - end + def initialize(arghash) + super(arghash) + @children ||= [] end end diff --git a/lib/puppet/parser/ast/leaf.rb b/lib/puppet/parser/ast/leaf.rb index 2a88e8d3f..82304c30f 100644 --- a/lib/puppet/parser/ast/leaf.rb +++ b/lib/puppet/parser/ast/leaf.rb @@ -1,75 +1,75 @@ -class Puppet::Parser::AST - # The base class for all of the leaves of the parse trees. These - # basically just have types and values. Both of these parameters - # are simple values, not AST objects. - class Leaf < AST - attr_accessor :value, :type - - # Return our value. - def evaluate(scope) - @value - end +# The base class for all of the leaves of the parse trees. These +# basically just have types and values. Both of these parameters +# are simple values, not AST objects. +# +class Puppet::Parser::AST::Leaf < Puppet::Parser::AST + attr_accessor :value, :type + # Return our value. + def evaluate(scope) + @value + end - def match(value) - @value == value - end + def match(value) + @value == value + end - def to_s - @value.to_s unless @value.nil? - end + def to_s + @value.to_s unless @value.nil? end +end - # Host names, either fully qualified or just the short name, or even a regex - class HostName < AST::Leaf - def initialize(hash) - super +# Host names, either fully qualified or just the short name, or even a regex +# +class Puppet::Parser::AST::HostName < Puppet::Parser::AST::Leaf + def initialize(hash) + super - # Note that this is an AST::Regex, not a Regexp - unless @value.is_a?(Regex) - @value = @value.to_s.downcase - if @value =~ /[^-\w.]/ - raise Puppet::DevError, "'#{@value}' is not a valid hostname" - end + # Note that this is an AST::Regex, not a Regexp + unless @value.is_a?(Regex) + @value = @value.to_s.downcase + if @value =~ /[^-\w.]/ + raise Puppet::DevError, "'#{@value}' is not a valid hostname" end end + end - # implementing eql? and hash so that when an HostName is stored - # in a hash it has the same hashing properties as the underlying value - def eql?(value) - @value.eql?(value.is_a?(HostName) ? value.value : value) - end + # implementing eql? and hash so that when an HostName is stored + # in a hash it has the same hashing properties as the underlying value + def eql?(value) + @value.eql?(value.is_a?(HostName) ? value.value : value) + end - def hash - @value.hash - end + def hash + @value.hash end +end - class Regex < AST::Leaf - def initialize(hash) - super - # transform value from hash options unless it is already a regular expression - @value = Regexp.new(@value) unless @value.is_a?(Regexp) - end +class Puppet::Parser::AST::Regex < Puppet::Parser::AST::Leaf + def initialize(hash) + super + # transform value from hash options unless it is already a regular expression + @value = Regexp.new(@value) unless @value.is_a?(Regexp) + end - # we're returning self here to wrap the regexp and to be used in places - # where a string would have been used, without modifying any client code. - # For instance, in many places we have the following code snippet: - # val = @val.safeevaluate(@scope) - # if val.match(otherval) - # ... - # end - # this way, we don't have to modify this test specifically for handling - # regexes. - def evaluate(scope) - self - end + # we're returning self here to wrap the regexp and to be used in places + # where a string would have been used, without modifying any client code. + # For instance, in many places we have the following code snippet: + # val = @val.safeevaluate(@scope) + # if val.match(otherval) + # ... + # end + # this way, we don't have to modify this test specifically for handling + # regexes. + # + def evaluate(scope) + self + end - def match(value) - @value.match(value) - end + def match(value) + @value.match(value) + end - def to_s - "/#{@value.source}/" - end + def to_s + "/#{@value.source}/" end end diff --git a/lib/puppet/parser/ast/node.rb b/lib/puppet/parser/ast/node.rb index abe160211..9f4cd47c3 100644 --- a/lib/puppet/parser/ast/node.rb +++ b/lib/puppet/parser/ast/node.rb @@ -1,21 +1,17 @@ -require 'puppet/parser/ast/top_level_construct' - class Puppet::Parser::AST::Node < Puppet::Parser::AST::TopLevelConstruct attr_accessor :names, :context def initialize(names, context = {}) raise ArgumentError, "names should be an array" unless names.is_a? Array if context[:parent] raise Puppet::DevError, "Node inheritance is removed in Puppet 4.0.0. See http://links.puppetlabs.com/puppet-node-inheritance-deprecation" end @names = names @context = context end def instantiate(modname) - @names.map do |name| - Puppet::Resource::Type.new(:node, name, @context.merge(:module_name => modname)) - end + @names.map { |name| Puppet::Resource::Type.new(:node, name, @context.merge(:module_name => modname)) } end end diff --git a/lib/puppet/parser/ast/resource.rb b/lib/puppet/parser/ast/resource.rb index 0b43831e0..f707c2ff6 100644 --- a/lib/puppet/parser/ast/resource.rb +++ b/lib/puppet/parser/ast/resource.rb @@ -1,63 +1,61 @@ -# Any normal puppet resource declaration. Can point to a definition or a -# builtin type. -class Puppet::Parser::AST -class Resource < AST::Branch +# Instruction for Resource instantiation. +# Instantiates resources of both native and user defined types. +# +class Puppet::Parser::AST::Resource < Puppet::Parser::AST::Branch attr_accessor :type, :instances, :exported, :virtual - # Does not actually return an object; instead sets an object - # in the current scope. + # Evaluates resources by adding them to the compiler for lazy evaluation + # and returning the produced resource references. + # def evaluate(scope) # We want virtual to be true if exported is true. We can't # just set :virtual => self.virtual in the initialization, # because sometimes the :virtual attribute is set *after* # :exported, in which case it clobbers :exported if :exported # is true. Argh, this was a very tough one to track down. virt = self.virtual || self.exported # First level of implicit iteration: build a resource for each # instance. This handles things like: # file { '/foo': owner => blah; '/bar': owner => blah } - @instances.collect { |instance| + @instances.collect do |instance| # Evaluate all of the specified params. - paramobjects = instance.parameters.collect { |param| - param.safeevaluate(scope) - } + paramobjects = instance.parameters.map { |param| param.safeevaluate(scope) } resource_titles = instance.title.safeevaluate(scope) # it's easier to always use an array, even for only one name resource_titles = [resource_titles] unless resource_titles.is_a?(Array) fully_qualified_type, resource_titles = scope.resolve_type_and_titles(type, resource_titles) # Second level of implicit iteration; build a resource for each # title. This handles things like: # file { ['/foo', '/bar']: owner => blah } - resource_titles.flatten.collect { |resource_title| + resource_titles.flatten.map do |resource_title| exceptwrap :type => Puppet::ParseError do resource = Puppet::Parser::Resource.new( - fully_qualified_type, resource_title, + fully_qualified_type, resource_title, :parameters => paramobjects, :file => self.file, :line => self.line, :exported => self.exported, :virtual => virt, :source => scope.source, :scope => scope, :strict => true ) if resource.resource_type.is_a? Puppet::Resource::Type resource.resource_type.instantiate_resource(scope, resource) end scope.compiler.add_resource(scope, resource) scope.compiler.evaluate_classes([resource_title], scope, false, true) if fully_qualified_type == 'class' resource end - } - }.flatten.reject { |resource| resource.nil? } + end + end.flatten.reject { |resource| resource.nil? } end end -end diff --git a/lib/puppet/parser/ast/resource_instance.rb b/lib/puppet/parser/ast/resource_instance.rb index ebfb17bf1..8594d6ddd 100644 --- a/lib/puppet/parser/ast/resource_instance.rb +++ b/lib/puppet/parser/ast/resource_instance.rb @@ -1,9 +1,6 @@ -require 'puppet/parser/ast/branch' - -class Puppet::Parser::AST - class ResourceInstance < Branch - # A simple container for a parameter for an object. Consists of a - # title and a set of parameters. +# A simple container for a parameter for an object. Consists of a +# title and a set of parameters. +# +class Puppet::Parser::AST::ResourceInstance < Puppet::Parser::AST::Branch attr_accessor :title, :parameters - end end diff --git a/lib/puppet/parser/ast/resourceparam.rb b/lib/puppet/parser/ast/resourceparam.rb index 04e945c52..891fbc63a 100644 --- a/lib/puppet/parser/ast/resourceparam.rb +++ b/lib/puppet/parser/ast/resourceparam.rb @@ -1,27 +1,26 @@ -require 'puppet/parser/ast/branch' +# The AST object for the parameters inside resource expressions +# +class Puppet::Parser::AST::ResourceParam < Puppet::Parser::AST::Branch + attr_accessor :value, :param, :add -class Puppet::Parser::AST - # The AST object for the parameters inside ResourceDefs and Selectors. - class ResourceParam < AST::Branch - attr_accessor :value, :param, :add - - def each - [@param,@value].each { |child| yield child } - end + def each + [@param, @value].each { |child| yield child } + end - # Return the parameter and the value. - def evaluate(scope) - value = @value.safeevaluate(scope) - return Puppet::Parser::Resource::Param.new( - :name => @param, - :value => value.nil? ? :undef : value, - :source => scope.source, :line => self.line, :file => self.file, - :add => self.add - ) - end + # Return the parameter and the value. + def evaluate(scope) + value = @value.safeevaluate(scope) + return Puppet::Parser::Resource::Param.new( + :name => @param, + :value => value.nil? ? :undef : value, + :source => scope.source, + :line => self.line, + :file => self.file, + :add => self.add + ) + end - def to_s - "#{@param} => #{@value.to_s}" - end + def to_s + "#{@param} => #{@value.to_s}" end end