summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser/ast
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-08-22 23:34:40 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-08-22 23:34:40 +0000
commit4151fd59ef6490c875140a874c0a13c5d3f311aa (patch)
treeceb265c6fdc52fa46889737263d2d5d8c3819a41 /lib/puppet/parser/ast
parent1b2ee4bb9d9fef44bdf8217f45d6893b7609a432 (diff)
downloadpuppet-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.rb2
-rw-r--r--lib/puppet/parser/ast/classdef.rb6
-rw-r--r--lib/puppet/parser/ast/compdef.rb27
-rw-r--r--lib/puppet/parser/ast/component.rb42
-rw-r--r--lib/puppet/parser/ast/hostclass.rb2
-rw-r--r--lib/puppet/parser/ast/objectdef.rb92
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 [