diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-08-22 23:34:40 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-08-22 23:34:40 +0000 |
commit | 4151fd59ef6490c875140a874c0a13c5d3f311aa (patch) | |
tree | ceb265c6fdc52fa46889737263d2d5d8c3819a41 /lib/puppet/parser/ast | |
parent | 1b2ee4bb9d9fef44bdf8217f45d6893b7609a432 (diff) | |
download | puppet-4151fd59ef6490c875140a874c0a13c5d3f311aa.tar.gz puppet-4151fd59ef6490c875140a874c0a13c5d3f311aa.tar.xz puppet-4151fd59ef6490c875140a874c0a13c5d3f311aa.zip |
Committing definition inheritance. I have not yet written tests yet, but my last commit pretty seriously broke some things without me realizing it, so I wanted to get this in.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@1484 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib/puppet/parser/ast')
-rw-r--r-- | lib/puppet/parser/ast/branch.rb | 2 | ||||
-rw-r--r-- | lib/puppet/parser/ast/classdef.rb | 6 | ||||
-rw-r--r-- | lib/puppet/parser/ast/compdef.rb | 27 | ||||
-rw-r--r-- | lib/puppet/parser/ast/component.rb | 42 | ||||
-rw-r--r-- | lib/puppet/parser/ast/hostclass.rb | 2 | ||||
-rw-r--r-- | lib/puppet/parser/ast/objectdef.rb | 92 |
6 files changed, 129 insertions, 42 deletions
diff --git a/lib/puppet/parser/ast/branch.rb b/lib/puppet/parser/ast/branch.rb index 941c00a68..5a4d323f5 100644 --- a/lib/puppet/parser/ast/branch.rb +++ b/lib/puppet/parser/ast/branch.rb @@ -45,3 +45,5 @@ class Puppet::Parser::AST end end end + +# $Id$ diff --git a/lib/puppet/parser/ast/classdef.rb b/lib/puppet/parser/ast/classdef.rb index 0a6a86816..cb66b3a8a 100644 --- a/lib/puppet/parser/ast/classdef.rb +++ b/lib/puppet/parser/ast/classdef.rb @@ -5,7 +5,9 @@ class Puppet::Parser::AST # but classes are always singletons -- only one can exist on a given # host. class ClassDef < AST::CompDef - attr_accessor :parentclass + def self.genclass + AST::HostClass + end def each if @parentclass @@ -18,7 +20,7 @@ class Puppet::Parser::AST end # Store our parse tree according to type. - def evaluate(hash) + def disabled_evaluate(hash) scope = hash[:scope] type = @type.safeevaluate(:scope => scope) #args = @args.safeevaluate(:scope => scope) diff --git a/lib/puppet/parser/ast/compdef.rb b/lib/puppet/parser/ast/compdef.rb index e5758d6f0..696e178e1 100644 --- a/lib/puppet/parser/ast/compdef.rb +++ b/lib/puppet/parser/ast/compdef.rb @@ -9,7 +9,11 @@ class Puppet::Parser::AST # encounter an error if the component is instantiated more than # once. class CompDef < AST::Branch - attr_accessor :type, :args, :code, :keyword, :scope + attr_accessor :type, :args, :code, :keyword, :scope, :parentclass + + def self.genclass + AST::Component + end def each [@type,@args,@code].each { |child| yield child } @@ -18,17 +22,21 @@ class Puppet::Parser::AST # Store the parse tree. def evaluate(hash) scope = hash[:scope] - type = @type.safeevaluate(:scope => scope) - args = @args.safeevaluate(:scope => scope) + arghash = {:code => @code} + arghash[:type] = @type.safeevaluate(:scope => scope) + + if @args + arghash[:args] = @args.safeevaluate(:scope => scope) + end + + if @parentclass + arghash[:parentclass] = @parentclass.safeevaluate(:scope => scope) + end begin - comp = AST::Component.new( - :type => type, - :args => args, - :code => @code - ) + comp = self.class.genclass.new(arghash) comp.keyword = self.keyword - scope.settype(type, comp) + scope.settype(arghash[:type], comp) rescue Puppet::ParseError => except except.line = self.line except.file = self.file @@ -44,6 +52,7 @@ class Puppet::Parser::AST def initialize(hash) @parentclass = nil + @args = nil # Set a default keyword @keyword = "define" diff --git a/lib/puppet/parser/ast/component.rb b/lib/puppet/parser/ast/component.rb index 317c8ced5..4d930f6a5 100644 --- a/lib/puppet/parser/ast/component.rb +++ b/lib/puppet/parser/ast/component.rb @@ -10,14 +10,18 @@ class Puppet::Parser::AST # The class name @name = :component - attr_accessor :type, :args, :code, :scope, :keyword, :collectable + attr_accessor :type, :args, :code, :scope, :keyword + attr_accessor :collectable, :parentclass + + # These are retrieved when looking up the superclass + attr_accessor :name, :arguments #def evaluate(scope,hash,objtype,objname) def evaluate(hash) origscope = hash[:scope] objtype = hash[:type] - objname = hash[:name] - arguments = hash[:arguments] || {} + @name = hash[:name] + @arguments = hash[:arguments] || {} @collectable = hash[:collectable] @@ -29,7 +33,7 @@ class Puppet::Parser::AST #end scope = pscope.newscope( :type => @type, - :name => objname, + :name => @name, :keyword => self.keyword ) newcontext = hash[:newcontext] @@ -48,8 +52,8 @@ class Puppet::Parser::AST # we are scope.tag(@type) - unless objname.nil? - scope.tag(objname) + unless @name.nil? + scope.tag(@name) end # define all of the arguments in our local scope @@ -59,15 +63,15 @@ class Puppet::Parser::AST # FIXME This should probably also require each parent # class's arguments... self.args.each { |arg, default| - unless arguments.include?(arg) + unless @arguments.include?(arg) if defined? default and ! default.nil? - arguments[arg] = default + @arguments[arg] = default #Puppet.debug "Got default %s for %s in %s" % - # [default.inspect, arg.inspect, objname.inspect] + # [default.inspect, arg.inspect, @name.inspect] else error = Puppet::ParseError.new( "Must pass %s to %s of type %s" % - [arg.inspect,objname,@type] + [arg.inspect,@name,@type] ) error.line = self.line error.file = self.file @@ -79,10 +83,9 @@ class Puppet::Parser::AST # Set each of the provided arguments as variables in the # component's scope. - arguments["name"] = objname - arguments.each { |arg,value| + @arguments.each { |arg,value| begin - scope.setvar(arg,arguments[arg]) + scope.setvar(arg,@arguments[arg]) rescue Puppet::ParseError => except except.line = self.line except.file = self.file @@ -100,8 +103,14 @@ class Puppet::Parser::AST end } + unless @arguments.include? "name" + scope.setvar("name",@name) + end + # Now just evaluate the code with our new bindings. - self.code.safeevaluate(:scope => scope) + scope.inside(self) do + self.code.safeevaluate(:scope => scope) + end # If we're being evaluated as a parent class, we want to return the # scope, so it can be overridden and such, but if not, we want to @@ -134,9 +143,10 @@ class Puppet::Parser::AST return true elsif defined? @parentclass and @parentclass # Else, check any existing parent - parent = @scope.lookuptype(@parentclass) - if parent and parent != [] + if parent = @scope.lookuptype(@parentclass) and parent != [] return parent.validarg?(param) + elsif builtin = Puppet::Type.type(@parentclass) + return builtin.validattr?(param) else raise Puppet::Error, "Could not find parent class %s" % @parentclass diff --git a/lib/puppet/parser/ast/hostclass.rb b/lib/puppet/parser/ast/hostclass.rb index f66078d7a..44077983d 100644 --- a/lib/puppet/parser/ast/hostclass.rb +++ b/lib/puppet/parser/ast/hostclass.rb @@ -4,9 +4,7 @@ class Puppet::Parser::AST # node. class HostClass < AST::Component @name = :class - attr_accessor :parentclass - #def evaluate(scope,hash,objtype,objname) def evaluate(hash) scope = hash[:scope] objname = hash[:name] diff --git a/lib/puppet/parser/ast/objectdef.rb b/lib/puppet/parser/ast/objectdef.rb index 7ab46a9d8..63577b60d 100644 --- a/lib/puppet/parser/ast/objectdef.rb +++ b/lib/puppet/parser/ast/objectdef.rb @@ -33,6 +33,13 @@ class Puppet::Parser::AST # Get our type and name. objtype = @type.safeevaluate(:scope => scope) + if objtype == "super" + objtype = supertype() + @subtype = true + else + @subtype = false + end + # If the type was a variable, we wouldn't have typechecked yet. # Do it now, if so. unless @checked @@ -62,6 +69,11 @@ class Puppet::Parser::AST hash[ary[0]] = ary[1] } + # Now collect info from our parent. + if @subtype + parentname = supersetup(hash) + end + objnames = [nil] # Determine our name if we have one. if self.name @@ -71,21 +83,26 @@ class Puppet::Parser::AST objnames = [objnames] end else - # See if they specified the name as a parameter instead of as a - # normal name (i.e., before the colon). - unless object # we're a builtin - if objclass = Puppet::Type.type(objtype) - namevar = objclass.namevar + if parentname + objnames = [parentname] + else + # See if they specified the name as a parameter instead of + # as a normal name (i.e., before the colon). + unless object # we're a builtin + if objclass = Puppet::Type.type(objtype) + namevar = objclass.namevar - tmp = hash["name"] || hash[namevar.to_s] + tmp = hash["name"] || hash[namevar.to_s] - if tmp - objnames = [tmp] + if tmp + objnames = [tmp] + end + else + # this should never happen, because we've already + # typechecked, but it's no real problem if it does + # happen. We just end up with an object with no + # name. end - else - # this should never happen, because we've already - # typechecked, but it's no real problem if it does happen. - # We just end up with an object with no name. end end end @@ -130,7 +147,7 @@ class Puppet::Parser::AST @checked = false super - self.typecheck(@type.value) + #self.typecheck(@type.value) end # Verify that all passed parameters are valid @@ -212,6 +229,55 @@ class Puppet::Parser::AST end end + def supercomp + unless defined? @supercomp + if @scope and comp = @scope.inside + @supercomp = comp + else + error = Puppet::ParseError.new( + "'super' is only valid within definitions" + ) + error.line = self.line + error.file = self.file + raise error + end + end + @supercomp + end + + # Take all of the arguments of our parent and add them into our own, + # without overriding anything. + def supersetup(hash) + comp = supercomp() + + # Now check each of the arguments from the parent. + comp.arguments.each do |name, value| + unless hash.has_key? name + hash[name] = value + end + end + + # Return the parent name, so it can be used if appropriate. + return comp.name + end + + # Retrieve our supertype. + def supertype + unless defined? @supertype + if parent = supercomp.parentclass + @supertype = parent + else + error = Puppet::ParseError.new( + "%s does not have a parent class" % comp.type + ) + error.line = self.line + error.file = self.file + raise error + end + end + @supertype + end + # Print this object out. def tree(indent = 0) return [ |