diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-04-26 05:39:58 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-04-26 05:39:58 +0000 |
commit | 46ce36b175962ce89e06af4863d2c9dc50f2a02f (patch) | |
tree | aeff2dacfd81caddce54666e2d155e07b6ad09e8 /lib/puppet/parser/functions.rb | |
parent | ccc4d95dd28164f6f10763a758db85db0d48984c (diff) | |
download | puppet-46ce36b175962ce89e06af4863d2c9dc50f2a02f.tar.gz puppet-46ce36b175962ce89e06af4863d2c9dc50f2a02f.tar.xz puppet-46ce36b175962ce89e06af4863d2c9dc50f2a02f.zip |
Creating a simplistic, generic function framework in the parser, so it is now very easy to add new functions. There is a pretty crappy, hardwired distinction between functions that return values and those that do not, but I do not see a good way around it right now. Functions are also currently responsible for handling their own arity, although I have plans for fixing that.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@1134 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib/puppet/parser/functions.rb')
-rw-r--r-- | lib/puppet/parser/functions.rb | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/lib/puppet/parser/functions.rb b/lib/puppet/parser/functions.rb new file mode 100644 index 000000000..bc7e870ae --- /dev/null +++ b/lib/puppet/parser/functions.rb @@ -0,0 +1,103 @@ +# Grr +require 'puppet/parser/scope' + +module Puppet::Parser +module Functions + # A module for managing parser functions. Each specified function + # becomes an instance method on the Scope class. + + # Create a new function type. + def self.newfunction(name, ftype = :statement, &block) + @functions ||= {} + name = name.intern if name.is_a? String + + if @functions.include? name + raise Puppet::DevError, "Function %s already defined" % name + end + + # We want to use a separate, hidden module, because we don't want + # people to be able to call them directly. + unless defined? FCollection + eval("module FCollection; end") + end + + unless ftype == :statement or ftype == :rvalue + raise Puppet::DevError, "Invalid statement type %s" % ftype.inspect + end + + fname = "function_" + name.to_s + Puppet::Parser::Scope.send(:define_method, fname, &block) + #FCollection.send(:module_function,name) + + # Someday we'll support specifying an arity, but for now, nope + #@functions[name] = {:arity => arity, :type => ftype} + @functions[name] = {:type => ftype, :name => fname} + end + + # Determine if a given name is a function + def self.function(name) + name = name.intern if name.is_a? String + + if @functions.include? name + return @functions[name][:name] + else + return false + end + end + + # Determine if a given function returns a value or not. + def self.rvalue?(name) + name = name.intern if name.is_a? String + + if @functions.include? name + case @functions[name][:type] + when :statement: return false + when :rvalue: return true + end + else + return false + end + end + + # Include the specified classes + newfunction(:include) do |vals| + vals.each do |val| + if objecttype = lookuptype(val) + # It's a defined type + objecttype.safeevaluate( + :type => val, + :scope => self + ) + else + raise Puppet::ParseError, "Unknown class %s" % val + end + end + end + + # Tag the current scope with each passed name + newfunction(:tag) do |vals| + vals.each do |val| + # Some hackery, because the tags are stored by object id + # for singletonness. + self.setclass(val.object_id, val) + end + + # Also add them as tags + self.tag(*vals) + end + + # Test whether a given tag is set. This functions as a big OR -- if any of the + # specified tags are unset, we return false. + newfunction(:tagged, :rvalue) do |vals| + classlist = self.classlist + + if vals.find do |val| ! classlist.include?(val) end + return false + else + return true + end + end +end +end + +# $Id$ |