summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser/ast/hostclass.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet/parser/ast/hostclass.rb')
-rw-r--r--lib/puppet/parser/ast/hostclass.rb166
1 files changed, 33 insertions, 133 deletions
diff --git a/lib/puppet/parser/ast/hostclass.rb b/lib/puppet/parser/ast/hostclass.rb
index 44077983d..4a4664f0f 100644
--- a/lib/puppet/parser/ast/hostclass.rb
+++ b/lib/puppet/parser/ast/hostclass.rb
@@ -1,3 +1,5 @@
+require 'puppet/parser/ast/component'
+
class Puppet::Parser::AST
# The code associated with a class. This is different from components
# in that each class is a singleton -- only one will exist for a given
@@ -5,152 +7,50 @@ class Puppet::Parser::AST
class HostClass < AST::Component
@name = :class
+ # Are we a child of the passed class? Do a recursive search up our
+ # parentage tree to figure it out.
+ def child_of?(klass)
+ return false unless self.parentclass
+
+ if klass == self.parentclass
+ return true
+ else
+ return self.parentclass.child_of?(klass)
+ end
+ end
+
+ # Evaluate the code associated with this class.
def evaluate(hash)
scope = hash[:scope]
- objname = hash[:name]
args = hash[:arguments]
+
# Verify that we haven't already been evaluated
- # FIXME The second subclass won't evaluate the parent class
- # code at all, and any overrides will throw an error.
- if myscope = scope.lookupclass(self.object_id)
+ if scope.setclass?(self)
Puppet.debug "%s class already evaluated" % @type
-
- # Not used, but will eventually be used to fix #140.
- if myscope.is_a? Puppet::Parser::Scope
- unless scope.object_id == myscope.object_id
- #scope.parent = myscope
- end
- end
return nil
end
- # Set the class before we do anything else, so that it's set
- # during the evaluation and can be inspected.
- scope.setclass(self.object_id, @type)
-
- origscope = scope
-
- # Default to creating a new context
- newcontext = true
-
- # If we've got a parent, then we pass it the original scope we
- # received. It will get passed all the way up to the top class,
- # which will create a subscope and pass that subscope to its
- # subclass.
- if @parentscope = self.evalparent(
- :scope => scope, :arguments => args, :name => objname
- )
- if @parentscope.is_a? Puppet::TransBucket
- raise Puppet::DevError, "Got a bucket instead of a scope"
- end
-
- # Override our scope binding with the parent scope
- # binding.
- scope = @parentscope
-
- # But don't create a new context if our parent created one
- newcontext = false
- end
-
- # Just use the Component evaluate method, but change the type
- # to our own type.
- result = super(
- :scope => scope,
- :arguments => args,
- :type => @type,
- :name => objname, # might be nil
- :newcontext => newcontext,
- :asparent => hash[:asparent] || false # might be nil
- )
-
- # Now set the class again, this time using the scope. This way
- # we can look up the parent scope of this class later, so we
- # can hook the children together.
- scope.setscope(self.object_id, result)
-
- # This is important but painfully difficult. If we're the top-level
- # class, that is, we have no parent classes, then the transscope
- # is our own scope, but if there are parent classes, then the topmost
- # parent's scope is the transscope, since it contains its code and
- # all of the subclass's code.
- transscope ||= result
-
- if hash[:asparent]
- # If we're a parent class, then return the scope object itself.
- return result
- else
- transscope = nil
- if @parentscope
- transscope = @parentscope
- until transscope.parent.object_id == origscope.object_id
- transscope = transscope.parent
- end
+ if @parentclass
+ if pklass = self.parentclass
+ pklass.safeevaluate :scope => scope
else
- transscope = result
+ parsefail "Could not find class %s" % @parentclass
end
-
- # But if we're the final subclass, translate the whole scope tree
- # into TransObjects and TransBuckets.
- return transscope.to_trans
end
- end
- # Evaluate our parent class. Parent classes are evaluated in the
- # exact same scope as the children. This is maybe not a good idea
- # but, eh.
- #def evalparent(scope, args, name)
- def evalparent(hash)
- scope = hash[:scope]
- args = hash[:arguments]
- name = hash[:name]
- if @parentclass
- #scope.warning "parent class of %s is %s" %
- # [@type, @parentclass.inspect]
- parentobj = nil
+ # Set the class before we do anything else, so that it's set
+ # during the evaluation and can be inspected.
+ scope.setclass(self)
- begin
- parentobj = scope.lookuptype(@parentclass)
- rescue Puppet::ParseError => except
- except.line = self.line
- except.file = self.file
- raise except
- rescue => detail
- error = Puppet::ParseError.new(detail)
- error.line = self.line
- error.file = self.file
- raise error
- end
- unless parentobj
- error = Puppet::ParseError.new(
- "Could not find parent '%s' of '%s'" %
- [@parentclass,@name])
- error.line = self.line
- error.file = self.file
- raise error
- end
+ unless hash[:nosubscope]
+ scope = subscope(scope)
+ end
- # Verify that the parent and child are of the same type
- unless parentobj.class == self.class
- error = Puppet::ParseError.new(
- "Class %s has incompatible parent type, %s vs %s" %
- [@type, parentobj.class, self.class]
- )
- error.file = self.file
- error.line = self.line
- raise error
- end
- # We don't need to pass the type, because the parent will just
- # use its own type. Specify that it's being evaluated as a parent,
- # so that it returns the scope, not a transbucket.
- return parentobj.safeevaluate(
- :scope => scope,
- :arguments => args,
- :name => name,
- :asparent => true,
- :collectable => self.collectable
- )
+ # Now evaluate our code, yo.
+ if self.code
+ return self.code.evaluate(:scope => scope)
else
- return false
+ return nil
end
end
@@ -158,7 +58,7 @@ class Puppet::Parser::AST
@parentclass = nil
super
end
-
end
-
end
+
+# $Id$