summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser/functions.rb
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-04-26 05:39:58 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-04-26 05:39:58 +0000
commit46ce36b175962ce89e06af4863d2c9dc50f2a02f (patch)
treeaeff2dacfd81caddce54666e2d155e07b6ad09e8 /lib/puppet/parser/functions.rb
parentccc4d95dd28164f6f10763a758db85db0d48984c (diff)
downloadpuppet-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.rb103
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$